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 *****************************************************************************/
25 #include <vlc_common.h>
26 #include <vlc_plugin.h>
30 static int Open (vlc_object_t
*);
31 static void Close (vlc_object_t
*);
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)
44 add_integer ("amem-rate", 44100,
45 N_("Sample rate"), N_("Sample rate"), false)
46 change_integer_range (1, 352800)
48 add_integer ("amem-channels", 2,
49 N_("Channels count"), N_("Channels count"), false)
50 change_integer_range (1, AOUT_CHAN_MAX
)
58 int (*setup
) (void **, char *, unsigned *, unsigned *);
59 void (*cleanup
) (void *opaque
);
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
);
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
;
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
;
114 vlc_mutex_lock(&sys
->lock
);
116 vlc_mutex_unlock(&sys
->lock
);
120 static int VolumeSet (audio_output_t
*aout
, float vol
)
122 aout_sys_t
*sys
= aout
->sys
;
127 vlc_mutex_lock(&sys
->lock
);
129 val
= sys
->set_volume(sys
->opaque
, vol
, sys
->mute
);
131 val
= 0; /* sys->opaque is not yet defined... */
132 vlc_mutex_unlock(&sys
->lock
);
137 static int MuteSet (audio_output_t
*aout
, bool mute
)
139 aout_sys_t
*sys
= aout
->sys
;
144 vlc_mutex_lock(&sys
->lock
);
146 val
= sys
->set_volume(sys
->opaque
, sys
->volume
, mute
);
148 val
= 0; /* sys->opaque is not yet defined... */
149 vlc_mutex_unlock(&sys
->lock
);
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
))
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
))
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
);
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";
193 if (aout_FormatNbChannels(fmt
) == 0)
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
);
210 fmt
->i_rate
= sys
->rate
;
211 channels
= sys
->channels
;
214 /* Initialize volume (in case the UI changed volume before setup) */
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
);
231 /* channel mapping */
235 fmt
->i_physical_channels
= AOUT_CHAN_CENTER
;
238 fmt
->i_physical_channels
= AOUT_CHANS_2_0
;
241 fmt
->i_physical_channels
= AOUT_CHANS_2_1
;
244 fmt
->i_physical_channels
= AOUT_CHANS_4_0
;
247 fmt
->i_physical_channels
= AOUT_CHANS_5_0
;
250 fmt
->i_physical_channels
= AOUT_CHANS_5_1
;
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
;
259 fmt
->i_physical_channels
= AOUT_CHANS_7_1
;
262 vlc_assert_unreachable();
265 fmt
->i_format
= VLC_CODEC_S16N
;
266 fmt
->channel_type
= AUDIO_CHANNEL_TYPE_BITMAP
;
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
))
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
;
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");
301 vlc_mutex_init(&sys
->lock
);
303 if (sys
->play
== NULL
)
312 aout
->time_get
= aout_TimeGetDefault
;
316 if (sys
->set_volume
!= NULL
)
318 aout
->volume_set
= VolumeSet
;
319 aout
->mute_set
= MuteSet
;
323 aout
->volume_set
= SoftVolumeSet
;
324 aout
->mute_set
= SoftMuteSet
;
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
);