Приветствую Вас, Гость
Главная » 2010 » Октябрь » 19 » продолжение
17:41
продолжение
4.5. Интерфейс управляющих сообщений MCI

Более тесное и гибкое взаимодействие между разработанным с использованием языка С/C++ приложением и устройством мультимедиа можно достичь при использовании интерфейса управляющих сообщений; при этом используется функция mciSendCommand, которой в качестве второго параметра передается код соответствующего управляющего сообщения.
Прототип функции mciSendCommand (см. файл mmsystem.h) приведен ниже

DWORD
mciSendCommand(UINT wDeviceID, // идентификатор устройства
UINT wMessage, // код сообщения
DWORD dwParam1, // флаги команды
DWORD dwParam2); // указатель на структуру
// параметров

Здесь wDeviceID - идентификатор управляемого устройства (для сообщения MCI_OPEN не используется, т.к. идентификатор создается в результате выполнения именно этой команды), wMessage - код сообщения, dwParam1 - флаги команды, dwParam2 - указатель на структуру параметров (формат коей зависит от кода сообщения).
Функция mciSendCommand возвращает нуль при нормальном завершении или код ошибки (текстовое описание ошибок можно получить с помощью функции mciGetErrorString, передав ей этот код в качестве параметра).
Нижеприведенный фрагмент кода открывает устройство ‘waveaudio’ (будет открыт файл, путь к которой записан в переменной szFileAudio)

// определение переменных
MCI_OPEN_PARMS mciOpen;
DWORD dwFlags, dwRc;

// заполнение полей структуры mciOpen
mciOpen.lpstrDeviceID = (LPSTR) "waveaudio";
mciOpen.lpstrElementName = (LPSTR) szFileName;
mciOpen.dwCallback = 0;
mciOpen.wDeviceID = 0;
mciOpen.wReserved = 0;
mciOpen.lpstrAlias = NULL;
dwFlags = MCI_OPEN_TYPE | MCI_OPEN_ELEMENT | MCI_WAIT;

// собственно открытие файла с помощью функции mciSendCommand
dwRc = mciSendCommand(0, MCI_OPEN, dwFlags,
(DWORD) (LPVOID) &mciOpen);

После выполнения данного фрагмента в переменную dwrc будет занесен код результата завершения; при успешном выполнении в поле wDeviceID структуры mciOpen заносится идентификатор открытого устройства.
В следующем примере закрывается мультимедиа - устройство с определенным ранее идентификатором mciOpen.wDeviceID

// определение переменных
MCI_GENERIC_PARMS mciGen;
DWORD dwRc;

// заполнение полей структуры mciOpen
mciGen.dwCallback = 0;

// собственно выполнение функции mciSendCommand
dwRc = mciSendCommand(mciOpen.wDeviceID, MCI_CLOSE, MCI_WAIT,
(DWORD) (LPMCI_GENERIC_PARMS) &mciGen);

В работе [6] приведен полный С-код приложения MCIWAVER, демонстрирующего использование интерфейса управляющих сообщений MCI для воспроизведения звуковых WAV-файлов; использование этого интерфейса для управления CD ROM и проигрывания MIDI-файлов приведено также в подразделах 3.7.2 и 3.8.2 данной работы.

3.6. Интерфейс низкого уровня

Программным интерфейсом низкого уровня удобно пользоваться в случае необходимости иметь непосредственный доступ к буферам, содержащим мультимедиа-данные; для случая работы со звуковыми файлами интерфейс обеспечивается несколькими функциями, имеющими префикс wave (например, waveInOpen, waveOutOpen, waveOutWrite, waveAddBuffer и т.д., причем функции экспортируются из файла mmsystem.dll).
Общая последовательность использования интерфейса низкого уровня заключается в чтении и проверке формата заголовка WAV-файла, открытия устройства вывода с указанием конкретного формата звуковых данных, блочного чтения данных WAV-файла, подготовки специальной функцией для вывода и передаче данных драйверу устройства вывода (драйвер выводит их на звуковой адаптер). При этом приложение должно самостоятельно подготовит блоки данных в оперативной памяти.
Запись звуковых данных осуществляется аналогично. В первую очередь открывается устройство ввода (ему указывается формат звуковых данных), далее заказывается один или несколько блоков памяти (они подготавливаются для ввода путем вызова специальной функции), подготовленные таким образом блоки по мере необходимости передаются драйверу устройства ввода (драйвер заполняет их записанными звуковыми данными). С целью сохранения записанных данных в WAV-файле приложение должно сформировать и записать в файл заголовок WAV-файла и звуковые данные из подготовленных и заполненных драйвером устройства ввода блоков памяти.
Программный интерфейс низкого уровня требует внимательного учета всех деталей процесса записи и воспроизведения (в отличие от интерфейса MCI, где многие параметры принимаются по умолчанию). Как всегда, большая трудоемкость программирования интерфейса низкого уровня компенсируется повышенной гибкостью и возможностью работы со звуковыми данными в реальном времени.

3.6.1. Формат wav-файла, информация о RIFF-структуре файлов

Имеющие отношение к мультимедиа данные (звук, видео и др.) хранятся в файлах т.н. RIFF-формата (Resource Interchange File Format - формат файла для обмена ресурсами). Как содержащие звук WAV-файлы, так и AVI-файлы, содержащие видеоинформацию, имеют формат RIFF.
Файл формата RIFF содержит вложенные фрагменты (chunk’s); внешний фрагмент состоит из заголовка и области данных (рис. 3.9).

Рис. 3.9. Внешний фрагмент RIFF
Первое двойное слово заголовка содержит четырехбуквенный код FOURCC, идентифицирующий хранящиеся во фрагменте данные. Второе двойное слово заголовка представляет собой размер области данных в байтах (без учета размера самого заголовка).
Область данных имеет переменную длину, однако она должна быть выравнена на границу слова (при необходимости дополняется в конце нулевым байтом до целого числа слов).
Важно понять, что формат RIFF не описывает конкретный формат данных; практически файл в RIFF-формате может содержать любые мультимедиа-данные, причем формат конкретных данных зависит от типа этих данных (RIFF является скорее стандартом описания контейнера данных).
Обозначенная на рис. 3.9 как ‘Данные’ область может содержать внутри себя другие фрагменты. Для содержащего звуковые данные файла (WAV-файл) эта область содержит идентификатор данных ‘WAVE’, фрагмент формата звуковых данных ‘fmt’ (три символа ‘fmt’ и пробел в конце), а также фрагмент звуковых данных (рис. 4.10).


Рис. 3.10. Формат WAV-файла (в структуре RIFF)

Файл может дополнительно содержать фрагменты других типов, поэтому не следует предполагать, что заголовок WAV-файла имеет фиксированный формат. Например, в формате могут присутствовать фрагменты ‘LIST’ или ‘ABOUT’, содержащие информацию о правах копирования и описание самого мультимедиа-файла.
Означенная на рис. 3.2 как ‘Формат данных’ область описывает звуковые данные. Формат этой области для файлов PCM (записанных с использованием импульсно-кодовой модуляции) соответствуют структуре PCMWAVEFORMAT, определенной в файле mmsystem.h следующим образом

typedef struct pcmwaveformat_tag
{
WAVEFORMAT wf;
WORD wBitsPerSample;
} PCMWAVEFORMAT;

typedef PCMWAVEFORMAT *PPCMWAVEFORMAT;
typedef PCMWAVEFORMAT NEAR *NPPCMWAVEFORMAT;
typedef PCMWAVEFORMAT FAR *LPPCMWAVEFORMAT;

Структура WAVEFORMAT описана в файле mmsystem.h следующим образом

typedef struct waveformat_tag
{
WORD wFormat Tag; // тип формата
WORD nChannels; // количество каналов (моно или стерео)
DWORD nSanplesPerSec; // частота дискретизации
DWORD nAvgBytesPerSec; // скорость потока данных
WORD nBlockAlign; // выравнивание блока данных
} WAVEFORMAT;

typedef WAVEFORMAT *PWAVEFORMAT;
typedef WAVEFORMAT NEAR *NPWAVEFORMAT;
typedef WAVEFORMAT FAR *LPWAVEFORMAT;

Поле wFormatTag описывает тип формата звуковых данных (для поддерживаемой стандартной библиотекой mmsystem.dll метода импульсно-кодовой модуляции PCM в этом поле должно находиться определенное в файле mmsystem.h значение WAVE_FORMAT_PCM)

#define WAVE_FORMAT_PCM 1

Поле nChannels содержит количество каналов, в нем могут находиться значения 1 (моно) или 2 (стерео).
В поле nSamplesPerSec записывается частота дискретизации (количество выборок сигнала в секунду). В этом поле могут находиться стандартные (11025 kГц, 22050 kГц или 44100 kГц) либо нестандартные значения (такие как 5000 kГц или 4400 kГц), однако не все драйверы звуковых адаптеров могут корректно работать с нестандартными частотами дискретизации.
Поле nAvgBytePerSec содержит среднюю скорость потока данных (количество байт в секунду, передаваемых драйверу устройства или получаемых от него). Эта информация может использоваться приложением для оценки размера необходимого для размещения звуковых данных буфера (например, для монофонического сигнала с дискретизацией 8 бит значение скорости численно совпадает со значением частоты дискретизации, для стереофонического сигнала с дискретностью 8 бит она вдвое выше). Точное значение величины nAvgBytePerSec рассчитывается по формуле

nAvgBytePerSec=(nChannel nSamples wBitsPerample) / 8

В поле nBlockAlign находится информация о выравнивании блока в байтах, причем

nBlockAlign=(nChannels wBitsPerSample) / 8

Поле wBitPerSample определяет дискретность сигнала (количество бит, используемое для одной выборки сигнала); обычно используются значения 8 или 16.
Формат самих звуковых данных зависит от количества каналов и от дискретности.
Для монофонического сигнала с дискретностью 8 бит звуковые данные представляют собой массив однобайтовых значений, каждое из которых является выборкой сигнала.
Для стереофонического сигнала с дискретностью 8 бит звуковые данные имеют формат массива двухбайтовых слов, причем младший байт слова соответствует левому каналу, а старший - правому.
Формат звуковых данных с дискретностью 16 бит выглядит аналогично (для монофонического сигнала данные хранятся в массиве 16-битовых слов; для стереофонического используется массив двойных слов, причем младшему слову соответствует левый канал, а старшему - правый).
Диапазон изменения значений выборок определяется дискретизацией. Для 8-битовых данных диапазон составляет от 0 до 255 (0xff), причем отсутствию сигнала (полная тишина) соответствует значение 128 (0x80); для 16-битовых значений диапазон изменения составляет от -32768 (-0x8000) до 32767 (0x7fff), отсутствию сигнала соответствует значение 0.

3.6.2. Функции для работы с файлами

Библиотека mmsystem.dll содержит удобные функции, специально предназначенные для работы с файлами RIFF-формата (хотя можно пользоваться стандартные функции ввода - вывода или функции семейства _hread и _hwrite). Специализированные функции успешно работают с блоками памяти большого размера (более 64 Кбайт), так как звуковые данные редко помещаются в одном сегменте памяти.
Открытие файла совершается функцией mmioOpen. Эта функция может открыть файл для буферизованного или небуферизованного ввода или для работы с файлом в оперативной памяти (полностью возможности указанной функции приведены в поставляемой совместно с MS SDK документации). Ниже приведен прототип функции mmioOpen

HMMIO
mmioOpen(LPSTR szFilename,
LPMMIOINFO lpmmioinfo,
DWORD dwOpenFlags);

Здесь szFilename - дальний указатель на текстовую строку, содержащую путь к открываемому файлу, lpmmioinfo - указатель на содержащую дополнительные параметры для операции открытия файла структуру MMIOINFO (может быть задан как NULL), dwOpenFlags - определяющие режим открытия файла флаги.
При успехе функция mmioOpen возвращает (нестандартный) идентификатор открытого файла, который можно использовать только в функциях с префиксом mmio. Код ошибки можно определить, анализируя поле wErrorRet структуры MMIOINFO.
Формат структуры MMINFO описан в файле mmsystem.h как

typedef struct _MMIOINFO
{
// поля общего назначения
DWORD dwFlags; // общий флаг состояния
FOURCC fccIOProc; // код идентификации процедуры
// ввода - вывода
LPMMIOPROC pIOProc; // указатель на процедуру
// ввода - вывода
UINT wErrorRet; // код завершения
HTASK htask; // идентификатор локальной процедуры
// ввода - вывода
// поля для буферизированного ввода - вывода
LONG ccBuffer; // размер буфера (или 0L)
HPSTR pchBuffer; // указатель на буфер (или NULL)
HPSTR pchNext; // указатель на следующий байт при
// операциях чтении или записи
HPSTR pchEndRead; // указ.на последний прочитанный байт
HPSTR pchEndWrite; // указ.на последний записанный байт
LONG lBufOffset; // дискового смещение начала буфера
// поля для процедур ввода - вывода
LONG lDiskOffset; // дисковое смещение для следующей
// операции чтения или записи
DWORD adwInfo[3]; // дополнительные данные
// для типа MMIOPROC
// прочие поля
DWORD dwReserved1; // зарезервировано
DWORD dwReserved2; // зарезервировано
HMMIO hmmio; // идентификатор открытого файла
} MMIOINFO;

typedef MMIOINFO *PMMIOINFO:
typedef MMIOINFO NEAR *NPMMIOINFO;
typedef MMIOINFO FAF *LPMMIOINFO;

Структура MMIOINFO дает возможность задавать многочисленные способы работы с файлами - можно использовать файлы в памяти, можно определить собственную процедуру для выполнения нестандартного ввода или вывода или работать с открытыми средствами MS-DOS идентификаторами файлов. В простейших случаях можно указать второй параметр функции mmioOpen как NULL и не использовать структуру MMIOINFO вообще

hmmio=mmioOpen((LPSTR)lpszFilename, NULL,
MMIO_READ | MMIO_ALLOCBUF);

Последний параметр функции mmioOpen предназначен для определения режима открытия файла в виде логической комбинации ИЛИ отдельных флагов, ниже приведен их список

Идентификатор флага Описание режима открытия файла
MMIO_READ Чтение
MMIO_WRITE Запись
MMIO_READWRITE Чтение и запись
MMIO_CREATE Создание нового файла (если файл с таким именем уже существует, он обрезается до нулевой длины)
MMIO_DELETE Удаление файла (если удаление выполнено корректно, возвращается TRUE, в противном случае - FALSE)
MMIO_PARSE Создание текстовой строки, содержащей полный путь к файлу на основе пути, переданного функции через параметр szFilename; результат замещает буфер szFilename
MMIO_EXIST Определяет существование указанного файла (при существовании создается текстовая строка, содержащая полный путь к файлу)
MMIO_ALLOCBUF Файл открывается для буферизованного ввода - вывода (по умолчанию размер буфера равен 8 Кбайт; изменить размер буфера можно заданием его в поле cchBuffer структуры MMIOINFO)
MMIO_COMPAT Файл открывается в режиме совместимости (файл может быть открыт несколько раз)
MMIO_EXCLUSIVE Файл будет открыт в монопольном режиме
MMIO_DENYWRITE Запрещает другим приложения открывать этот файл на запись
MMIO_DENYREAD Запрещает другим приложения открывать этот файл на чтение
MMIO_DENYNONE Другие приложения могут открывать файл и на запись, и на чтение
MMIO_GETTEMP Создание текстовой строки для открытия временного файла (строка записывается в буфер, адрес которого передается через первый параметр функции; собственно открытие файла не выполняется)

В нижеследующем фрагменте кода выполняется создание файла, открываемого и на чтение, и на запись

hFile=mmioOpen(szFileName, NULL,
MMIO_CREATE | MMIO_READWRITE);

Закрытие файла, открытого функцией mmioOpen (после завершения работы с ним) должно осуществляться функцией mmioClose.

UINT
mmioClose(HMMIO hmmio, UINT wFlags);

Параметр hmmio - полученный ранее с помощью функции mmioOpen идентификатор открытого файла, wFlags - определяющие режим закрытия файла флаги (можно указать флаг MMIO_FHOPEN для закрытия файла, открытого средствами MS-DOS). При успехе возвращается нулевое значение, в противном случае - код ошибки.
Запись в открытый с помощью функции mmioOpen файл осуществляется с помощью функции mmioWrite. Эта функция позволяет за единичный вызов записать в файл блок данных размером большим 64 Кбайт; после записи осуществляется перемещение текущей позиции в файле вперед на количество записанных байт.

LONG
mmioWrite(HMMIO hmmio, // идентификатор открытого файла
HPSTR hpBuff, // указатель на буфер данных
LONG dwBytes); // размер буфера

При успехе функция mmioWrite возвращает количество записанных байт или -1 при возникновении ошибки.
Чтение из открытого с помощью функции mmioOpen файла выполняется функцией mmioRead, также позволяющей за один вызов прочитать блок данных размером более 64 Кбайт; после чтения осуществляется перемещение текущей позиции в файле вперед на количество прочитанных байт.

LONG
mmioRead(HMMIO hmmio, // идентификатор открытого файла
HPSTR hpBuff, // указатель на буфер данных
LONG dwBytes); // размер буфера

При успехе функция mmioRead возвращает количество прочитанных байт или -1 при возникновении ошибки; при достижении конца файла возвращается нулевое значение.
Позиционирование в открытом с помощью функции mmioOpen файла выполняется функцией mmioSeek.

LONG
mmioSeek(HMMIO hmmio, // идентикатор открытого файла
LONG dwOffset, // смещение для текущей позиции
int nOrigin); // код отсчета смещения

Величины dwOffset и nOrigin интерпретируются обычным для файловых операций в языке С образом. При успехе функция mmioSeek возвращает новое смещение текущей позиции в файле (от начала файла, в байтах) или -1 при возникновении ошибки.
Для работы с RIFF-файлами в библиотеке mmsystem.dll присутствуют специальные функции, сильно облегчающие работу с фрагментами RIFF-файлов (хотя можно использовать обычные функции ввода - вывода, в том числе описанные выше). Эти специализированные функции помогают заполнить четырехбайтовый идентификатор фрагмента, найти в файле нужный фрагмент и установить на него (или за него) текущую позицию файла, создать новый фрагмент в новом файле.
При формировании нового фрагмента удобна функция mmioFOURCC, позволяющая создать четырехбуквенный код фрагмента из отдельных букв

FOURCC
mmioFOURCC(CHAR ch0, // первая буква кода
CHAR ch1, // вторая - . - . - . -
CHAR ch2, // третья - . - . - . -
CHAR ch3); // четвертая - . - . - . -

Здесь параметры ch0, ch1, ch2, ch3 - коды букв, образующих четырехбуквенный код; функция возвращает значение сформированного четырехбуквенного идентификатора, который можно использовать при формировании нового фрагмента.
Нетрудно догадаться, что функция mmioFOURCC реализована в виде макроса, упаковывающего четыре байта в двойное слово

#define mmioFOURCC(ch0,ch1,ch2,ch3) \
((DWORD) (BYTE) (ch0) | \
((DWORD) (BYTE) (ch1) << 8) | \
((DWORD) (BYTE) (ch2) << 16) | \
((DWORD) (BYTE) (ch3) << 24))

Для форматирования, например, идентификатора "WAVE" можно воспользоваться вышеописанным макросом следующим образом

FOURCC fourccWaveID;
fourccWaveID=mmmioFOURCC(‘W’, ‘A’, ‘V’, ‘E’);

С помощью функции mmioStringToFOURCC можно сформировать четырехбуквенный идентификатор не из отдельных букв, а из строки символов.

FOURCC
mmioStringToFOURCC(LPCSTR szString, UINT wFlags);

Здесь szString - указатель на преобразуемую строку, закрытую двоичным нулем, при wFlags=MMIO_TOUPPER все символы строки будут преобразованы в заглавные. Функция mmioStringToFOURCC возвращает значение четырехбуквенного идентификатора, могущего быть использованным при формировании нового фрагмента; пример использования функции приведен ниже

FOURCC fourccWaveID;
fourccWaveID=mmioStringToFOURCC("wave", MMIO_TOUPPER);

Для создания нового фрагмента в RIFF-формате удобно использовать функцию mmioCreateChunk; новый фрагмент создается в текущей позиции файла, предварительно открытого с помощью функции mmioOpen

UINT
mmioCreateChunk(HMMIO hmmio, // идентификатор файла
LPMMCKINFO lpck, // указатель на
// структуру MMCKINFO
UINT wFlags); // тип фрагмента

При wFlags=MMIO_CREATERIFF создается фрагмент "RIFF", при wFlags=MMIO_CREATELIST создается фрагмент "LIST". При нормальном завершении работы функция возвращает нулевое значение, в противном случае - код ошибки.
Структура MMCKINFO и указатели на нее определены в файле mmsystem.h как

typedef struct _MMCKINFO
{
FOURCC ckid;
DWORD cksize;
FOURCC fccType;
DWORD dwDataOffset;
DWORD dwFlags;
} MMCKINFO;

typedef MMCKINFO *PMMCKINFO;
typedef MMCKINFO NEAR *NPMMCKINFO:
typedef MMCKINFO FAR *LPMMCKINFO;

В нижеприведенной таблице приведено описание отдельных полей этой структуры

Идентификатор поля Описание
ckid Код, соответствующий четырехбуквенному идентификатору фрагмента
cksize Размер фрагмента в байтах без учета идентификатора фрагмента; поля длины фрагмента и дополнительных байтов выравнивания, которые могут находиться в конце фрагмента
fccType Тип фрагмента
dwDataOffset Смещение области данных относительно начала файла (в байтах)
dwFlags Нуль или MMIO_DIRTY (в последнем случае длина фрагмента может быть изменена, поэтому для ее обновления следует вызвать функцию mmioAscend); флаг MMIO_DIRTY может быть установлен при создании фрагмента функцией mmioCreateChunk

В нижеприведенном примере создается новый файл, подготавливается структура MMCKINFO, а затем создается фрагмент "RIFF", для чего вызывается функция mmioCreateChunk

hFile=mmioOpen(szFileName, NULL,
MMIO_CREATE | MMIO_READWRITE);
if (hFile != NULL)
{
ck.ckid=MMIO_CREATERIFF;
ck.cksize=waveioocbIn.lpWaveHdr->dwBytesRecorded
+ sizeof(PCMWAVEFORMAT) + 20;
ck.fccType=mmioFOURCC(‘W’, ‘A’, ‘V’, ‘E’);
mmioCreateChunk(hFile, (LPMMCKINFO) &ck, MMIO_CREATERIFF);
}

С целью поиска нужного фрагмента внутри RIFF-файла нет необходимости выполнять побайтное чтение файла и анализ его внутренней структуры; найти необходимый фрагмент и выполнить позиционирование относительно этого фрагмента можно с помощью функций mmioDescend и mmioAscend.
Функция mmioDescend ищет заданный фрагмент начиная с текущей позиции; при нахождении фрагмента текущая позиция будет установлена на область данных (она расположена на 8 байт ближе к концу файла от начала фрагмента, см. рис 3.9).

UINT
mmioDescend(HMMIO hmmio, // идентификатор файла
LPMMCKINFO lpck, // указатель на структуру
// MMCKINFO для
// текущего фрагмента
LPMMCKINFO lpckParent, // указатель на стр-ру
// MMCKINFO для
// внешнего фрагмента
UINT wFlags); // режим поиска

Здесь lpckParent - указатель на структуру MMCKINFO, описывающую внешний фрагмент, внутри которого выполняется поиск. В качестве внешнего фрагмента могут выступать только фрагменты ‘RIFF’ или ‘LIST’; если внешний фрагмент отсутствует, этот параметр можно указывать как NULL. Если указан wFlags=MMIO_FINDCHUNK, выполняется поиск фрагмента, заданного своим идентификатором, если wFlags=MMIO_FINDLIST - выполняется поиск фрагмента внутри фрагмента ‘LIST’, при wFlags=MMIO_FINDRIFF - внутри фрагмента ‘RIFF’.
При нормальном завершении функция mmioDescend возвращает нулевое значение, в противном случае - код ошибки.
В нижеприведенном примере кода открывается на чтение WAV-файл, затем в нем выполняется поиск фрагментов ‘WAVE’ и ‘fmt’

hmmio=mmioOpen((LPSTR)lpszFileName, NULL,
MMIO_READ | MMIO_ALLOCBUF);
if (!hmmio)
return WIOERR_FILEERROR;
memset(&ckRIFF, 0, sizeof(MMCKINFO));
ckRIFF.fccType=mmioFOURCC(‘W’, ‘A’, ‘V’, ‘E’);
if (mmioDescend(hmmio, &ckRIFF, NULL, MMIO_FINDRIFF))
{
mmioClose(hmmio, 0);
return WIOERR_BADFORMAT;
}
memset(&ckFMT, 0, sizeof(MMCKINFO));
ckFMT.ckid=mmioFOURCC(‘f’, ‘m’, ‘t’, ‘ ’);
if (mmioDescend(hmmio, &ckFMT, &ckRIFF, MMIO_FINDCHUNK))
{
mmioClose(hmmio, 0);
return WIOERR_BADFORMAT;
}

Функция mmioAscend предназначена для продвижения текущей позиции к началу следующего фрагмента.

UINT
mmioAscend(HMMIO hmmio, // идентификатор открытого файла
LPMMCKINFO lpck, // указатель на стр-ру MMCKINFO
UINT wFlags); // режим поиска

Структура MMCKINFO должна быть предварительно заполнена функцией mmioDescend или mmioCreateChunk, параметр wFlags не используется и должен быть нулевым.
При нормальном завершении функция mmioAscend возвращает нулевое значение, в противном случае - код ошибки.

Просмотров: 646 | Добавил: Shamaj | Рейтинг: 0.0/0


Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]