]> git.sesse.net Git - vlc/blobdiff - modules/audio_output/mmdevice.c
stream_filter: smooth: minor optimization
[vlc] / modules / audio_output / mmdevice.c
index 394d4b331345e765dfd9f2414c0cc4ee6c908944..d9d3573d0f1845930707dd1dc9e6a7215bb77259 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * mmdevice.c : Windows Multimedia Device API audio output plugin for VLC
  *****************************************************************************
- * Copyright (C) 2012 Rémi Denis-Courmont
+ * Copyright (C) 2012-2014 Rémi Denis-Courmont
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
@@ -22,8 +22,6 @@
 # include <config.h>
 #endif
 
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x600 /* Windows Vista */
 #define INITGUID
 #define COBJMACROS
 #define CONST_VTABLE
@@ -33,6 +31,7 @@
 #include <assert.h>
 #include <audiopolicy.h>
 #include <mmdeviceapi.h>
+#include <endpointvolume.h>
 
 DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd,
    0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
@@ -44,6 +43,37 @@ DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd,
 #include <vlc_modules.h>
 #include "audio_output/mmdevice.h"
 
+#if (_WIN32_WINNT < 0x600)
+static VOID WINAPI (*InitializeConditionVariable)(PCONDITION_VARIABLE);
+static BOOL WINAPI (*SleepConditionVariableCS)(PCONDITION_VARIABLE,
+                                               PCRITICAL_SECTION, DWORD);
+static VOID WINAPI (*WakeConditionVariable)(PCONDITION_VARIABLE);
+#define LOOKUP(s) \
+    if (((s) = (void *)GetProcAddress(h, #s)) == NULL) return FALSE
+
+BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID); /* avoid warning */
+BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
+{
+    (void) dll;
+    (void) reserved;
+
+    switch (reason)
+    {
+        case DLL_PROCESS_ATTACH:
+        {
+            HANDLE h = GetModuleHandle(TEXT("kernel32.dll"));
+            if (unlikely(h == NULL))
+                return FALSE;
+            LOOKUP(InitializeConditionVariable);
+            LOOKUP(SleepConditionVariableCS);
+            LOOKUP(WakeConditionVariable);
+            break;
+        }
+    }
+    return TRUE;
+}
+#endif
+
 DEFINE_GUID (GUID_VLC_AUD_OUT, 0x4533f59d, 0x59ee, 0x00c6,
    0xad, 0xb2, 0xc6, 0x8b, 0x50, 0x1a, 0x66, 0x55);
 
@@ -77,15 +107,17 @@ struct aout_sys_t
 {
     aout_stream_t *stream; /**< Underlying audio output stream */
     module_t *module;
-#if !VLC_WINSTORE_APP
     audio_output_t *aout;
     IMMDeviceEnumerator *it; /**< Device enumerator, NULL when exiting */
     IMMDevice *dev; /**< Selected output device, NULL if none */
 
     struct IMMNotificationClient device_events;
     struct IAudioSessionEvents session_events;
+    struct IAudioVolumeDuckNotification duck;
 
     LONG refs;
+    unsigned ducks;
+    float gain; /**< Current software gain volume */
 
     wchar_t *device; /**< Requested device identifier, NULL if none */
     float volume; /**< Requested volume, negative if none */
@@ -94,9 +126,6 @@ struct aout_sys_t
     CONDITION_VARIABLE work;
     CONDITION_VARIABLE ready;
     vlc_thread_t thread; /**< Thread for audio session control */
-#else
-    void *client;
-#endif
 };
 
 /* NOTE: The Core Audio API documentation totally fails to specify the thread
@@ -162,28 +191,27 @@ static void Flush(audio_output_t *aout, bool wait)
     aout_sys_t *sys = aout->sys;
 
     EnterMTA();
-
-    if (wait)
-    {   /* Loosy drain emulation */
-        mtime_t delay;
-
-        if (SUCCEEDED(aout_stream_TimeGet(sys->stream, &delay)))
-            Sleep((delay / (CLOCK_FREQ / 1000)) + 1);
-    }
-    else
-        aout_stream_Flush(sys->stream);
-
+    aout_stream_Flush(sys->stream, wait);
     LeaveMTA();
-
 }
 
-#if !VLC_WINSTORE_APP
 static int VolumeSet(audio_output_t *aout, float vol)
 {
     aout_sys_t *sys = aout->sys;
+    float gain = 1.f;
 
     vol = vol * vol * vol; /* ISimpleAudioVolume is tapered linearly. */
+
+    if (vol > 1.f)
+    {
+        gain = vol;
+        vol = 1.f;
+    }
+
+    aout_GainRequest(aout, gain);
+
     EnterCriticalSection(&sys->lock);
+    sys->gain = gain;
     sys->volume = vol;
     WakeConditionVariable(&sys->work);
     LeaveCriticalSection(&sys->lock);
@@ -265,7 +293,7 @@ vlc_AudioSessionEvents_OnIconPathChanged(IAudioSessionEvents *this,
 
 static STDMETHODIMP
 vlc_AudioSessionEvents_OnSimpleVolumeChanged(IAudioSessionEvents *this,
-                                             float vol, WINBOOL mute,
+                                             float vol, BOOL mute,
                                              LPCGUID ctx)
 {
     aout_sys_t *sys = vlc_AudioSessionEvents_sys(this);
@@ -273,8 +301,9 @@ vlc_AudioSessionEvents_OnSimpleVolumeChanged(IAudioSessionEvents *this,
 
     msg_Dbg(aout, "simple volume changed: %f, muting %sabled", vol,
             mute ? "en" : "dis");
-    aout_VolumeReport(aout, cbrtf(vol));
-    aout_MuteReport(aout, mute == TRUE);
+    EnterCriticalSection(&sys->lock);
+    WakeConditionVariable(&sys->work); /* implicit state: vol & mute */
+    LeaveCriticalSection(&sys->lock);
     (void) ctx;
     return S_OK;
 }
@@ -287,8 +316,12 @@ vlc_AudioSessionEvents_OnChannelVolumeChanged(IAudioSessionEvents *this,
     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]);
+    if (changed != (DWORD)-1)
+        msg_Dbg(aout, "channel volume %lu of %lu changed: %f", changed, count,
+                vols[changed]);
+    else
+        msg_Dbg(aout, "%lu channels volume changed", count);
+
     (void) ctx;
     return S_OK;
 }
@@ -368,6 +401,80 @@ static const struct IAudioSessionEventsVtbl vlc_AudioSessionEvents =
     vlc_AudioSessionEvents_OnSessionDisconnected,
 };
 
+static inline aout_sys_t *vlc_AudioVolumeDuckNotification_sys(IAudioVolumeDuckNotification *this)
+{
+    return (void *)(((char *)this) - offsetof(aout_sys_t, duck));
+}
+
+static STDMETHODIMP
+vlc_AudioVolumeDuckNotification_QueryInterface(
+    IAudioVolumeDuckNotification *this, REFIID riid, void **ppv)
+{
+    if (IsEqualIID(riid, &IID_IUnknown)
+     || IsEqualIID(riid, &IID_IAudioVolumeDuckNotification))
+    {
+        *ppv = this;
+        IUnknown_AddRef(this);
+        return S_OK;
+    }
+    else
+    {
+       *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+}
+
+static STDMETHODIMP_(ULONG)
+vlc_AudioVolumeDuckNotification_AddRef(IAudioVolumeDuckNotification *this)
+{
+    aout_sys_t *sys = vlc_AudioVolumeDuckNotification_sys(this);
+    return InterlockedIncrement(&sys->refs);
+}
+
+static STDMETHODIMP_(ULONG)
+vlc_AudioVolumeDuckNotification_Release(IAudioVolumeDuckNotification *this)
+{
+    aout_sys_t *sys = vlc_AudioVolumeDuckNotification_sys(this);
+    return InterlockedDecrement(&sys->refs);
+}
+
+static STDMETHODIMP
+vlc_AudioVolumeDuckNotification_OnVolumeDuckNotification(
+    IAudioVolumeDuckNotification *this, LPCWSTR sid, UINT32 count)
+{
+    aout_sys_t *sys = vlc_AudioVolumeDuckNotification_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "volume ducked by %ls of %u sessions", sid, count);
+    sys->ducks++;
+    aout_PolicyReport(aout, true);
+    return S_OK;
+}
+
+static STDMETHODIMP
+vlc_AudioVolumeDuckNotification_OnVolumeUnduckNotification(
+    IAudioVolumeDuckNotification *this, LPCWSTR sid)
+{
+    aout_sys_t *sys = vlc_AudioVolumeDuckNotification_sys(this);
+    audio_output_t *aout = sys->aout;
+
+    msg_Dbg(aout, "volume unducked by %ls", sid);
+    sys->ducks--;
+    aout_PolicyReport(aout, sys->ducks != 0);
+    return S_OK;
+}
+
+static const struct IAudioVolumeDuckNotificationVtbl vlc_AudioVolumeDuckNotification =
+{
+    vlc_AudioVolumeDuckNotification_QueryInterface,
+    vlc_AudioVolumeDuckNotification_AddRef,
+    vlc_AudioVolumeDuckNotification_Release,
+
+    vlc_AudioVolumeDuckNotification_OnVolumeDuckNotification,
+    vlc_AudioVolumeDuckNotification_OnVolumeUnduckNotification,
+};
+
+
 /*** Audio devices ***/
 
 /** Gets the user-readable device name */
@@ -490,7 +597,7 @@ vlc_MMNotificationClient_OnDefaultDeviceChange(IMMNotificationClient *this,
 
     if (flow != eRender)
         return S_OK;
-    if (role != eConsole) /* FIXME? use eMultimedia instead */
+    if (role != eConsole)
         return S_OK;
 
     msg_Dbg(aout, "default device changed: %ls", wid); /* TODO? migrate */
@@ -538,9 +645,9 @@ vlc_MMNotificationClient_OnDeviceStateChanged(IMMNotificationClient *this,
 }
 
 static STDMETHODIMP
-vlc_MMNotificationClient_OnDevicePropertyChanged(IMMNotificationClient *this,
-                                                 LPCWSTR wid,
-                                                 const PROPERTYKEY key)
+vlc_MMNotificationClient_OnPropertyValueChanged(IMMNotificationClient *this,
+                                                LPCWSTR wid,
+                                                const PROPERTYKEY key)
 {
     aout_sys_t *sys = vlc_MMNotificationClient_sys(this);
     audio_output_t *aout = sys->aout;
@@ -563,7 +670,7 @@ static const struct IMMNotificationClientVtbl vlc_MMNotificationClient =
     vlc_MMNotificationClient_OnDeviceAdded,
     vlc_MMNotificationClient_OnDeviceRemoved,
     vlc_MMNotificationClient_OnDefaultDeviceChange,
-    vlc_MMNotificationClient_OnDevicePropertyChanged,
+    vlc_MMNotificationClient_OnPropertyValueChanged,
 };
 
 static int DevicesEnum(audio_output_t *aout, IMMDeviceEnumerator *it)
@@ -680,6 +787,7 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
     IAudioSessionManager *manager;
     IAudioSessionControl *control;
     ISimpleAudioVolume *volume;
+    IAudioEndpointVolume *endpoint;
     void *pv;
     HRESULT hr;
 
@@ -690,16 +798,22 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
     {
         msg_Dbg(aout, "using selected device %ls", sys->device);
         hr = IMMDeviceEnumerator_GetDevice(it, sys->device, &sys->dev);
+        if (FAILED(hr))
+            msg_Err(aout, "cannot get selected device %ls (error 0x%lx)",
+                    sys->device, hr);
         free(sys->device);
     }
     else
         hr = AUDCLNT_E_DEVICE_INVALIDATED;
 
     while (hr == AUDCLNT_E_DEVICE_INVALIDATED)
-    {   /* Default device selected by policy */
+    {   /* Default device selected by policy and with stream routing.
+         * "Do not use eMultimedia" says MSDN. */
         msg_Dbg(aout, "using default device");
         hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(it, eRender,
                                                          eConsole, &sys->dev);
+        if (FAILED(hr))
+            msg_Err(aout, "cannot get default device (error 0x%lx)", hr);
     }
 
     sys->device = NULL;
@@ -723,7 +837,7 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
     }
     else
     {
-        msg_Err(aout, "cannot get device (error 0x%lx)", hr);
+        msg_Err(aout, "cannot get device identifier (error 0x%lx)", hr);
         return hr;
     }
 
@@ -752,25 +866,41 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
 
         hr = IAudioSessionManager_GetSimpleAudioVolume(manager, guid, FALSE,
                                                        &volume);
+        if (FAILED(hr))
+            msg_Err(aout, "cannot get simple volume (error 0x%lx)", hr);
+
+        /* Try to get version 2 (Windows 7) of the manager & control */
+        wchar_t *siid = NULL;
+
+        hr = IAudioSessionManager_QueryInterface(manager,
+                                              &IID_IAudioSessionControl2, &pv);
         if (SUCCEEDED(hr))
-        {   /* Get current values _after_ registering for notification */
-            BOOL mute;
-            float level;
+        {
+            IAudioSessionControl2 *c2 = pv;
 
-            hr = ISimpleAudioVolume_GetMute(volume, &mute);
-            if (SUCCEEDED(hr))
-                aout_MuteReport(aout, mute != FALSE);
-            else
-                msg_Err(aout, "cannot get mute (error 0x%lx)", hr);
+            IAudioSessionControl2_SetDuckingPreference(c2, FALSE);
+            hr = IAudioSessionControl2_GetSessionInstanceIdentifier(c2, &siid);
+            if (FAILED(hr))
+                siid = NULL;
+            IAudioSessionControl2_Release(c2);
+        }
+        else
+            msg_Dbg(aout, "version 2 session control unavailable");
 
-            hr = ISimpleAudioVolume_GetMasterVolume(volume, &level);
-            if (SUCCEEDED(hr))
-                aout_VolumeReport(aout, level);
-            else
-                msg_Err(aout, "cannot get mute (error 0x%lx)", hr);
+        hr = IAudioSessionManager_QueryInterface(manager,
+                                              &IID_IAudioSessionManager2, &pv);
+        if (SUCCEEDED(hr))
+        {
+            IAudioSessionManager2 *m2 = pv;
+
+            IAudioSessionManager2_RegisterDuckNotification(m2, siid,
+                                                           &sys->duck);
+            IAudioSessionManager2_Release(m2);
         }
         else
-            msg_Err(aout, "cannot get simple volume (error 0x%lx)", hr);
+            msg_Dbg(aout, "version 2 session management unavailable");
+
+        CoTaskMemFree(siid);
     }
     else
     {
@@ -779,32 +909,84 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
         volume = NULL;
     }
 
+    hr = IMMDevice_Activate(sys->dev, &IID_IAudioEndpointVolume,
+                            CLSCTX_ALL, NULL, &pv);
+    endpoint = pv;
+    if (SUCCEEDED(hr))
+    {
+        float min, max, inc;
+
+        hr = IAudioEndpointVolume_GetVolumeRange(endpoint, &min, &max, &inc);
+        if (SUCCEEDED(hr))
+            msg_Dbg(aout, "volume from %+f dB to %+f dB with %f dB increments",
+                    min, max, inc);
+        else
+            msg_Err(aout, "cannot get volume range (error 0x%lx)", hr);
+    }
+    else
+        msg_Err(aout, "cannot activate endpoint volume (error %lx)", hr);
+
     /* Main loop (adjust volume as long as device is unchanged) */
     while (sys->device == NULL)
     {
-        if (volume != NULL && sys->volume >= 0.f)
+        if (volume != NULL)
         {
-            hr = ISimpleAudioVolume_SetMasterVolume(volume, sys->volume, NULL);
-            if (FAILED(hr))
-                msg_Err(aout, "cannot set master volume (error 0x%lx)", hr);
+            float level;
+
+            hr = ISimpleAudioVolume_GetMasterVolume(volume, &level);
+            if (SUCCEEDED(hr))
+                aout_VolumeReport(aout, cbrtf(level * sys->gain));
+            else
+                msg_Err(aout, "cannot get master volume (error 0x%lx)", hr);
+
+            level = sys->volume;
+            if (level >= 0.f)
+            {
+                hr = ISimpleAudioVolume_SetMasterVolume(volume, level, NULL);
+                if (FAILED(hr))
+                    msg_Err(aout, "cannot set master volume (error 0x%lx)",
+                            hr);
+            }
             sys->volume = -1.f;
-        }
 
-        if (volume != NULL && sys->mute >= 0)
-        {
-            hr = ISimpleAudioVolume_SetMute(volume,
-                                            sys->mute ? TRUE : FALSE, NULL);
-            if (FAILED(hr))
-                msg_Err(aout, "cannot set mute (error 0x%lx)", hr);
+            BOOL mute;
+
+            hr = ISimpleAudioVolume_GetMute(volume, &mute);
+            if (SUCCEEDED(hr))
+                aout_MuteReport(aout, mute != FALSE);
+            else
+                msg_Err(aout, "cannot get mute (error 0x%lx)", hr);
+
+            if (sys->mute >= 0)
+            {
+                mute = sys->mute ? TRUE : FALSE;
+
+                hr = ISimpleAudioVolume_SetMute(volume, mute, NULL);
+                if (FAILED(hr))
+                    msg_Err(aout, "cannot set mute (error 0x%lx)", hr);
+            }
             sys->mute = -1;
         }
 
         SleepConditionVariableCS(&sys->work, &sys->lock, INFINITE);
     }
+    LeaveCriticalSection(&sys->lock);
+
+    if (endpoint != NULL)
+        IAudioEndpointVolume_Release(endpoint);
 
     if (manager != NULL)
-    {
-        /* Deregister session control */
+    {   /* Deregister callbacks *without* the lock */
+        hr = IAudioSessionManager_QueryInterface(manager,
+                                              &IID_IAudioSessionManager2, &pv);
+        if (SUCCEEDED(hr))
+        {
+            IAudioSessionManager2 *m2 = pv;
+
+            IAudioSessionManager2_UnregisterDuckNotification(m2, &sys->duck);
+            IAudioSessionManager2_Release(m2);
+        }
+
         if (volume != NULL)
             ISimpleAudioVolume_Release(volume);
 
@@ -818,6 +1000,7 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
         IAudioSessionManager_Release(manager);
     }
 
+    EnterCriticalSection(&sys->lock);
     IMMDevice_Release(sys->dev);
     sys->dev = NULL;
     return S_OK;
@@ -860,17 +1043,6 @@ static HRESULT ActivateDevice(void *opaque, REFIID iid, PROPVARIANT *actparms,
     IMMDevice *dev = opaque;
     return IMMDevice_Activate(dev, iid, CLSCTX_ALL, actparms, pv);
 }
-#else /* VLC_WINSTORE_APP */
-static HRESULT ActivateDevice(void *opaque, REFIID iid, PROPVARIANT *actparms,
-                              void **restrict pv)
-{
-    aout_sys_t *sys = opaque;
-
-    (void)iid; (void)actparms;
-    *pv = sys->client;
-    return S_OK;
-}
-#endif /* VLC_WINSTORE_APP */
 
 static int aout_stream_Start(void *func, va_list ap)
 {
@@ -896,6 +1068,7 @@ static void aout_stream_Stop(void *func, va_list ap)
 static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
     aout_sys_t *sys = aout->sys;
+
     if (sys->dev == NULL)
         return -1;
 
@@ -903,11 +1076,7 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
     if (unlikely(s == NULL))
         return -1;
 
-#if !VLC_WINSTORE_APP
     s->owner.device = sys->dev;
-#else
-    s->owner.device = sys->client;
-#endif
     s->owner.activate = ActivateDevice;
 
     EnterMTA();
@@ -915,7 +1084,8 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
     {
         HRESULT hr;
 
-        sys->module = vlc_module_load(s, "aout stream", NULL, false,
+        /* TODO: Do not overload the "aout" configuration item. */
+        sys->module = vlc_module_load(s, "aout stream", "$aout", false,
                                       aout_stream_Start, s, fmt, &hr);
         if (hr != AUDCLNT_E_DEVICE_INVALIDATED || DeviceSelect(aout, NULL))
             break;
@@ -930,6 +1100,7 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 
     assert (sys->stream == NULL);
     sys->stream = s;
+    aout_GainRequest(aout, sys->gain);
     return 0;
 }
 
@@ -937,7 +1108,7 @@ static void Stop(audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
 
-    assert (sys->stream != NULL);
+    assert(sys->stream != NULL);
 
     EnterMTA();
     vlc_module_unload(sys->module, aout_stream_Stop, sys->stream);
@@ -957,14 +1128,17 @@ static int Open(vlc_object_t *obj)
 
     aout->sys = sys;
     sys->stream = NULL;
-#if !VLC_WINSTORE_APP
     sys->aout = aout;
     sys->it = NULL;
     sys->dev = NULL;
+    sys->device_events.lpVtbl = &vlc_MMNotificationClient;
     sys->session_events.lpVtbl = &vlc_AudioSessionEvents;
+    sys->duck.lpVtbl = &vlc_AudioVolumeDuckNotification;
     sys->refs = 1;
+    sys->ducks = 0;
 
     sys->device = default_device;
+    sys->gain = 1.f;
     sys->volume = -1.f;
     sys->mute = -1;
     InitializeCriticalSection(&sys->lock);
@@ -993,19 +1167,18 @@ static int Open(vlc_object_t *obj)
         goto error;
     }
 
-    DeviceSelect(aout, NULL);
+    EnterCriticalSection(&sys->lock);
+    while (sys->device != NULL)
+        SleepConditionVariableCS(&sys->ready, &sys->lock, INFINITE);
+    LeaveCriticalSection(&sys->lock);
     LeaveMTA(); /* Leave MTA after thread has entered MTA */
-#else
-    sys->client = var_InheritAddress(aout, "mmdevice-audioclient");
-    assert(sys->client != NULL);
-#endif
+
     aout->start = Start;
     aout->stop = Stop;
     aout->time_get = TimeGet;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
-#if !VLC_WINSTORE_APP
     aout->volume_set = VolumeSet;
     aout->mute_set = MuteSet;
     aout->device_select = DeviceSelect;
@@ -1015,16 +1188,13 @@ error:
     DeleteCriticalSection(&sys->lock);
     free(sys);
     return VLC_EGENERIC;
-#else
-    return VLC_SUCCESS;
-#endif
 }
 
 static void Close(vlc_object_t *obj)
 {
     audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = aout->sys;
-#if !VLC_WINSTORE_APP
+
     EnterCriticalSection(&sys->lock);
     sys->device = default_device; /* break out of MMSession() loop */
     sys->it = NULL; /* break out of MMThread() loop */
@@ -1033,9 +1203,6 @@ static void Close(vlc_object_t *obj)
 
     vlc_join(sys->thread, NULL);
     DeleteCriticalSection(&sys->lock);
-#else
-    free(sys->client);
-#endif
     free(sys);
 }
 
@@ -1043,12 +1210,8 @@ vlc_module_begin()
     set_shortname("MMDevice")
     set_description(N_("Windows Multimedia Device output"))
     set_capability("audio output", 150)
-#if VLC_WINSTORE_APP
-    /* Pointer to the activated AudioClient* */
-    add_integer("mmdevice-audioclient", 0x0, NULL, NULL, true);
-#endif
     set_category(CAT_AUDIO)
     set_subcategory(SUBCAT_AUDIO_AOUT)
-    add_shortcut("wasapi")
+    add_shortcut("wasapi", "directsound")
     set_callbacks(Open, Close)
 vlc_module_end()