Commit d52d2efd authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont
Browse files

mmdevice: split out Store code

parent e5267d38
......@@ -487,6 +487,7 @@ AS_IF([test "${SYS}" = "mingw32" -a "${enable_winstore_app}" = "yes"], [
VLC_ADD_LIBS([libvlccore], [-lole32 -lruntimeobject])
])
AC_DEFINE_UNQUOTED(VLC_WINSTORE_APP, ${vlc_winstore_app}, [Define to 1 if you want to build for Windows Store apps])
AM_CONDITIONAL([HAVE_WINSTORE], [test "$vlc_winstore_app" = "1"])
dnl
......
......@@ -59,10 +59,17 @@ endif
libmmdevice_plugin_la_SOURCES = audio_output/mmdevice.c audio_output/mmdevice.h
libmmdevice_plugin_la_LIBADD = -lole32 $(LIBM)
libwinstore_plugin_la_SOURCES = audio_output/winstore.c audio_output/mmdevice.h
libwinstore_plugin_la_LIBADD = -lole32
libwasapi_plugin_la_SOURCES = audio_output/wasapi.c
libwasapi_plugin_la_LIBADD = -lole32 -lksuser
if HAVE_WASAPI
aout_LTLIBRARIES += libmmdevice_plugin.la libwasapi_plugin.la
aout_LTLIBRARIES += libwasapi_plugin.la
if !HAVE_WINSTORE
aout_LTLIBRARIES += libmmdevice_plugin.la
else
aout_LTLIBRARIES += libwinstore_plugin.la
endif
endif
libdirectsound_plugin_la_SOURCES = audio_output/directsound.c \
......
/*****************************************************************************
* mmdevice.c : Windows Multimedia Device API audio output plugin for VLC
*****************************************************************************
* Copyright (C) 2012 Rémi Denis-Courmont
* Copyright (C) 2012-2013 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
......@@ -76,7 +76,6 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
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);
......@@ -88,7 +87,6 @@ static int TryEnterMTA(vlc_object_t *obj)
return 0;
}
#define TryEnterMTA(o) TryEnterMTA(VLC_OBJECT(o))
#endif
static void EnterMTA(void)
{
......@@ -102,15 +100,12 @@ static void LeaveMTA(void)
CoUninitialize();
}
#if !VLC_WINSTORE_APP
static wchar_t default_device[1] = L"";
#endif
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 */
......@@ -127,9 +122,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
......@@ -195,22 +187,11 @@ 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;
......@@ -894,17 +875,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)
{
......@@ -930,20 +900,15 @@ 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))
return -1;
#if !VLC_WINSTORE_APP
s->owner.device = sys->dev;
#else
s->owner.device = sys->client;
#endif
s->owner.activate = ActivateDevice;
EnterMTA();
......@@ -953,11 +918,7 @@ 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
#if !VLC_WINSTORE_APP
|| DeviceSelect(aout, NULL)
#endif
)
if (hr != AUDCLNT_E_DEVICE_INVALIDATED || DeviceSelect(aout, NULL))
break;
}
LeaveMTA();
......@@ -997,7 +958,6 @@ 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;
......@@ -1038,17 +998,13 @@ static int Open(vlc_object_t *obj)
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;
......@@ -1058,16 +1014,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 */
......@@ -1076,9 +1029,6 @@ static void Close(vlc_object_t *obj)
vlc_join(sys->thread, NULL);
DeleteCriticalSection(&sys->lock);
#else
free(sys->client);
#endif
free(sys);
}
......@@ -1086,10 +1036,6 @@ 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")
......
......@@ -72,9 +72,18 @@ static inline HRESULT aout_stream_Pause(aout_stream_t *s, bool paused)
return (s->pause)(s, paused);
}
static inline HRESULT aout_stream_Flush(aout_stream_t *s)
static inline HRESULT aout_stream_Flush(aout_stream_t *s, bool wait)
{
return (s->flush)(s);
if (wait)
{ /* Loosy drain emulation */
mtime_t delay;
if (SUCCEEDED(aout_stream_TimeGet(s, &delay)))
Sleep((delay / (CLOCK_FREQ / 1000)) + 1);
return S_OK;
}
else
return (s->flush)(s);
}
static inline
......
/*****************************************************************************
* mmdevice.c : Windows Multimedia Device API audio output plugin for VLC
*****************************************************************************
* Copyright (C) 2012 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
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define INITGUID
#define COBJMACROS
#include <stdlib.h>
#include <assert.h>
#include <audiopolicy.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_aout.h>
#include <vlc_modules.h>
#include "audio_output/mmdevice.h"
DEFINE_GUID (GUID_VLC_AUD_OUT, 0x4533f59d, 0x59ee, 0x00c6,
0xad, 0xb2, 0xc6, 0x8b, 0x50, 0x1a, 0x66, 0x55);
static void EnterMTA(void)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (unlikely(FAILED(hr)))
abort();
}
static void LeaveMTA(void)
{
CoUninitialize();
}
struct aout_sys_t
{
aout_stream_t *stream; /**< Underlying audio output stream */
module_t *module;
IAudioClient *client;
};
static int TimeGet(audio_output_t *aout, mtime_t *restrict delay)
{
aout_sys_t *sys = aout->sys;
HRESULT hr;
EnterMTA();
hr = aout_stream_TimeGet(sys->stream, delay);
LeaveMTA();
return SUCCEEDED(hr) ? 0 : -1;
}
static void Play(audio_output_t *aout, block_t *block)
{
aout_sys_t *sys = aout->sys;
EnterMTA();
aout_stream_Play(sys->stream, block);
LeaveMTA();
}
static void Pause(audio_output_t *aout, bool paused, mtime_t date)
{
aout_sys_t *sys = aout->sys;
EnterMTA();
aout_stream_Pause(sys->stream, paused);
LeaveMTA();
(void) date;
}
static void Flush(audio_output_t *aout, bool wait)
{
aout_sys_t *sys = aout->sys;
EnterMTA();
aout_stream_Flush(sys->stream, wait);
LeaveMTA();
}
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;
}
static int aout_stream_Start(void *func, va_list ap)
{
aout_stream_start_t start = func;
aout_stream_t *s = va_arg(ap, aout_stream_t *);
audio_sample_format_t *fmt = va_arg(ap, audio_sample_format_t *);
HRESULT *hr = va_arg(ap, HRESULT *);
*hr = start(s, fmt, &GUID_VLC_AUD_OUT);
return SUCCEEDED(*hr) ? VLC_SUCCESS : VLC_EGENERIC;
}
static void aout_stream_Stop(void *func, va_list ap)
{
aout_stream_stop_t stop = func;
aout_stream_t *s = va_arg(ap, aout_stream_t *);
stop(s);
}
static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
aout_sys_t *sys = aout->sys;
HRESULT hr;
aout_stream_t *s = vlc_object_create(aout, sizeof (*s));
if (unlikely(s == NULL))
return -1;
s->owner.device = sys->client;
s->owner.activate = ActivateDevice;
EnterMTA();
sys->module = vlc_module_load(s, "aout stream", NULL, false,
aout_stream_Start, s, fmt, &hr);
LeaveMTA();
if (sys->module == NULL)
{
vlc_object_release(s);
return -1;
}
assert (sys->stream == NULL);
sys->stream = s;
return 0;
}
static void Stop(audio_output_t *aout)
{
aout_sys_t *sys = aout->sys;
assert (sys->stream != NULL);
EnterMTA();
vlc_module_unload(sys->module, aout_stream_Stop, sys->stream);
LeaveMTA();
vlc_object_release(sys->stream);
sys->stream = NULL;
}
static int Open(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = malloc(sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
aout->sys = sys;
sys->stream = NULL;
sys->client = var_InheritAddress(aout, "mmdevice-audioclient");
assert(sys->client != NULL);
aout->start = Start;
aout->stop = Stop;
aout->time_get = TimeGet;
aout->play = Play;
aout->pause = Pause;
aout->flush = Flush;
return VLC_SUCCESS;
}
static void Close(vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
free(sys->client);
free(sys);
}
vlc_module_begin()
set_shortname("winstore")
set_description(N_("Windows Store audio output"))
set_capability("audio output", 150)
/* Pointer to the activated AudioClient* */
add_integer("winstore-audioclient", 0x0, NULL, NULL, true);
set_category(CAT_AUDIO)
set_subcategory(SUBCAT_AUDIO_AOUT)
add_shortcut("wasapi")
set_callbacks(Open, Close)
vlc_module_end()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment