From: dmitrykos Date: Sun, 26 Dec 2010 16:36:52 +0000 (+0000) Subject: wasapi: fixed audio device not released to other applications if WASAPI Exclusive... X-Git-Tag: pa_stable_v19_20110326_r1647~69 X-Git-Url: https://andrewgundersen.net/repos?a=commitdiff_plain;h=8b6f0610b6631d3887518927642db9cb95b5796a;p=portaudio wasapi: fixed audio device not released to other applications if WASAPI Exclusive stream is stopped but not yet closed. Bug does not affect Shared mode streams. Fixed possible object's leakage in situation when WASAPI thread encountered an error and stopped and user decided to start stream again without prior closing it. --- diff --git a/src/hostapi/wasapi/pa_win_wasapi.c b/src/hostapi/wasapi/pa_win_wasapi.c index 29a8aa8..cbd9dee 100644 --- a/src/hostapi/wasapi/pa_win_wasapi.c +++ b/src/hostapi/wasapi/pa_win_wasapi.c @@ -473,6 +473,7 @@ PaWasapiStream; // Local stream methods static void _OnStreamStop(PaWasapiStream *stream); static void _FinishStream(PaWasapiStream *stream); +static void _CleanupStream(PaWasapiStream *stream); // Local statics static volatile BOOL g_WasapiCOMInit = FALSE; @@ -1656,8 +1657,8 @@ static PaError GetClosestFormat(IAudioClient *myClient, double sampleRate, to 24-bit for user-space. The bug concerns Vista, if Windows 7 supports 24-bits for Input please report to PortAudio developers to exclude Windows 7. */ - if ((params.sampleFormat == paInt24) && (output == FALSE)) - params.sampleFormat = paFloat32; + /*if ((params.sampleFormat == paInt24) && (output == FALSE)) + params.sampleFormat = paFloat32;*/ // <<< The silence was due to missing Int32_To_Int24_Dither implementation MakeWaveFormatFromParams(outWavex, ¶ms, sampleRate); @@ -2760,12 +2761,7 @@ static PaError CloseStream( PaStream* s ) CloseHandle(stream->event[S_INPUT]); CloseHandle(stream->event[S_OUTPUT]); - SAFE_CLOSE(stream->hThread); - SAFE_CLOSE(stream->hThreadStart); - SAFE_CLOSE(stream->hThreadExit); - SAFE_CLOSE(stream->hCloseRequest); - SAFE_CLOSE(stream->hBlockingOpStreamRD); - SAFE_CLOSE(stream->hBlockingOpStreamWR); + _CleanupStream(stream); free(stream->in.monoBuffer); free(stream->out.monoBuffer); @@ -2789,6 +2785,9 @@ static PaError StartStream( PaStream *s ) PaUtil_ResetBufferProcessor(&stream->bufferProcessor); + // Cleanup handles (may be necessary if stream was stopped by itself due to error) + _CleanupStream(stream); + // Create close event stream->hCloseRequest = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -2889,6 +2888,15 @@ static void _FinishStream(PaWasapiStream *stream) _OnStreamStop(stream); } + // Cleanup handles + _CleanupStream(stream); + + stream->running = FALSE; +} + +// ------------------------------------------------------------------------------------------ +static void _CleanupStream(PaWasapiStream *stream) +{ // Close thread handles to allow restart SAFE_CLOSE(stream->hThread); SAFE_CLOSE(stream->hThreadStart); @@ -2896,8 +2904,6 @@ static void _FinishStream(PaWasapiStream *stream) SAFE_CLOSE(stream->hCloseRequest); SAFE_CLOSE(stream->hBlockingOpStreamRD); SAFE_CLOSE(stream->hBlockingOpStreamWR); - - stream->running = FALSE; } // ------------------------------------------------------------------------------------------ @@ -3726,10 +3732,8 @@ static HRESULT ProcessOutputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor // Process data if (stream->out.monoMixer != NULL) { -#define __DIV_8(v) ((v) >> 3) //!< (v / 8) - // expand buffer (one way only for better performancedue to no calls to realloc) - UINT32 mono_frames_size = frames * __DIV_8(stream->out.wavex.Format.wBitsPerSample); + UINT32 mono_frames_size = frames * (stream->out.wavex.Format.wBitsPerSample / 8); if (mono_frames_size > stream->out.monoBufferSize) stream->out.monoBuffer = realloc(stream->out.monoBuffer, (stream->out.monoBufferSize = mono_frames_size)); @@ -3738,8 +3742,6 @@ static HRESULT ProcessOutputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor // mix 1 to 2 channels stream->out.monoMixer(data, stream->out.monoBuffer, frames); - -#undef __DIV_8 } else { @@ -3787,10 +3789,8 @@ static HRESULT ProcessInputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor // Process data if (stream->in.monoMixer != NULL) { -#define __DIV_8(v) ((v) >> 3) //!< (v / 8) - // expand buffer (one way only for better performancedue to no calls to realloc) - UINT32 mono_frames_size = frames * __DIV_8(stream->in.wavex.Format.wBitsPerSample); + UINT32 mono_frames_size = frames * (stream->in.wavex.Format.wBitsPerSample / 8); if (mono_frames_size > stream->in.monoBufferSize) stream->in.monoBuffer = realloc(stream->in.monoBuffer, (stream->in.monoBufferSize = mono_frames_size)); @@ -3799,8 +3799,6 @@ static HRESULT ProcessInputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor // process processor[S_INPUT].processor((BYTE *)stream->in.monoBuffer, frames, NULL, 0, processor[S_INPUT].userData); - -#undef __DIV_8 } else { @@ -3810,6 +3808,8 @@ static HRESULT ProcessInputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor // Release buffer if ((hr = IAudioCaptureClient_ReleaseBuffer(stream->cclient, frames)) != S_OK) return LogHostError(hr); + + break; } return hr; @@ -3833,6 +3833,10 @@ void _OnStreamStop(PaWasapiStream *stream) stream->hAvTask = NULL; } + // Release Render/Capture clients (if Exclusive mode was used it will release devices to other applications) + SAFE_RELEASE(stream->cclient); + SAFE_RELEASE(stream->rclient); + // Notify if (stream->streamRepresentation.streamFinishedCallback != NULL) stream->streamRepresentation.streamFinishedCallback(stream->streamRepresentation.userData); @@ -3961,8 +3965,8 @@ PA_THREAD_FUNC ProcThreadEvent(void *param) // Processing Loop for (;;) { - // 2 sec timeout - dwResult = WaitForMultipleObjects(S_COUNT, stream->event, bWaitAllEvents, 10000); + // 10 sec timeout (on timeout stream will auto-stop when processed by WAIT_TIMEOUT case) + dwResult = WaitForMultipleObjects(S_COUNT, stream->event, bWaitAllEvents, 10*1000); // Check for close event (after wait for buffers to avoid any calls to user // callback when hCloseRequest was set) @@ -3979,24 +3983,30 @@ PA_THREAD_FUNC ProcThreadEvent(void *param) // Input stream case WAIT_OBJECT_0 + S_INPUT: { + if (stream->cclient == NULL) break; + if ((hr = ProcessInputBuffer(stream, processor)) != S_OK) { LogHostError(hr); goto thread_error; } + break; } // Output stream case WAIT_OBJECT_0 + S_OUTPUT: { + if (stream->rclient == NULL) break; + if ((hr = ProcessOutputBuffer(stream, processor, stream->out.framesPerBuffer)) != S_OK) { LogHostError(hr); goto thread_error; } + break; } } } @@ -4233,13 +4243,16 @@ PA_THREAD_FUNC ProcThreadPoll(void *param) { // Input stream case S_INPUT: { + if (stream->cclient == NULL) break; + if ((hr = ProcessInputBuffer(stream, processor)) != S_OK) { LogHostError(hr); goto thread_error; } + break; } // Output stream @@ -4329,9 +4342,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param) // convert output mono if (stream->out.monoMixer) { - #define __DIV_8(v) ((v) >> 3) //!< (v / 8) - UINT32 mono_frames_size = o_processed * __DIV_8(stream->out.wavex.Format.wBitsPerSample); - #undef __DIV_8 + UINT32 mono_frames_size = o_processed * (stream->out.wavex.Format.wBitsPerSample / 8); // expand buffer (one way only for better performance due to no calls to realloc) if (mono_frames_size > stream->out.monoBufferSize) { @@ -4350,9 +4361,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param) // convert input mono if (stream->in.monoMixer) { - #define __DIV_8(v) ((v) >> 3) //!< (v / 8) - UINT32 mono_frames_size = i_processed * __DIV_8(stream->in.wavex.Format.wBitsPerSample); - #undef __DIV_8 + UINT32 mono_frames_size = i_processed * (stream->in.wavex.Format.wBitsPerSample / 8); // expand buffer (one way only for better performance due to no calls to realloc) if (mono_frames_size > stream->in.monoBufferSize) { @@ -4455,9 +4464,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param) // convert output mono if (stream->out.monoMixer) { - #define __DIV_8(v) ((v) >> 3) //!< (v / 8) - UINT32 mono_frames_size = o_processed * __DIV_8(stream->out.wavex.Format.wBitsPerSample); - #undef __DIV_8 + UINT32 mono_frames_size = o_processed * (stream->out.wavex.Format.wBitsPerSample / 8); // expand buffer (one way only for better performance due to no calls to realloc) if (mono_frames_size > stream->out.monoBufferSize) { @@ -4476,9 +4483,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param) // convert input mono if (stream->in.monoMixer) { - #define __DIV_8(v) ((v) >> 3) //!< (v / 8) - UINT32 mono_frames_size = i_processed * __DIV_8(stream->in.wavex.Format.wBitsPerSample); - #undef __DIV_8 + UINT32 mono_frames_size = i_processed * (stream->in.wavex.Format.wBitsPerSample / 8); // expand buffer (one way only for better performance due to no calls to realloc) if (mono_frames_size > stream->in.monoBufferSize) {