]> Repos - portaudio/commitdiff
wasapi: fixed audio device not released to other applications if WASAPI Exclusive...
authordmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Sun, 26 Dec 2010 16:36:52 +0000 (16:36 +0000)
committerdmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Sun, 26 Dec 2010 16:36:52 +0000 (16:36 +0000)
src/hostapi/wasapi/pa_win_wasapi.c

index 29a8aa805178448b66290c436cebe8fdae34c03a..cbd9dee44905a7811ccf09140da503872947092f 100644 (file)
@@ -473,6 +473,7 @@ PaWasapiStream;
 // Local stream methods\r
 static void _OnStreamStop(PaWasapiStream *stream);\r
 static void _FinishStream(PaWasapiStream *stream);\r
+static void _CleanupStream(PaWasapiStream *stream);\r
 \r
 // Local statics\r
 static volatile BOOL  g_WasapiCOMInit    = FALSE;\r
@@ -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\r
           please report to PortAudio developers to exclude Windows 7.\r
        */\r
-       if ((params.sampleFormat == paInt24) && (output == FALSE))\r
-               params.sampleFormat = paFloat32;\r
+       /*if ((params.sampleFormat == paInt24) && (output == FALSE))\r
+               params.sampleFormat = paFloat32;*/ // <<< The silence was due to missing Int32_To_Int24_Dither implementation\r
 \r
     MakeWaveFormatFromParams(outWavex, &params, sampleRate);\r
 \r
@@ -2760,12 +2761,7 @@ static PaError CloseStream( PaStream* s )
        CloseHandle(stream->event[S_INPUT]);\r
        CloseHandle(stream->event[S_OUTPUT]);\r
 \r
-    SAFE_CLOSE(stream->hThread);\r
-       SAFE_CLOSE(stream->hThreadStart);\r
-       SAFE_CLOSE(stream->hThreadExit);\r
-       SAFE_CLOSE(stream->hCloseRequest);\r
-       SAFE_CLOSE(stream->hBlockingOpStreamRD);\r
-       SAFE_CLOSE(stream->hBlockingOpStreamWR);\r
+       _CleanupStream(stream);\r
 \r
        free(stream->in.monoBuffer);\r
        free(stream->out.monoBuffer);\r
@@ -2789,6 +2785,9 @@ static PaError StartStream( PaStream *s )
 \r
     PaUtil_ResetBufferProcessor(&stream->bufferProcessor);\r
 \r
+       // Cleanup handles (may be necessary if stream was stopped by itself due to error)\r
+       _CleanupStream(stream);\r
+\r
        // Create close event\r
        stream->hCloseRequest = CreateEvent(NULL, TRUE, FALSE, NULL);\r
 \r
@@ -2889,6 +2888,15 @@ static void _FinishStream(PaWasapiStream *stream)
                _OnStreamStop(stream);\r
        }\r
 \r
+       // Cleanup handles\r
+       _CleanupStream(stream);\r
+\r
+    stream->running = FALSE;\r
+}\r
+\r
+// ------------------------------------------------------------------------------------------\r
+static void _CleanupStream(PaWasapiStream *stream)\r
+{\r
        // Close thread handles to allow restart\r
        SAFE_CLOSE(stream->hThread);\r
        SAFE_CLOSE(stream->hThreadStart);\r
@@ -2896,8 +2904,6 @@ static void _FinishStream(PaWasapiStream *stream)
        SAFE_CLOSE(stream->hCloseRequest);\r
        SAFE_CLOSE(stream->hBlockingOpStreamRD);\r
        SAFE_CLOSE(stream->hBlockingOpStreamWR);\r
-\r
-    stream->running = FALSE;\r
 }\r
 \r
 // ------------------------------------------------------------------------------------------\r
@@ -3726,10 +3732,8 @@ static HRESULT ProcessOutputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor
        // Process data\r
        if (stream->out.monoMixer != NULL)\r
        {\r
-#define __DIV_8(v)  ((v) >> 3) //!< (v / 8)\r
-\r
                // expand buffer (one way only for better performancedue to no calls to realloc)\r
-               UINT32 mono_frames_size = frames * __DIV_8(stream->out.wavex.Format.wBitsPerSample);\r
+               UINT32 mono_frames_size = frames * (stream->out.wavex.Format.wBitsPerSample / 8);\r
                if (mono_frames_size > stream->out.monoBufferSize)\r
                        stream->out.monoBuffer = realloc(stream->out.monoBuffer, (stream->out.monoBufferSize = mono_frames_size));\r
 \r
@@ -3738,8 +3742,6 @@ static HRESULT ProcessOutputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor
 \r
                // mix 1 to 2 channels\r
                stream->out.monoMixer(data, stream->out.monoBuffer, frames);\r
-\r
-#undef __DIV_8\r
        }\r
        else\r
        {\r
@@ -3787,10 +3789,8 @@ static HRESULT ProcessInputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor
                // Process data\r
                if (stream->in.monoMixer != NULL)\r
                {\r
-#define __DIV_8(v)  ((v) >> 3) //!< (v / 8)\r
-\r
                        // expand buffer (one way only for better performancedue to no calls to realloc)\r
-                       UINT32 mono_frames_size = frames * __DIV_8(stream->in.wavex.Format.wBitsPerSample);\r
+                       UINT32 mono_frames_size = frames * (stream->in.wavex.Format.wBitsPerSample / 8);\r
                        if (mono_frames_size > stream->in.monoBufferSize)\r
                                stream->in.monoBuffer = realloc(stream->in.monoBuffer, (stream->in.monoBufferSize = mono_frames_size));\r
 \r
@@ -3799,8 +3799,6 @@ static HRESULT ProcessInputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor
 \r
                        // process\r
                        processor[S_INPUT].processor((BYTE *)stream->in.monoBuffer, frames, NULL, 0, processor[S_INPUT].userData);\r
-\r
-#undef __DIV_8\r
                }\r
                else\r
                {\r
@@ -3810,6 +3808,8 @@ static HRESULT ProcessInputBuffer(PaWasapiStream *stream, PaWasapiHostProcessor
                // Release buffer\r
                if ((hr = IAudioCaptureClient_ReleaseBuffer(stream->cclient, frames)) != S_OK)\r
                        return LogHostError(hr);\r
+\r
+               break;\r
        }\r
 \r
        return hr;\r
@@ -3833,6 +3833,10 @@ void _OnStreamStop(PaWasapiStream *stream)
                stream->hAvTask = NULL;\r
        }\r
 \r
+       // Release Render/Capture clients (if Exclusive mode was used it will release devices to other applications)\r
+    SAFE_RELEASE(stream->cclient);\r
+    SAFE_RELEASE(stream->rclient);\r
+\r
     // Notify\r
     if (stream->streamRepresentation.streamFinishedCallback != NULL)\r
         stream->streamRepresentation.streamFinishedCallback(stream->streamRepresentation.userData);\r
@@ -3961,8 +3965,8 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
        // Processing Loop\r
        for (;;)\r
     {\r
-           // 2 sec timeout\r
-        dwResult = WaitForMultipleObjects(S_COUNT, stream->event, bWaitAllEvents, 10000);\r
+           // 10 sec timeout (on timeout stream will auto-stop when processed by WAIT_TIMEOUT case)\r
+        dwResult = WaitForMultipleObjects(S_COUNT, stream->event, bWaitAllEvents, 10*1000);\r
 \r
                // Check for close event (after wait for buffers to avoid any calls to user\r
                // callback when hCloseRequest was set)\r
@@ -3979,24 +3983,30 @@ PA_THREAD_FUNC ProcThreadEvent(void *param)
 \r
                // Input stream\r
                case WAIT_OBJECT_0 + S_INPUT: {\r
+\r
             if (stream->cclient == NULL)\r
                 break;\r
+\r
                        if ((hr = ProcessInputBuffer(stream, processor)) != S_OK)\r
                        {\r
                                LogHostError(hr);\r
                                goto thread_error;\r
                        }\r
+\r
                        break; }\r
 \r
                // Output stream\r
                case WAIT_OBJECT_0 + S_OUTPUT: {\r
+\r
             if (stream->rclient == NULL)\r
                 break;\r
+\r
                        if ((hr = ProcessOutputBuffer(stream, processor, stream->out.framesPerBuffer)) != S_OK)\r
                        {\r
                                LogHostError(hr);\r
                                goto thread_error;\r
                        }\r
+\r
                        break; }\r
                }\r
        }\r
@@ -4233,13 +4243,16 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
                                {\r
                                // Input stream\r
                                case S_INPUT: {\r
+\r
                                        if (stream->cclient == NULL)\r
                                                break;\r
+\r
                                        if ((hr = ProcessInputBuffer(stream, processor)) != S_OK)\r
                                        {\r
                                                LogHostError(hr);\r
                                                goto thread_error;\r
                                        }\r
+\r
                                        break; }\r
 \r
                                // Output stream\r
@@ -4329,9 +4342,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
                                        // convert output mono\r
                                        if (stream->out.monoMixer)\r
                                        {\r
-                                               #define __DIV_8(v)  ((v) >> 3) //!< (v / 8)\r
-                                               UINT32 mono_frames_size = o_processed * __DIV_8(stream->out.wavex.Format.wBitsPerSample);\r
-                                               #undef __DIV_8\r
+                                               UINT32 mono_frames_size = o_processed * (stream->out.wavex.Format.wBitsPerSample / 8);\r
                                                // expand buffer (one way only for better performance due to no calls to realloc)\r
                                                if (mono_frames_size > stream->out.monoBufferSize)\r
                                                {\r
@@ -4350,9 +4361,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
                                        // convert input mono\r
                                        if (stream->in.monoMixer)\r
                                        {\r
-                                               #define __DIV_8(v)  ((v) >> 3) //!< (v / 8)\r
-                                               UINT32 mono_frames_size = i_processed * __DIV_8(stream->in.wavex.Format.wBitsPerSample);\r
-                                               #undef __DIV_8\r
+                                               UINT32 mono_frames_size = i_processed * (stream->in.wavex.Format.wBitsPerSample / 8);\r
                                                // expand buffer (one way only for better performance due to no calls to realloc)\r
                                                if (mono_frames_size > stream->in.monoBufferSize)\r
                                                {\r
@@ -4455,9 +4464,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
                                                // convert output mono\r
                                                if (stream->out.monoMixer)\r
                                                {\r
-                                                       #define __DIV_8(v)  ((v) >> 3) //!< (v / 8)\r
-                                                       UINT32 mono_frames_size = o_processed * __DIV_8(stream->out.wavex.Format.wBitsPerSample);\r
-                                                       #undef __DIV_8\r
+                                                       UINT32 mono_frames_size = o_processed * (stream->out.wavex.Format.wBitsPerSample / 8);\r
                                                        // expand buffer (one way only for better performance due to no calls to realloc)\r
                                                        if (mono_frames_size > stream->out.monoBufferSize)\r
                                                        {\r
@@ -4476,9 +4483,7 @@ PA_THREAD_FUNC ProcThreadPoll(void *param)
                                                // convert input mono\r
                                                if (stream->in.monoMixer)\r
                                                {\r
-                                                       #define __DIV_8(v)  ((v) >> 3) //!< (v / 8)\r
-                                                       UINT32 mono_frames_size = i_processed * __DIV_8(stream->in.wavex.Format.wBitsPerSample);\r
-                                                       #undef __DIV_8\r
+                                                       UINT32 mono_frames_size = i_processed * (stream->in.wavex.Format.wBitsPerSample / 8);\r
                                                        // expand buffer (one way only for better performance due to no calls to realloc)\r
                                                        if (mono_frames_size > stream->in.monoBufferSize)\r
                                                        {\r