winrt: Wait for EnumerationCompleted before leaving WASAPI_EnumerateEndpoints
authorEthan Lee <flibitijibibo@flibitijibibo.com>
Tue, 03 Mar 2020 12:31:41 -0500
changeset 135900311c59d15f9
parent 13589 ed4d8114b4e8
child 13591 35b18e76f1a6
winrt: Wait for EnumerationCompleted before leaving WASAPI_EnumerateEndpoints
src/audio/wasapi/SDL_wasapi_winrt.cpp
     1.1 --- a/src/audio/wasapi/SDL_wasapi_winrt.cpp	Wed Mar 04 17:10:37 2020 -0800
     1.2 +++ b/src/audio/wasapi/SDL_wasapi_winrt.cpp	Tue Mar 03 12:31:41 2020 -0500
     1.3 @@ -63,8 +63,10 @@
     1.4      void OnDeviceAdded(DeviceWatcher^ sender, DeviceInformation^ args);
     1.5      void OnDeviceRemoved(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
     1.6      void OnDeviceUpdated(DeviceWatcher^ sender, DeviceInformationUpdate^ args);
     1.7 +    void OnEnumerationCompleted(DeviceWatcher^ sender, Platform::Object^ args);
     1.8      void OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args);
     1.9      void OnDefaultCaptureDeviceChanged(Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args);
    1.10 +    SDL_semaphore* completed;
    1.11  
    1.12  private:
    1.13      const SDL_bool iscapture;
    1.14 @@ -72,20 +74,23 @@
    1.15      Windows::Foundation::EventRegistrationToken added_handler;
    1.16      Windows::Foundation::EventRegistrationToken removed_handler;
    1.17      Windows::Foundation::EventRegistrationToken updated_handler;
    1.18 +    Windows::Foundation::EventRegistrationToken completed_handler;
    1.19      Windows::Foundation::EventRegistrationToken default_changed_handler;
    1.20  };
    1.21  
    1.22  SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture)
    1.23      : iscapture(_iscapture)
    1.24 +    , completed(SDL_CreateSemaphore(0))
    1.25      , watcher(DeviceInformation::CreateWatcher(_iscapture ? DeviceClass::AudioCapture : DeviceClass::AudioRender))
    1.26  {
    1.27 -    if (!watcher)
    1.28 +    if (!watcher || !completed)
    1.29          return;  // uhoh.
    1.30  
    1.31      // !!! FIXME: this doesn't need a lambda here, I think, if I make SDL_WasapiDeviceEventHandler a proper C++/CX class. --ryan.
    1.32      added_handler = watcher->Added += ref new TypedEventHandler<DeviceWatcher^, DeviceInformation^>([this](DeviceWatcher^ sender, DeviceInformation^ args) { OnDeviceAdded(sender, args); } );
    1.33      removed_handler = watcher->Removed += ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceRemoved(sender, args); } );
    1.34      updated_handler = watcher->Updated += ref new TypedEventHandler<DeviceWatcher^, DeviceInformationUpdate^>([this](DeviceWatcher^ sender, DeviceInformationUpdate^ args) { OnDeviceUpdated(sender, args); } );
    1.35 +    completed_handler = watcher->EnumerationCompleted += ref new TypedEventHandler<DeviceWatcher^, Platform::Object^>([this](DeviceWatcher^ sender, Platform::Object^ args) { OnEnumerationCompleted(sender, args); } );
    1.36      if (iscapture) {
    1.37          default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler<Platform::Object^, DefaultAudioCaptureDeviceChangedEventArgs^>([this](Platform::Object^ sender, DefaultAudioCaptureDeviceChangedEventArgs^ args) { OnDefaultCaptureDeviceChanged(sender, args); } );
    1.38      } else {
    1.39 @@ -100,9 +105,14 @@
    1.40          watcher->Added -= added_handler;
    1.41          watcher->Removed -= removed_handler;
    1.42          watcher->Updated -= updated_handler;
    1.43 +        watcher->EnumerationCompleted -= completed_handler;
    1.44          watcher->Stop();
    1.45          watcher = nullptr;
    1.46      }
    1.47 +    if (completed) {
    1.48 +        SDL_DestroySemaphore(completed);
    1.49 +        completed = nullptr;
    1.50 +    }
    1.51  
    1.52      if (iscapture) {
    1.53          MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler;
    1.54 @@ -136,6 +146,13 @@
    1.55  }
    1.56  
    1.57  void
    1.58 +SDL_WasapiDeviceEventHandler::OnEnumerationCompleted(DeviceWatcher^ sender, Platform::Object^ args)
    1.59 +{
    1.60 +    SDL_assert(sender == this->watcher);
    1.61 +    SDL_SemPost(this->completed);
    1.62 +}
    1.63 +
    1.64 +void
    1.65  SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object^ sender, DefaultAudioRenderDeviceChangedEventArgs^ args)
    1.66  {
    1.67      SDL_assert(this->iscapture);
    1.68 @@ -173,6 +190,8 @@
    1.69      //  listening for updates.
    1.70      playback_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_FALSE);
    1.71      capture_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_TRUE);
    1.72 +    SDL_SemWait(playback_device_event_handler->completed);
    1.73 +    SDL_SemWait(capture_device_event_handler->completed);
    1.74  }
    1.75  
    1.76  struct SDL_WasapiActivationHandler : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >