Пишу программу, работающую со звуком. Понадобилось мне имя устройства, юзаю waveOutGetDevCaps, в эту функцию передаю хендл полученный от waveOutOpen. Если в waveOutOpen использовать индекс устройства, то получаю правильно заполненное короткое имя и GUID имени. Но мне нужно указать WAVE_MAPPER в waveOutOpen, но в таком случае все GUID-ы нулевые, и короткое имя тоже не заполнено, как быть? PS Вызываемая копия функции - юникодная. Код (ASM): struct GUID Data1 dd ? Data2 dw ? Data3 dw ? Data4 dq ? ends struct WAVEOUTCAPS2 wMid dw ? wPid dw ? vDriverVersion dd ? szPname du 32 dup (?) dwFormats dd ? wChannels dw ? wReserved1 dw ? dwSupport dd ? ManufacturerGuid GUID ProductGuid GUID NameGuid GUID ends struct WAVEFORMATEX wFormatTag dw ? nChannels dw ? nSamplesPerSec dd ? nAvgBytesPerSec dd ? nBlockAlign dw ? wBitsPerSample dw ? cbSize dw ? ends ... mov [WaveFormat+WAVEFORMATEX.wFormatTag],WAVE_FORMAT_PCM mov [WaveFormat+WAVEFORMATEX.nChannels],1 mov [WaveFormat+WAVEFORMATEX.nSamplesPerSec],44100 mov [WaveFormat+WAVEFORMATEX.nAvgBytesPerSec],44100*2 mov [WaveFormat+WAVEFORMATEX.nBlockAlign],2 mov [WaveFormat+WAVEFORMATEX.wBitsPerSample],16 and [WaveFormat+WAVEFORMATEX.cbSize],0 lea rcx,[hWaveOut] or rdx,WAVE_MAPPER lea r8,[WaveFormat] invoke waveOutOpen,rcx,rdx,r8,[Event],0,CALLBACK_EVENT test rax,rax je .Opened invoke CloseHandle,[Event] lea rcx,[OpenError] invoke wprintf,rcx,rdx jmp .err .Opened: lea rdx,[WaveOutCaps] invoke waveOutGetDevCaps,[hWaveOut],rdx,sizeof.WAVEOUTCAPS2 test rax,rax je .CapsGot lea rcx,[CapsErr] invoke wprintf,rcx jmp .EndCaps .CapsGot: int3
Я передаю хендл, полученный при открытии WAVE_MAPPER функцией waveOutOpen в функцию waveOutGetDevCaps.
Проверил, это не будет работать. Можно попробовать отправить сообщение DRVM_MAPPER_PREFERRED_GET чтобы получить ID.
Решил вместо WAVE_MAPPER перечислить все устройства и вывести их имена, но для первого и единственного устройства у меня на компьютере waveOutGetDevCaps корректно заполняет ManufacturerGuid и ProductGuid, но NameGuid - нулевой.
Удобно. Если никто не скинет, сделаю примерчик позже. Если же просто перечисление, то COM даже не используется в явном виде. А прием с DRVM_MAPPER_PREFERRED_GET работает?
Код (ASM): format PE64 entry start include 'WIN64WX.inc' struct GUID Data1 dd ? Data2 dw ? Data3 dw ? Data4 db 8 dup(?) ends section '.idata' import data readable writeable library kernel, 'kernel32.dll', \ dsound, 'dsound.dll', \ ole32, 'ole32.dll', \ msvcrt, 'msvcrt.dll' import kernel,\ memcpy, 'RtlMoveMemory', \ ExitProcess, 'ExitProcess', \ WriteConsole, 'WriteConsoleW', \ GetStdHandle, 'GetStdHandle', \ lstrlen, 'lstrlenW' import dsound, \ DirectSoundEnumerate, 3 import msvcrt, \ swprintf_s, 'swprintf_s' import ole32, \ StringFromGUID2, 'StringFromGUID2' section '.data' data readable writeable hOut dq ?; pszFormat du "%s: %s", 13, 10, 0 ; Формат [Имя: GUID] section '.text' code readable executable proc start invoke GetStdHandle, STD_OUTPUT_HANDLE mov [hOut], rax invoke DirectSoundEnumerate, DSEnumCallback ; Запуск перечисления invoke ExitProcess, 0; ret endp ; Функция перечисления proc DSEnumCallback, lpGuid, lpcstrDescription, lpcstrModule, lpContext locals cBuffer du 128 dup(?) ; Буфер для выходной строки cGUID du 41 dup(?) ; Буфер для строкового представления GUID tGuid GUID 0, 0, 0, 8 dup (0) dwWritten dw ? endl mov [lpGuid], rcx; mov [lpcstrDescription], rdx; .if ([lpGuid]) invoke memcpy, addr tGuid, [lpGuid], sizeof.GUID .endif invoke StringFromGUID2, addr tGuid, addr cGUID, 41 ; Переводим GUID в строку cinvoke swprintf_s, addr cBuffer, 128, pszFormat, [lpcstrDescription], addr cGUID invoke WriteConsole, [hOut], addr cBuffer, <invoke lstrlen, addr cBuffer>, addr dwWritten, NULL ; Выводим в консоль ret endp
Посмотрел DirectSound, как я понял, для работы нужно вызывать метод SetCooperativeLevel, он принимает на вход хендл окна моей программы. Но проблема в том, что у моей программы нет окна (только консоль). Можно ли как-то обойтись без окна, или надо юзать WINMM? Хотя вроде-бы GetDesktopWindow принимает, так вообще можно делать?
_qwe8013, лучше создать окно или получить хендл консольного окна, т.к. в документации требуется окно верхнего уровня принадлежащее текущему процессу. Вообще использовать или не использовать DirectSound для проигрывания звука - зависит от задачи. Я скинул пример получения полных имен через DirectSound, а для проигрывания также можно использовать WINMM. Если ты не используешь возможности DirectSound то лучше наверное использовать WINMM.
Ещё такой вопрос: вызываю функцию waveOutGetDevCaps с заведомо невалидным индексом устройства: Код (ASM): lea rdx,[WaveCaps] invoke waveOutGetDevCaps,10,rdx,sizeof.WAVEOUTCAPS2 она возвращает ошибку. Но когда я передаю её в waveOutGetErrorText, в строке оказывается мусор: Код (ASM): ErrText du 512 dup (?) ... lea rdx,[ErrText] invoke waveOutGetErrorText,rax,rdx,512 Как получить строку ошибки?
Да, у меня тоже всё верно, просто кодировку дампа не правильно настроил, а как это вывести на консоль? CharToOEM не помогает.