]> git.sesse.net Git - vlc/blob - modules/audio_output/winstore.c
direct3d11: catch texture mapping errors
[vlc] / modules / audio_output / winstore.c
1 /*****************************************************************************
2  * mmdevice.c : Windows Multimedia Device API audio output plugin for VLC
3  *****************************************************************************
4  * Copyright (C) 2012 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #define INITGUID
26 #define COBJMACROS
27
28 #include <stdlib.h>
29 #include <assert.h>
30 #include <audiopolicy.h>
31
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_aout.h>
35 #include <vlc_modules.h>
36 #include "audio_output/mmdevice.h"
37
38 DEFINE_GUID (GUID_VLC_AUD_OUT, 0x4533f59d, 0x59ee, 0x00c6,
39    0xad, 0xb2, 0xc6, 0x8b, 0x50, 0x1a, 0x66, 0x55);
40
41 static void EnterMTA(void)
42 {
43     HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
44     if (unlikely(FAILED(hr)))
45         abort();
46 }
47
48 static void LeaveMTA(void)
49 {
50     CoUninitialize();
51 }
52
53 struct aout_sys_t
54 {
55     aout_stream_t *stream; /**< Underlying audio output stream */
56     module_t *module;
57     IAudioClient *client;
58 };
59
60 static int TimeGet(audio_output_t *aout, mtime_t *restrict delay)
61 {
62     aout_sys_t *sys = aout->sys;
63     HRESULT hr;
64
65     EnterMTA();
66     hr = aout_stream_TimeGet(sys->stream, delay);
67     LeaveMTA();
68
69     return SUCCEEDED(hr) ? 0 : -1;
70 }
71
72 static void Play(audio_output_t *aout, block_t *block)
73 {
74     aout_sys_t *sys = aout->sys;
75
76     EnterMTA();
77     aout_stream_Play(sys->stream, block);
78     LeaveMTA();
79 }
80
81 static void Pause(audio_output_t *aout, bool paused, mtime_t date)
82 {
83     aout_sys_t *sys = aout->sys;
84
85     EnterMTA();
86     aout_stream_Pause(sys->stream, paused);
87     LeaveMTA();
88
89     (void) date;
90 }
91
92 static void Flush(audio_output_t *aout, bool wait)
93 {
94     aout_sys_t *sys = aout->sys;
95
96     EnterMTA();
97     aout_stream_Flush(sys->stream, wait);
98     LeaveMTA();
99 }
100
101 static HRESULT ActivateDevice(void *opaque, REFIID iid, PROPVARIANT *actparms,
102                               void **restrict pv)
103 {
104     IAudioClient *client = opaque;
105
106     if (!IsEqualIID(iid, &IID_IAudioClient))
107         return E_NOINTERFACE;
108     if (actparms != NULL)
109         return E_INVALIDARG;
110
111     IAudioClient_AddRef(client);
112     *pv = opaque;
113
114     return S_OK;
115 }
116
117 static int aout_stream_Start(void *func, va_list ap)
118 {
119     aout_stream_start_t start = func;
120     aout_stream_t *s = va_arg(ap, aout_stream_t *);
121     audio_sample_format_t *fmt = va_arg(ap, audio_sample_format_t *);
122     HRESULT *hr = va_arg(ap, HRESULT *);
123
124     *hr = start(s, fmt, &GUID_VLC_AUD_OUT);
125     return SUCCEEDED(*hr) ? VLC_SUCCESS : VLC_EGENERIC;
126 }
127
128 static void aout_stream_Stop(void *func, va_list ap)
129 {
130     aout_stream_stop_t stop = func;
131     aout_stream_t *s = va_arg(ap, aout_stream_t *);
132
133     stop(s);
134 }
135
136 static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
137 {
138     aout_sys_t *sys = aout->sys;
139     HRESULT hr;
140
141     aout_stream_t *s = vlc_object_create(aout, sizeof (*s));
142     if (unlikely(s == NULL))
143         return -1;
144
145     s->owner.device = sys->client;
146     s->owner.activate = ActivateDevice;
147
148     EnterMTA();
149     sys->module = vlc_module_load(s, "aout stream", NULL, false,
150                                   aout_stream_Start, s, fmt, &hr);
151     LeaveMTA();
152
153     if (sys->module == NULL)
154     {
155         vlc_object_release(s);
156         return -1;
157     }
158
159     assert (sys->stream == NULL);
160     sys->stream = s;
161     return 0;
162 }
163
164 static void Stop(audio_output_t *aout)
165 {
166     aout_sys_t *sys = aout->sys;
167
168     assert (sys->stream != NULL);
169
170     EnterMTA();
171     vlc_module_unload(sys->module, aout_stream_Stop, sys->stream);
172     LeaveMTA();
173
174     vlc_object_release(sys->stream);
175     sys->stream = NULL;
176 }
177
178 static int Open(vlc_object_t *obj)
179 {
180     audio_output_t *aout = (audio_output_t *)obj;
181
182     IAudioClient* client = var_InheritInteger(aout, "winstore-audioclient");
183     if (client == NULL)
184         return VLC_EGENERIC;
185
186     aout_sys_t *sys = malloc(sizeof (*sys));
187     if (unlikely(sys == NULL))
188         return VLC_ENOMEM;
189
190     aout->sys = sys;
191     sys->stream = NULL;
192     sys->client = client;
193     aout->start = Start;
194     aout->stop = Stop;
195     aout->time_get = TimeGet;
196     aout->play = Play;
197     aout->pause = Pause;
198     aout->flush = Flush;
199     return VLC_SUCCESS;
200 }
201
202 static void Close(vlc_object_t *obj)
203 {
204     audio_output_t *aout = (audio_output_t *)obj;
205     aout_sys_t *sys = aout->sys;
206
207     free(sys);
208 }
209
210 vlc_module_begin()
211     set_shortname("winstore")
212     set_description(N_("Windows Store audio output"))
213     set_capability("audio output", 150)
214     /* Pointer to the activated AudioClient* */
215     add_integer("winstore-audioclient", 0x0, NULL, NULL, true);
216     set_category(CAT_AUDIO)
217     set_subcategory(SUBCAT_AUDIO_AOUT)
218     add_shortcut("wasapi")
219     set_callbacks(Open, Close)
220 vlc_module_end()