]> git.sesse.net Git - vlc/blob - modules/audio_output/amem.c
direct3d11: catch texture mapping errors
[vlc] / modules / audio_output / amem.c
1 /*****************************************************************************
2  * amem.c : virtual LibVLC audio output plugin
3  *****************************************************************************
4  * Copyright (C) 2011 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 #include <vlc_common.h>
26 #include <vlc_plugin.h>
27 #include <vlc_aout.h>
28 #include <assert.h>
29
30 static int Open (vlc_object_t *);
31 static void Close (vlc_object_t *);
32
33 vlc_module_begin ()
34     set_shortname (N_("Audio memory"))
35     set_description (N_("Audio memory output"))
36     set_capability ("audio output", 0)
37     set_category (CAT_AUDIO)
38     set_subcategory (SUBCAT_AUDIO_AOUT)
39     set_callbacks (Open, Close)
40
41     add_string ("amem-format", "S16N",
42                 N_("Sample format"), N_("Sample format"), false)
43         change_private()
44     add_integer ("amem-rate", 44100,
45                  N_("Sample rate"), N_("Sample rate"), false)
46         change_integer_range (1, 352800)
47         change_private()
48     add_integer ("amem-channels", 2,
49                  N_("Channels count"), N_("Channels count"), false)
50         change_integer_range (1, AOUT_CHAN_MAX)
51         change_private()
52
53 vlc_module_end ()
54
55 struct aout_sys_t
56 {
57     void *opaque;
58     int (*setup) (void **, char *, unsigned *, unsigned *);
59     void (*cleanup) (void *opaque);
60     union
61     {
62         struct
63         {
64             void *setup_opaque;
65         };
66         struct
67         {
68              unsigned rate:18;
69              unsigned channels:14;
70         };
71     };
72     void (*play) (void *opaque, const void *data, unsigned count, int64_t pts);
73     void (*pause) (void *opaque, int64_t pts);
74     void (*resume) (void *opaque, int64_t pts);
75     void (*flush) (void *opaque);
76     void (*drain) (void *opaque);
77     int (*set_volume) (void *opaque, float vol, bool mute);
78     float volume;
79     bool mute;
80     bool ready;
81 };
82
83 static void Play (audio_output_t *aout, block_t *block)
84 {
85     aout_sys_t *sys = aout->sys;
86
87     sys->play (sys->opaque, block->p_buffer, block->i_nb_samples,
88                block->i_pts);
89     block_Release (block);
90 }
91
92 static void Pause (audio_output_t *aout, bool paused, mtime_t date)
93 {
94     aout_sys_t *sys = aout->sys;
95     void (*cb) (void *, int64_t) = paused ? sys->pause : sys->resume;
96
97     if (cb != NULL)
98         cb (sys->opaque, date);
99 }
100
101 static void Flush (audio_output_t *aout, bool wait)
102 {
103     aout_sys_t *sys = aout->sys;
104     void (*cb) (void *) = wait ? sys->drain : sys->flush;
105
106     if (cb != NULL)
107         cb (sys->opaque);
108 }
109
110 static int VolumeSet (audio_output_t *aout, float vol)
111 {
112     aout_sys_t *sys = aout->sys;
113
114     sys->volume = vol;
115     if (sys->ready)
116         return 0; /* sys->opaque is not yet defined... */
117     return sys->set_volume (sys->opaque, vol, sys->mute) ? -1 : 0;
118 }
119
120 static int MuteSet (audio_output_t *aout, bool mute)
121 {
122     aout_sys_t *sys = aout->sys;
123
124     sys->mute = mute;
125     if (!sys->ready)
126         return 0; /* sys->opaque is not yet defined... */
127     return sys->set_volume (sys->opaque, sys->volume, mute) ? -1 : 0;
128 }
129
130 static int SoftVolumeSet (audio_output_t *aout, float vol)
131 {
132     aout_sys_t *sys = aout->sys;
133
134     vol = vol * vol * vol;
135     if (!sys->mute && aout_GainRequest (aout, vol))
136         return -1;
137     sys->volume = vol;
138     return 0;
139 }
140
141 static int SoftMuteSet (audio_output_t *aout, bool mute)
142 {
143     aout_sys_t *sys = aout->sys;
144
145     if (aout_GainRequest (aout, mute ? 0.f : sys->volume))
146         return -1;
147     sys->mute = mute;
148     return 0;
149 }
150
151 static void Stop (audio_output_t *aout)
152 {
153     aout_sys_t *sys = aout->sys;
154
155     if (sys->cleanup != NULL)
156         sys->cleanup (sys->opaque);
157     sys->ready = false;
158 }
159
160 static int Start (audio_output_t *aout, audio_sample_format_t *fmt)
161 {
162     aout_sys_t *sys = aout->sys;
163     char format[5] = "S16N";
164     unsigned channels;
165
166     if (sys->setup != NULL)
167     {
168         channels = aout_FormatNbChannels(fmt);
169
170         sys->opaque = sys->setup_opaque;
171         if (sys->setup (&sys->opaque, format, &fmt->i_rate, &channels))
172             return VLC_EGENERIC;
173     }
174     else
175     {
176         fmt->i_rate = sys->rate;
177         channels = sys->channels;
178     }
179
180     /* Initialize volume (in case the UI changed volume before setup) */
181     sys->ready = true;
182     if (sys->set_volume != NULL)
183         sys->set_volume(sys->opaque, sys->volume, sys->mute);
184
185     /* Ensure that format is supported */
186     if (fmt->i_rate == 0 || fmt->i_rate > 192000
187      || channels == 0 || channels > AOUT_CHAN_MAX
188      || strcmp(format, "S16N") /* TODO: amem-format */)
189     {
190         msg_Err (aout, "format not supported: %s, %u channel(s), %u Hz",
191                  format, channels, fmt->i_rate);
192         Stop (aout);
193         return VLC_EGENERIC;
194     }
195
196     /* channel mapping */
197     switch (channels)
198     {
199         case 1:
200             fmt->i_physical_channels = AOUT_CHAN_CENTER;
201             break;
202         case 2:
203             fmt->i_physical_channels = AOUT_CHANS_2_0;
204             break;
205         case 3:
206             fmt->i_physical_channels = AOUT_CHANS_2_1;
207             break;
208         case 4:
209             fmt->i_physical_channels = AOUT_CHANS_4_0;
210             break;
211         case 5:
212             fmt->i_physical_channels = AOUT_CHANS_5_0;
213             break;
214         case 6:
215             fmt->i_physical_channels = AOUT_CHANS_5_1;
216             break;
217         case 7:
218             fmt->i_physical_channels =
219                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
220                 AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT |
221                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
222             break;
223         case 8:
224             fmt->i_physical_channels = AOUT_CHANS_7_1;
225             break;
226         default:
227             vlc_assert_unreachable();
228     }
229
230     fmt->i_format = VLC_CODEC_S16N;
231     fmt->i_original_channels = fmt->i_physical_channels;
232     return VLC_SUCCESS;
233 }
234
235 static int Open (vlc_object_t *obj)
236 {
237     audio_output_t *aout = (audio_output_t *)obj;
238     aout_sys_t *sys = malloc (sizeof (*sys));
239     if (unlikely(sys == NULL))
240         return VLC_ENOMEM;
241
242     void *opaque = var_InheritAddress (obj, "amem-data");
243     sys->setup = var_InheritAddress (obj, "amem-setup");
244     if (sys->setup != NULL)
245     {
246         sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
247         sys->setup_opaque = opaque;
248     }
249     else
250     {
251         sys->cleanup = NULL;
252         sys->opaque = opaque;
253         sys->rate = var_InheritInteger (obj, "amem-rate");
254         sys->channels = var_InheritInteger (obj, "amem-channels");
255     }
256     sys->play = var_InheritAddress (obj, "amem-play");
257     sys->pause = var_InheritAddress (obj, "amem-pause");
258     sys->resume = var_InheritAddress (obj, "amem-resume");
259     sys->flush = var_InheritAddress (obj, "amem-flush");
260     sys->drain = var_InheritAddress (obj, "amem-drain");
261     sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
262     sys->volume = 1.;
263     sys->mute = false;
264     sys->ready = false;
265     if (sys->play == NULL)
266     {
267         free (sys);
268         return VLC_EGENERIC;
269     }
270
271     aout->sys = sys;
272     aout->start = Start;
273     aout->stop = Stop;
274     aout->time_get = NULL;
275     aout->play = Play;
276     aout->pause = Pause;
277     aout->flush = Flush;
278     if (sys->set_volume != NULL)
279     {
280         aout->volume_set = VolumeSet;
281         aout->mute_set = MuteSet;
282     }
283     else
284     {
285         aout->volume_set = SoftVolumeSet;
286         aout->mute_set = SoftMuteSet;
287     }
288     return VLC_SUCCESS;
289 }
290
291 static void Close (vlc_object_t *obj)
292 {
293     audio_output_t *aout = (audio_output_t *)obj;
294     aout_sys_t *sys = aout->sys;
295
296     free (sys);
297 }