input/clock: (docs) fix old function name
[vlc.git] / modules / audio_output / amem.c
blobdb90fc250ad11b5e723421db53d3b087a3ac0fb8
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 struct aout_sys_t
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;
83 static void Play (audio_output_t *aout, block_t *block)
85 aout_sys_t *sys = aout->sys;
87 sys->play (sys->opaque, block->p_buffer, block->i_nb_samples,
88 block->i_pts);
89 block_Release (block);
92 static void Pause (audio_output_t *aout, bool paused, mtime_t date)
94 aout_sys_t *sys = aout->sys;
95 void (*cb) (void *, int64_t) = paused ? sys->pause : sys->resume;
97 if (cb != NULL)
98 cb (sys->opaque, date);
101 static void Flush (audio_output_t *aout, bool wait)
103 aout_sys_t *sys = aout->sys;
104 void (*cb) (void *) = wait ? sys->drain : sys->flush;
106 if (cb != NULL)
107 cb (sys->opaque);
110 static int VolumeSet (audio_output_t *aout, float vol)
112 aout_sys_t *sys = aout->sys;
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;
120 static int MuteSet (audio_output_t *aout, bool mute)
122 aout_sys_t *sys = aout->sys;
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;
130 static int SoftVolumeSet (audio_output_t *aout, float vol)
132 aout_sys_t *sys = aout->sys;
134 vol = vol * vol * vol;
135 if (!sys->mute && aout_GainRequest (aout, vol))
136 return -1;
137 sys->volume = vol;
138 return 0;
141 static int SoftMuteSet (audio_output_t *aout, bool mute)
143 aout_sys_t *sys = aout->sys;
145 if (aout_GainRequest (aout, mute ? 0.f : sys->volume))
146 return -1;
147 sys->mute = mute;
148 return 0;
151 static void Stop (audio_output_t *aout)
153 aout_sys_t *sys = aout->sys;
155 if (sys->cleanup != NULL)
156 sys->cleanup (sys->opaque);
157 sys->ready = false;
160 static int Start (audio_output_t *aout, audio_sample_format_t *fmt)
162 aout_sys_t *sys = aout->sys;
163 char format[5] = "S16N";
164 unsigned channels;
166 if (aout_FormatNbChannels(fmt) == 0)
167 return VLC_EGENERIC;
169 if (sys->setup != NULL)
171 channels = aout_FormatNbChannels(fmt);
173 sys->opaque = sys->setup_opaque;
174 if (sys->setup (&sys->opaque, format, &fmt->i_rate, &channels))
175 return VLC_EGENERIC;
177 else
179 fmt->i_rate = sys->rate;
180 channels = sys->channels;
183 /* Initialize volume (in case the UI changed volume before setup) */
184 sys->ready = true;
185 if (sys->set_volume != NULL)
186 sys->set_volume(sys->opaque, sys->volume, sys->mute);
188 /* Ensure that format is supported */
189 if (fmt->i_rate == 0 || fmt->i_rate > 192000
190 || channels == 0 || channels > AOUT_CHAN_MAX
191 || strcmp(format, "S16N") /* TODO: amem-format */)
193 msg_Err (aout, "format not supported: %s, %u channel(s), %u Hz",
194 format, channels, fmt->i_rate);
195 Stop (aout);
196 return VLC_EGENERIC;
199 /* channel mapping */
200 switch (channels)
202 case 1:
203 fmt->i_physical_channels = AOUT_CHAN_CENTER;
204 break;
205 case 2:
206 fmt->i_physical_channels = AOUT_CHANS_2_0;
207 break;
208 case 3:
209 fmt->i_physical_channels = AOUT_CHANS_2_1;
210 break;
211 case 4:
212 fmt->i_physical_channels = AOUT_CHANS_4_0;
213 break;
214 case 5:
215 fmt->i_physical_channels = AOUT_CHANS_5_0;
216 break;
217 case 6:
218 fmt->i_physical_channels = AOUT_CHANS_5_1;
219 break;
220 case 7:
221 fmt->i_physical_channels =
222 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
223 AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT |
224 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
225 break;
226 case 8:
227 fmt->i_physical_channels = AOUT_CHANS_7_1;
228 break;
229 default:
230 vlc_assert_unreachable();
233 fmt->i_format = VLC_CODEC_S16N;
234 fmt->channel_type = AUDIO_CHANNEL_TYPE_BITMAP;
235 return VLC_SUCCESS;
238 static int Open (vlc_object_t *obj)
240 audio_output_t *aout = (audio_output_t *)obj;
241 aout_sys_t *sys = malloc (sizeof (*sys));
242 if (unlikely(sys == NULL))
243 return VLC_ENOMEM;
245 void *opaque = var_InheritAddress (obj, "amem-data");
246 sys->setup = var_InheritAddress (obj, "amem-setup");
247 if (sys->setup != NULL)
249 sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
250 sys->setup_opaque = opaque;
252 else
254 sys->cleanup = NULL;
255 sys->opaque = opaque;
256 sys->rate = var_InheritInteger (obj, "amem-rate");
257 sys->channels = var_InheritInteger (obj, "amem-channels");
259 sys->play = var_InheritAddress (obj, "amem-play");
260 sys->pause = var_InheritAddress (obj, "amem-pause");
261 sys->resume = var_InheritAddress (obj, "amem-resume");
262 sys->flush = var_InheritAddress (obj, "amem-flush");
263 sys->drain = var_InheritAddress (obj, "amem-drain");
264 sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
265 sys->volume = 1.;
266 sys->mute = false;
267 sys->ready = false;
268 if (sys->play == NULL)
270 free (sys);
271 return VLC_EGENERIC;
274 aout->sys = sys;
275 aout->start = Start;
276 aout->stop = Stop;
277 aout->time_get = NULL;
278 aout->play = Play;
279 aout->pause = Pause;
280 aout->flush = Flush;
281 if (sys->set_volume != NULL)
283 aout->volume_set = VolumeSet;
284 aout->mute_set = MuteSet;
286 else
288 aout->volume_set = SoftVolumeSet;
289 aout->mute_set = SoftMuteSet;
291 return VLC_SUCCESS;
294 static void Close (vlc_object_t *obj)
296 audio_output_t *aout = (audio_output_t *)obj;
297 aout_sys_t *sys = aout->sys;
299 free (sys);