]> git.sesse.net Git - vlc/blobdiff - modules/audio_output/mmdevice.c
mmdevice: avoid incorrect assertion
[vlc] / modules / audio_output / mmdevice.c
index 2b5e332b8ef4279731cded1de34d5399355ad428..2f41567334a62f07168dacf1f4eed1ce1d6c153b 100644 (file)
 # include <config.h>
 #endif
 
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x600 /* Windows Vista */
 #define INITGUID
 #define COBJMACROS
 #define CONST_VTABLE
 
 #include <stdlib.h>
+#include <math.h>
 #include <assert.h>
 #include <audiopolicy.h>
 #include <mmdeviceapi.h>
@@ -43,9 +42,41 @@ 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);
 
+#if !VLC_WINSTORE_APP
 static int TryEnterMTA(vlc_object_t *obj)
 {
     HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
@@ -57,6 +88,7 @@ static int TryEnterMTA(vlc_object_t *obj)
     return 0;
 }
 #define TryEnterMTA(o) TryEnterMTA(VLC_OBJECT(o))
+#endif
 
 static void EnterMTA(void)
 {
@@ -70,7 +102,9 @@ static void LeaveMTA(void)
     CoUninitialize();
 }
 
+#if !VLC_WINSTORE_APP
 static wchar_t default_device[1] = L"";
+#endif
 
 struct aout_sys_t
 {
@@ -181,6 +215,7 @@ static int VolumeSet(audio_output_t *aout, float vol)
 {
     aout_sys_t *sys = aout->sys;
 
+    vol = vol * vol * vol; /* ISimpleAudioVolume is tapered linearly. */
     EnterCriticalSection(&sys->lock);
     sys->volume = vol;
     WakeConditionVariable(&sys->work);
@@ -271,7 +306,7 @@ vlc_AudioSessionEvents_OnSimpleVolumeChanged(IAudioSessionEvents *this,
 
     msg_Dbg(aout, "simple volume changed: %f, muting %sabled", vol,
             mute ? "en" : "dis");
-    aout_VolumeReport(aout, vol);
+    aout_VolumeReport(aout, cbrtf(vol));
     aout_MuteReport(aout, mute == TRUE);
     (void) ctx;
     return S_OK;
@@ -488,7 +523,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 */
@@ -694,7 +729,8 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
         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);
@@ -894,8 +930,10 @@ 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 !VLC_WINSTORE_APP
     if (sys->dev == NULL)
         return -1;
+#endif
 
     aout_stream_t *s = vlc_object_create(aout, sizeof (*s));
     if (unlikely(s == NULL))
@@ -915,7 +953,11 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 
         sys->module = vlc_module_load(s, "aout stream", NULL, false,
                                       aout_stream_Start, s, fmt, &hr);
-        if (hr != AUDCLNT_E_DEVICE_INVALIDATED || DeviceSelect(aout, NULL))
+        if (hr != AUDCLNT_E_DEVICE_INVALIDATED
+#if !VLC_WINSTORE_APP
+                || DeviceSelect(aout, NULL)
+#endif
+           )
             break;
     }
     LeaveMTA();
@@ -991,7 +1033,10 @@ 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");