input: add an input_item_t arg to input_CreateFilename()
[vlc.git] / modules / audio_output / amem.c
blobdcba84c32dc76a7b0326d894652f1962f167459b
1 /*****************************************************************************
2 * amem.c : virtual LibVLC audio output plugin
3 *****************************************************************************
4 * Copyright (C) 2011 RĂ©mi Denis-Courmont
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.
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.
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 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include <vlc_common.h>
26 #include <vlc_plugin.h>
27 #include <vlc_aout.h>
28 #include <assert.h>
30 static int Open (vlc_object_t *);
31 static void Close (vlc_object_t *);
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)
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()
53 vlc_module_end ()
55 typedef struct
57 void *opaque;
58 int (*setup) (void **, char *, unsigned *, unsigned *);
59 void (*cleanup) (void *opaque);
60 union
62 struct
64 void *setup_opaque;
66 struct
68 unsigned rate:18;
69 unsigned channels:14;
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 vlc_mutex_t lock;
82 } aout_sys_t;
84 static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
86 aout_sys_t *sys = aout->sys;
88 vlc_mutex_lock(&sys->lock);
89 sys->play(sys->opaque, block->p_buffer, block->i_nb_samples, date);
90 vlc_mutex_unlock(&sys->lock);
91 block_Release (block);
94 static void Pause (audio_output_t *aout, bool paused, vlc_tick_t date)
96 aout_sys_t *sys = aout->sys;
97 void (*cb) (void *, int64_t) = paused ? sys->pause : sys->resume;
99 if (cb != NULL)
101 vlc_mutex_lock(&sys->lock);
102 cb (sys->opaque, date);
103 vlc_mutex_unlock(&sys->lock);
107 static void Flush (audio_output_t *aout, bool wait)
109 aout_sys_t *sys = aout->sys;
110 void (*cb) (void *) = wait ? sys->drain : sys->flush;
112 if (cb != NULL)
114 vlc_mutex_lock(&sys->lock);
115 cb (sys->opaque);
116 vlc_mutex_unlock(&sys->lock);
120 static int VolumeSet (audio_output_t *aout, float vol)
122 aout_sys_t *sys = aout->sys;
123 int val;
125 sys->volume = vol;
127 vlc_mutex_lock(&sys->lock);
128 if (sys->ready)
129 val = sys->set_volume(sys->opaque, vol, sys->mute);
130 else
131 val = 0; /* sys->opaque is not yet defined... */
132 vlc_mutex_unlock(&sys->lock);
134 return val ? -1 : 0;
137 static int MuteSet (audio_output_t *aout, bool mute)
139 aout_sys_t *sys = aout->sys;
140 int val;
142 sys->mute = mute;
144 vlc_mutex_lock(&sys->lock);
145 if (sys->ready)
146 val = sys->set_volume(sys->opaque, sys->volume, mute);
147 else
148 val = 0; /* sys->opaque is not yet defined... */
149 vlc_mutex_unlock(&sys->lock);
151 return val ? -1 : 0;
154 static int SoftVolumeSet (audio_output_t *aout, float vol)
156 aout_sys_t *sys = aout->sys;
158 vol = vol * vol * vol;
159 if (!sys->mute && aout_GainRequest (aout, vol))
160 return -1;
161 sys->volume = vol;
162 return 0;
165 static int SoftMuteSet (audio_output_t *aout, bool mute)
167 aout_sys_t *sys = aout->sys;
169 if (aout_GainRequest (aout, mute ? 0.f : sys->volume))
170 return -1;
171 sys->mute = mute;
172 return 0;
175 static void Stop (audio_output_t *aout)
177 aout_sys_t *sys = aout->sys;
179 vlc_mutex_lock(&sys->lock);
180 if (sys->cleanup != NULL)
181 sys->cleanup (sys->opaque);
183 sys->ready = false;
184 vlc_mutex_unlock(&sys->lock);
187 static int Start (audio_output_t *aout, audio_sample_format_t *fmt)
189 aout_sys_t *sys = aout->sys;
190 char format[5] = "S16N";
191 unsigned channels;
193 if (aout_FormatNbChannels(fmt) == 0)
194 return VLC_EGENERIC;
196 vlc_mutex_lock(&sys->lock);
197 if (sys->setup != NULL)
199 channels = aout_FormatNbChannels(fmt);
201 sys->opaque = sys->setup_opaque;
202 if (sys->setup (&sys->opaque, format, &fmt->i_rate, &channels))
204 vlc_mutex_unlock(&sys->lock);
205 return VLC_EGENERIC;
208 else
210 fmt->i_rate = sys->rate;
211 channels = sys->channels;
214 /* Initialize volume (in case the UI changed volume before setup) */
215 sys->ready = true;
216 if (sys->set_volume != NULL)
217 sys->set_volume(sys->opaque, sys->volume, sys->mute);
218 vlc_mutex_unlock(&sys->lock);
220 /* Ensure that format is supported */
221 if (fmt->i_rate == 0 || fmt->i_rate > 192000
222 || channels == 0 || channels > AOUT_CHAN_MAX
223 || strcmp(format, "S16N") /* TODO: amem-format */)
225 msg_Err (aout, "format not supported: %s, %u channel(s), %u Hz",
226 format, channels, fmt->i_rate);
227 Stop (aout);
228 return VLC_EGENERIC;
231 /* channel mapping */
232 switch (channels)
234 case 1:
235 fmt->i_physical_channels = AOUT_CHAN_CENTER;
236 break;
237 case 2:
238 fmt->i_physical_channels = AOUT_CHANS_2_0;
239 break;
240 case 3:
241 fmt->i_physical_channels = AOUT_CHANS_2_1;
242 break;
243 case 4:
244 fmt->i_physical_channels = AOUT_CHANS_4_0;
245 break;
246 case 5:
247 fmt->i_physical_channels = AOUT_CHANS_5_0;
248 break;
249 case 6:
250 fmt->i_physical_channels = AOUT_CHANS_5_1;
251 break;
252 case 7:
253 fmt->i_physical_channels =
254 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
255 AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT |
256 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
257 break;
258 case 8:
259 fmt->i_physical_channels = AOUT_CHANS_7_1;
260 break;
261 default:
262 vlc_assert_unreachable();
265 fmt->i_format = VLC_CODEC_S16N;
266 fmt->channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
267 return VLC_SUCCESS;
270 static int Open (vlc_object_t *obj)
272 audio_output_t *aout = (audio_output_t *)obj;
273 aout_sys_t *sys = malloc (sizeof (*sys));
274 if (unlikely(sys == NULL))
275 return VLC_ENOMEM;
277 void *opaque = var_InheritAddress (obj, "amem-data");
278 sys->setup = var_InheritAddress (obj, "amem-setup");
279 if (sys->setup != NULL)
281 sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
282 sys->setup_opaque = opaque;
284 else
286 sys->cleanup = NULL;
287 sys->opaque = opaque;
288 sys->rate = var_InheritInteger (obj, "amem-rate");
289 sys->channels = var_InheritInteger (obj, "amem-channels");
292 sys->play = var_InheritAddress (obj, "amem-play");
293 sys->pause = var_InheritAddress (obj, "amem-pause");
294 sys->resume = var_InheritAddress (obj, "amem-resume");
295 sys->flush = var_InheritAddress (obj, "amem-flush");
296 sys->drain = var_InheritAddress (obj, "amem-drain");
297 sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
298 sys->volume = 1.;
299 sys->mute = false;
300 sys->ready = false;
301 vlc_mutex_init(&sys->lock);
303 if (sys->play == NULL)
305 free (sys);
306 return VLC_EGENERIC;
309 aout->sys = sys;
310 aout->start = Start;
311 aout->stop = Stop;
312 aout->time_get = aout_TimeGetDefault;
313 aout->play = Play;
314 aout->pause = Pause;
315 aout->flush = Flush;
316 if (sys->set_volume != NULL)
318 aout->volume_set = VolumeSet;
319 aout->mute_set = MuteSet;
321 else
323 aout->volume_set = SoftVolumeSet;
324 aout->mute_set = SoftMuteSet;
326 return VLC_SUCCESS;
329 static void Close (vlc_object_t *obj)
331 audio_output_t *aout = (audio_output_t *)obj;
332 aout_sys_t *sys = aout->sys;
334 vlc_mutex_destroy(&sys->lock);
335 free (sys);