Мультимедиа для Windows

         

SNDPLAY



Приложение SNDPLAY

Наше первое приложение SNDPLAY, имеющее зачатки мультимедиа, предназначено для демонстрации различных способов работы с функцией sndPlaySound (листинг 2.1).

Листинг 2.1. Файл sndplay\sndplay.cpp // ---------------------------------------- // Использование функций // MessageBeep и sndPlaySound // ---------------------------------------- #define STRICT #include <windows.h> #include <mmsystem.h> #pragma argsused int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { HANDLE hWaveRes, hRes; LPSTR lpRes; BOOL rc; HFILE hf; DWORD dwFileSize; HGLOBAL hWave; char huge *lpBuf; // Проигрываем звук, соответствующий строке // SystemQuestion раздела [sound] файла win.ini MessageBeep(MB_ICONQUESTION); MessageBox(NULL, "Начнем, что ли?", "SndPlay", MB_OK | MB_ICONQUESTION); // Проигрываем файл sndplay.snd в синхронном режиме rc = sndPlaySound((LPSTR)"sndplay.wav", SND_SYNC); if(!rc) { MessageBeep(MB_ICONHAND); MessageBox(NULL, "Не могу проиграть файл sndplay.wav", "SndPlay", MB_OK | MB_ICONHAND); return -1; } // Загружаем звуковой фрагмент из ресурсов приложения // и проигрываем его // Находим нужный ресурс hWaveRes = FindResource(hInstance, "APP_SOUND", "WAVE"); if(hWaveRes) { // Загружаем ресурс в память hRes = LoadResource(hInstance, (HRSRC)hWaveRes); if(hRes) { // Фиксируем ресурс в памяти, получая // указатель на данные lpRes = (LPSTR)LockResource(hRes); if(lpRes) { // Проигрываем звук в цикле rc = sndPlaySound(lpRes, SND_MEMORY | SND_ASYNC | SND_LOOP); MessageBox(NULL, "Для завершения нажмите кнопку OK", "SndPlay", MB_OK | MB_ICONINFORMATION);


// Останавливаем проигрывание sndPlaySound(NULL, 0); // Расфиксируем и освобождаем ресурс UnlockResource(hRes); FreeResource(hRes); // Загружаем звуковой фрагмент непосредственно из // wav-файла в память и проигрываем его // Открываем wav-файл hf = _lopen((LPSTR)"uff.wav", OF_READ); // Определяем размер файла dwFileSize = _llseek(hf, 0l, 2); _llseek(hf, 0l, 0); // Заказываем глобальный блок памяти, // размер которого равен длине файла hWave = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwFileSize); // Фиксируем блок памяти lpBuf = (char huge *)GlobalLock(hWave); if(lpBuf != NULL) { // Читаем файл в полученный блок памяти _hread(hf, lpBuf, dwFileSize); // Проигрываем звуковой фрагмент, загруженный в память rc = sndPlaySound((LPCSTR)lpBuf, SND_MEMORY | SND_SYNC); if(!rc) { MessageBeep(MB_ICONHAND); MessageBox(NULL, "Не могу проиграть файл uff.wav", "SndPlay", MB_OK | MB_ICONHAND); } // Расфиксируем и освобождаем память GlobalUnlock(hWave); GlobalFree(hWave); // Закрываем файл _lclose(hf); } } } } return 0; }

Приложение не имеет главного окна и функции окна. Сразу после запуска приложение SNDPLAY вызывает функцию MessageBeep, с помощью которой проигрывается звук, соответствующий строке SystemQuestion раздела [sound] файла win.ini.

Затем приложение вызывает функцию sndPlaySound для проигрывания файла sndplay.wav в синхронном режиме: rc = sndPlaySound((LPSTR)"sndplay.wav", SND_SYNC);

Как только этот файл будет проигран, функция sndPlaySound вернет управление и работа приложения будет продолжена.

Далее приложение загружает звуковой фрагмент из ресурсов и проигрывает его асинхронно в циклическом режиме. При этом на экран выводится диалоговая панель с сообщением о то, что для прекращения циклического проигрывания следует нажать кнопку OK. Методика работы с ресурсами была описана нами в 12 томе "Библиотеки системного программиста". После поиска и фиксирования ресурса адрес соответствующего блока памяти передается в качестве первого параметра функции sndPlaySound: rc = sndPlaySound(lpRes, SND_MEMORY | SND_ASYNC | SND_LOOP);

Так как звуковой файл находится в памяти, во втором параметре этой функции необходимо указать флаги SND_MEMORY и SND_ASYNC. Для циклического проигрывания следует также указать флаг SND_LOOP.

Для прерывания циклического проигрывания функция sndPlaySound вызывается с нулевыми параметрами: sndPlaySound(NULL, 0);

В некоторых случаях может оказаться удобным проигрывать звуковой фрагмент, загруженный в память не из ресурсов приложения, а непосредственно из wav-файла. Финальная часть приложения SNDPLAY демонстрирует этот способ.

Вначале приложение открывает wav-файл с помощью функции _lopen и определяет его размер, вызывая функцию _llseek : hf = _lopen((LPSTR)"uff.wav", OF_READ); dwFileSize = _llseek(hf, 0l, 2); _llseek(hf, 0l, 0);

Далее приложение заказывает глобальный блок памяти такого размера, чтобы в нем мог поместиться весь wav-файл. Блок фиксируется в памяти: hWave = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwFileSize); lpBuf = (char huge *)GlobalLock(hWave);

Теперь, если передать адрес этого блока функции sndPlaySound, можно проиграть его в асинхронном или синхронном режиме. Так как мы освобождаем память сразу после возврата управления из функции sndPlaySound, для простоты мы выбрали синхронный режим: rc = sndPlaySound((LPCSTR)lpBuf, SND_MEMORY | SND_SYNC);

Только после того, как проигрывание закончено, можно расфиксировать и освободить память с образом wav-файла: GlobalUnlock(hWave); GlobalFree(hWave);

Если освободить память до момента окончания проигрывания, Windows перейдет в нестабильное состояние, требующее полного перезапуска.

Файл ресурсов приложения (листинг 2.2) содержит описание ресурса типа WAVE (можно использовать любой другой нестандартный тип ресурса):

Листинг 2.2. Файл sndplay\sndplay.rc APP_SOUND WAVE loop.wav APPICON ICON "sndplay.ico"

Файл определения модуля приложения SNDPLAY приведен в листинге 2.3.

Листинг 2.3. Файл sndplay\sndplay.def NAME SNDPLAY DESCRIPTION 'Приложение SNDPLAY, (C) 1994, Frolov A.V.' EXETYPE windows STUB 'winstub.exe' STACKSIZE 5120 HEAPSIZE 1024 CODE preload moveable discardable DATA preload moveable multiple



Содержание    Назад    Вперед