Пишу библиотеку DLL для звуковой связи по tcp/ip сети. Для передачи звука принял решение использовать поток, на ThreadID которого будут приходить сообщения с данными от ОС. Проблема в следующем: у меня происходит запуск потока в Suspended (т.е. остановленном режиме), потом вызов waveInOpen, затем идет подготовка буферов и, собственно, запуск потока. В потоке в цикле стоит GetMessage(), который принимает сообщение и работает с ним дальше. Проблема в том, что после запуска потока сообщение не принимается (GetMessage() уходит в вечное ожидание), но если поток сразу делать запущеным, то сообщения приходят. Отсюда вопрос -- возможен ли прием (в очередь) сообщений suspended-потоком и если нет, то как такого добиться? И правильно ли я понял источник проблемы ? Я понимаю, что открытие аудио-устройства можно делать прямо в потоке, но пока хотелось бы написать именно так как я описал выше.
функция инициализации (вызывается один раз при запуске программы)
| Код | function SAS_InitTransmitter(DeviceID: Integer): Integer; var WaveFormat: TWaveFormatEx; I: Integer; begin ... AudioOutputDevice := DeviceID;
TransmitterThread := TAudioTransmitter.Create; // Создаем поток
with WaveFormat do begin wFormatTag := WAVE_FORMAT_PCM; nChannels := 1; wBitsPerSample := 16; nBlockAlign := nChannels * wBitsPerSample div 8; nSamplesPerSec := 8000; nAvgBytesPerSec := nSamplesPerSec * nBlockAlign; cbSize := 0; end;
InDevHandle := 0; Result := ifx(waveInOpen(@InDevHandle, AudioOutputDevice, @WaveFormat, TransmitterThread.ThreadID, 0, CALLBACK_THREAD) = MMSYSERR_NOERROR, SAS_E_FAIL, SAS_E_SUCCESS); if Result = SAS_E_FAIL then Exit;
// Готовим CWAVEBUFFERSCOUNT буферов передатчика, размером с фрейм кодирования (20 мс) for I := 0 to High(TXBuffers) do begin SetLength(inBuffs[I], encframe); with TXBuffers[I] do begin lpData := @inBuffs[I, 0]; dwBufferLength := Length(inBuffs[I]) * SizeOf(inBuffs[I, 0]); dwBytesRecorded := 0; dwUser := I; // Порядковый номер буфера dwLoops := 0; Result := ifx(waveInPrepareHeader(InDevHandle, @TXBuffers[I], SizeOf(TWAVEHDR)) = MMSYSERR_NOERROR, SAS_E_FAIL, SAS_E_SUCCESS); if Result = SAS_E_FAIL then Exit; end; end;
if Result = SAS_E_SUCCESS then begin TransmitterThread.Resume; // Запускаем поток!! TXInit := True; end else TransmitterThread.Free; end;
|
поток:
| Код | constructor TAudioTransmitter.Create; begin inherited Create(True); // Если False, то сообщение принимается Priority := tpNormal; FreeOnTerminate := False; GetMem(payload, 8000); PeekMessage(Msg, 0, 0, 0, PM_REMOVE); end;
destructor TAudioTransmitter.Destroy; begin PostThreadMessage(ThreadID, WM_QUIT, 0, 0); FreeMem(payload); inherited; end;
procedure TAudioTransmitter.Execute; var I, enc_size, BuffNo, total_pl, frames: Integer; AudioData: TSAS_MSG_AUDIODATA; begin .. while not Terminated do begin ..
if GetMessage(Msg, 0, 0, 0) then begin case Msg.message of MM_WIM_OPEN: begin ... end;
MM_WIM_DATA: begin ...
waveInAddBuffer(InDevHandle, PWAVEHDR(Msg.lParam), SizeOf(TWAVEHDR)); end; end; end;
end; end;
|
|