Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Программирование звука > waveInReset вешает прогу, а waveInStop работает нормально


Автор: Jin X 27.01.20, 17:30
Столкнулся с такой проблемой: при необходимости остановки записи вызов waveInReset вешает прогу (через раз), а waveInStop работает нормально.
Хотя, в другой проге всё ок.
Почему такое может быть?
p.s. Понимаю, что по-хорошему нужно бы код выложить, но пока не могу...

Добавлено
Разобрался.
Блин, магия какая-то. Возишься-возишься, понять не можешь в чём проблема.
Как только создашь тему на форуме, сразу находишь ошибку сам :)

Короче, в waveInProc было добавление буфера (причём, при uMsg = WIM_DATA).
Т.о. waveInReset вызывал waveInProc с uMsg = WIM_DATA для каждого буфера. Процедура добавляла новый буфер и процесс зацикливался...

Добавлено
А, нет. вру. Не зацикливается. Просто зависает при попытке добавить буфер.

Автор: Prince 27.01.20, 19:01
waveinproc и waveinaddbuffer вызывается в отдельном потоке, если используется сallback function. ресет этот поток убивает. При таком раскладе, да, возникают сюрпризы. Где-то тут этот ньюанс обсуждался уже.

Отказался от функции ресет вообще в свое время. Только стоп.

Автор: Jin X 28.01.20, 09:15
Как же waveInReset может убить поток, который потом вызывает (это я про waveInProc)?
Если не добавлять буферы, то всё ок.

Добавлено
Где обсуждалось – это я вчера перечитывал, я же и создавал тему (почти 4 года назад): waveInStop, waveInUnprepareHeader :)

Автор: Prince 28.01.20, 10:03
Может после обработки сообщений, но убивает поток, в котором эта самая очередь сообщений обрабатывается.
Такая же ернуда как c waveinaddbuffer будет, если waveoutwrite в callback использовать или да, waveInUnprepareHeader. Майкрософт сам же и говорит, что из callback нельзя вызывать никаких функций, кроме...
Поэтому от waveinreset отказался. Меньше мороки. waveinstop не уничтожает объекты, а потому алгоритм дальнейших действий получается просчитываемым и предсказуемым.

Автор: Jin X 28.01.20, 10:50
Цитата Prince @
Может после обработки сообщений, но убивает поток, в котором эта самая очередь сообщений обрабатывается.
Тогда добавление буфера из callback-процедуры не должно вешать софт :)

Цитата Prince @
Майкрософт сам же и говорит, что из callback нельзя вызывать никаких функций, кроме...
Кроме...? По крайней мере, waveInAddBuffer кроме как из callback-функции вызывать неоткуда.

Цитата Prince @
waveinstop не уничтожает объекты, а потому алгоритм дальнейших действий получается просчитываемым и предсказуемым.
:good:

Добавлено
Цитата Jin X @
Кроме...?
Applications should not call any system-defined functions from inside a callback function, except for EnterCriticalSection, LeaveCriticalSection, midiOutLongMsg, midiOutShortMsg, OutputDebugString, PostMessage, PostThreadMessage, SetEvent, timeGetSystemTime, timeGetTime, timeKillEvent, and timeSetEvent. Calling other wave functions will cause deadlock.

Откуда же тогда вызывать waveInAddBuffer?

Автор: Prince 28.01.20, 12:32
Цитата
Откуда же тогда вызывать waveInAddBuffer?

Задавался тем же вопросом. Ведь вызов из обработчика как бы сам собой напрашивается. Майкрософт хранит эту тайну.

Цитата
Цитата
Может после обработки сообщений, но убивает поток, в котором эта самая очередь сообщений обрабатывается.

Тогда добавление буфера из callback-процедуры не должно вешать софт

Помню, что waveinopen создает один дополнительный поток, и он не убивается вплоть до завершения работы приложения. Т.е., он не убивается даже после waveinclose . А после первого вызова waveinaddbuffer создавался еще один поток, в котором и крутился цикл обработки сообщений . waveinreset этот пооток прибивал.

Интуитивно, при вызове waveinreset уничтожается очередь заголовков буферов, поэтому waveinaddbuffer из обработчика после waveinreset - это как добавить элемент в динамический массив, когда самого массива уже нет. Ну это так, догадка.

Автор: Jin X 28.01.20, 13:55
Цитата Prince @
Задавался тем же вопросом. Ведь вызов из обработчика как бы сам собой напрашивается. Майкрософт хранит эту тайну.
Короче, нужно использовать поточный или оконный колбэк, вот что напрашивается :)
При этом, если прога не оконная, придётся создавать поток и в нём крутить цикл GetMessage (и создавать окно, если привязываемся к окну).
Я тут тоже тупанул: создал окно в текущем потоке + новый поток, в котором крутил цикл GetMessage. И думал: чего же это окно не получает сообщения? А ведь GetMessage получает сообщения только для окон, созданных в текущем потоке :facepalm:
В колбэк-функцией, кстати, есть ещё один неприятный момент. Если используется WAVE_MAPPER, то при смене аудиоустройства по умолчанию прога виснет. У меня, по крайней мере, такая канитель. Это WAVE_MAPPER, про другие не помню, вроде не должно.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)