[vlc-commits] wasapi: implement audio session events (fixes #7203)

Rémi Denis-Courmont git at videolan.org
Wed Aug 8 17:16:21 CEST 2012


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Aug  8 17:58:21 2012 +0300| [7e692c9ea721b7d7febbf7c7302e84e3a39d2e94] | committer: Rémi Denis-Courmont

wasapi: implement audio session events (fixes #7203)

This was not tested due to lack of hardware.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7e692c9ea721b7d7febbf7c7302e84e3a39d2e94
---

 modules/audio_output/wasapi.c |  163 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/modules/audio_output/wasapi.c b/modules/audio_output/wasapi.c
index 25532b7..af12649 100644
--- a/modules/audio_output/wasapi.c
+++ b/modules/audio_output/wasapi.c
@@ -24,6 +24,7 @@
 
 #define INITGUID
 #define COBJMACROS
+#define CONST_VTABLE
 
 #include <assert.h>
 #include <audioclient.h>
@@ -77,19 +78,26 @@ static void Leave(void)
 
 struct aout_sys_t
 {
+    audio_output_t *aout;
     IAudioClient *client;
     IAudioRenderClient *render;
     IAudioClock *clock;
+
     union
     {
         ISimpleAudioVolume *simple;
     } volume;
     IAudioSessionControl *control;
+    struct IAudioSessionEvents events;
+    LONG refs;
+
     UINT32 frames; /**< Total buffer size (frames) */
     HANDLE ready; /**< Semaphore from MTA thread */
     HANDLE done; /**< Semaphore to MTA thread */
 };
 
+
+/*** VLC audio output callbacks ***/
 static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
 {
     aout_sys_t *sys = aout->sys;
@@ -225,6 +233,8 @@ static int SimpleMuteSet(audio_output_t *aout, bool mute)
     return FAILED(hr) ? -1 : 0;
 }
 
+
+/*** Audio devices ***/
 static int DeviceChanged(vlc_object_t *obj, const char *varname,
                          vlc_value_t prev, vlc_value_t cur, void *data)
 {
@@ -304,6 +314,150 @@ static void GetDevices(vlc_object_t *obj, IMMDeviceEnumerator *it)
 }
 
 
+/*** Audio session events ***/
+static inline aout_sys_t *vlc_AudioSessionEvents_sys(IAudioSessionEvents *this)
+{
+    return (aout_sys_t *)(((char *)this) - offsetof(aout_sys_t, events));
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_QueryInterface(IAudioSessionEvents *this, REFIID riid,
+                                      void **ppv)
+{
+    if (IsEqualIID(riid, &IID_IUnknown)
+     || IsEqualIID(riid, &IID_IAudioSessionEvents))
+    {
+        *ppv = this;
+        IUnknown_AddRef(this);
+        return S_OK;
+    }
+    else
+    {
+       *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+static STDMETHODIMP_(ULONG)
+vlc_AudioSessionEvents_AddRef(IAudioSessionEvents *this)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    return InterlockedIncrement(&sys->refs);
+}
+
+static STDMETHODIMP_(ULONG)
+vlc_AudioSessionEvents_Release(IAudioSessionEvents *this)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    return InterlockedDecrement(&sys->refs);
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_OnDisplayNameChanged(IAudioSessionEvents *this,
+                                            LPCWSTR wname, LPCGUID ctx)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "display name changed: %ls", wname);
+    (void) ctx;
+    return S_OK;
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_OnIconPathChanged(IAudioSessionEvents *this,
+                                         LPCWSTR wpath, LPCGUID ctx)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "icon path changed: %ls", wpath);
+    (void) ctx;
+    return S_OK;
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_OnSimpleVolumeChanged(IAudioSessionEvents *this, float vol,
+                                             WINBOOL mute, LPCGUID ctx)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "simple volume changed: %f, muting %sabled", vol,
+            mute ? "en" : "dis");
+    aout_VolumeReport(aout, vol);
+    aout_MuteReport(aout, mute == TRUE);
+    (void) ctx;
+    return S_OK;
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_OnChannelVolumeChanged(IAudioSessionEvents *this,
+                                              DWORD count, float *vols,
+                                              DWORD changed, LPCGUID ctx)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "channel volume %lu of %lu changed: %f", changed, count,
+            vols[changed]);
+    (void) ctx;
+    return S_OK;
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_OnGroupingParamChanged(IAudioSessionEvents *this,
+                                              LPCGUID param, LPCGUID ctx)
+
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "grouping parameter changed");
+    (void) param;
+    (void) ctx;
+    return S_OK;
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_OnStateChanged(IAudioSessionEvents *this,
+                                      AudioSessionState state)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "state changed: %d", state);
+    return S_OK;
+}
+
+static STDMETHODIMP
+vlc_AudioSessionEvents_OnSessionDisconnected(IAudioSessionEvents *this,
+                                             AudioSessionDisconnectReason reason)
+{
+    aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "session disconnected: reason %d", reason);
+    return S_OK;
+}
+
+static const struct IAudioSessionEventsVtbl vlc_AudioSessionEvents =
+{
+    vlc_AudioSessionEvents_QueryInterface,
+    vlc_AudioSessionEvents_AddRef,
+    vlc_AudioSessionEvents_Release,
+
+    vlc_AudioSessionEvents_OnDisplayNameChanged,
+    vlc_AudioSessionEvents_OnIconPathChanged,
+    vlc_AudioSessionEvents_OnSimpleVolumeChanged,
+    vlc_AudioSessionEvents_OnChannelVolumeChanged,
+    vlc_AudioSessionEvents_OnGroupingParamChanged,
+    vlc_AudioSessionEvents_OnStateChanged,
+    vlc_AudioSessionEvents_OnSessionDisconnected,
+};
+
+
+/*** Initialization / deinitialization **/
 static void vlc_ToWave(WAVEFORMATEXTENSIBLE *restrict wf,
                        audio_sample_format_t *restrict audio)
 {
@@ -471,9 +625,12 @@ static int Open(vlc_object_t *obj)
     aout_sys_t *sys = malloc(sizeof (*sys));
     if (unlikely(sys == NULL))
         return VLC_ENOMEM;
+    sys->aout = aout;
     sys->client = NULL;
     sys->render = NULL;
     sys->clock = NULL;
+    sys->events.lpVtbl = &vlc_AudioSessionEvents;
+    sys->refs = 1;
     sys->ready = NULL;
     sys->done = NULL;
     aout->sys = sys;
@@ -610,6 +767,9 @@ retry:
         aout->volume_set = SimpleVolumeSet;
         aout->mute_set = SimpleMuteSet;
     }
+    if (likely(sys->control != NULL))
+       IAudioSessionControl_RegisterAudioSessionNotification(sys->control,
+                                                             &sys->events);
     var_AddCallback (aout, "audio-device", DeviceChanged, NULL);
 
     return VLC_SUCCESS;
@@ -637,6 +797,9 @@ static void Close (vlc_object_t *obj)
     aout_sys_t *sys = aout->sys;
 
     Enter();
+    if (likely(sys->control != NULL))
+       IAudioSessionControl_UnregisterAudioSessionNotification(sys->control,
+                                                               &sys->events);
     ReleaseSemaphore(sys->done, 1, NULL); /* tell MTA thread to finish */
     WaitForSingleObject(sys->ready, INFINITE); /* wait for that ^ */
     IAudioClient_Stop(sys->client); /* should not be needed */



More information about the vlc-commits mailing list