1 /*****************************************************************************
2 * sndio.c : sndio plugin for VLC
3 *****************************************************************************
4 * Copyright (C) 2012 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 *****************************************************************************/
28 #include <vlc_common.h>
29 #include <vlc_plugin.h>
34 static int Open (vlc_object_t
*);
35 static void Close (vlc_object_t
*);
38 set_shortname ("sndio")
39 set_description (N_("OpenBSD sndio audio output"))
40 set_category (CAT_AUDIO
)
41 set_subcategory (SUBCAT_AUDIO_AOUT
)
42 set_capability ("audio output", 120)
43 set_callbacks (Open
, Close
)
46 static int TimeGet (audio_output_t
*, mtime_t
*);
47 static void Play (audio_output_t
*, block_t
*);
48 static void Flush (audio_output_t
*, bool);
49 static int VolumeSet (audio_output_t
*, float);
50 static int MuteSet (audio_output_t
*, bool);
51 static void VolumeChanged (void *, unsigned);
52 static void PositionChanged (void *, int);
64 /** Initializes an sndio playback stream */
65 static int Start (audio_output_t
*aout
, audio_sample_format_t
*restrict fmt
)
67 aout_sys_t
*sys
= aout
->sys
;
69 if (aout_FormatNbChannels(fmt
) == 0)
72 sys
->hdl
= sio_open (NULL
, SIO_PLAY
, 0 /* blocking */);
75 msg_Err (aout
, "cannot create audio playback stream");
81 switch (fmt
->i_format
) {
89 par
.le
= SIO_LE_NATIVE
;
96 par
.le
= SIO_LE_NATIVE
;
99 /* use a common audio format */
102 par
.le
= SIO_LE_NATIVE
;
104 par
.pchan
= aout_FormatNbChannels (fmt
);
105 par
.rate
= fmt
->i_rate
;
106 par
.round
= par
.rate
/ 50;
107 par
.appbufsz
= par
.rate
/ 4;
109 if (!sio_setpar (sys
->hdl
, &par
) || !sio_getpar (sys
->hdl
, &par
))
111 msg_Err (aout
, "cannot negotiate audio playback parameters");
115 if (par
.bps
!= par
.bits
>> 3 && !par
.msb
)
117 msg_Err (aout
, "unsupported audio sample format (%u bits in %u bytes)",
121 if (par
.sig
!= (par
.bits
!= 8))
123 msg_Err (aout
, "unsupported audio sample format (%ssigned)",
124 par
.sig
? "" : "un");
127 if (par
.bps
> 1 && par
.le
!= SIO_LE_NATIVE
)
129 msg_Err (aout
, "unsupported audio sample format (%s endian)",
130 par
.le
? "little" : "big");
136 fmt
->i_format
= VLC_CODEC_U8
;
139 fmt
->i_format
= VLC_CODEC_S16N
;
142 fmt
->i_format
= VLC_CODEC_S32N
;
145 msg_Err (aout
, "unsupported audio sample format (%u bits)",
150 fmt
->i_rate
= par
.rate
;
151 sys
->rate
= par
.rate
;
158 chans
= AOUT_CHAN_CENTER
;
161 chans
= AOUT_CHANS_STEREO
;
164 chans
= AOUT_CHANS_4_0
;
167 chans
= AOUT_CHANS_5_1
;
170 chans
= AOUT_CHANS_7_1
;
173 msg_Err (aout
, "unknown %u channels map", par
.pchan
);
177 fmt
->channel_type
= AUDIO_CHANNEL_TYPE_BITMAP
;
178 fmt
->i_physical_channels
= chans
;
179 aout_FormatPrepare (fmt
);
181 aout
->time_get
= TimeGet
;
185 if (sio_onvol(sys
->hdl
, VolumeChanged
, aout
))
187 aout
->volume_set
= VolumeSet
;
188 aout
->mute_set
= MuteSet
;
192 aout
->volume_set
= NULL
;
193 aout
->mute_set
= NULL
;
198 sio_onmove (sys
->hdl
, PositionChanged
, aout
);
199 sio_start (sys
->hdl
);
203 sio_close (sys
->hdl
);
207 static void Stop (audio_output_t
*aout
)
209 aout_sys_t
*sys
= aout
->sys
;
211 sio_close (sys
->hdl
);
214 static void PositionChanged (void *arg
, int delta
)
216 audio_output_t
*aout
= arg
;
217 aout_sys_t
*sys
= aout
->sys
;
223 static int TimeGet (audio_output_t
*aout
, mtime_t
*restrict delay
)
225 aout_sys_t
*sys
= aout
->sys
;
229 *delay
= (mtime_t
)sys
->delay
* CLOCK_FREQ
/ sys
->rate
;
233 static void Play (audio_output_t
*aout
, block_t
*block
)
235 aout_sys_t
*sys
= aout
->sys
;
237 sio_write (sys
->hdl
, block
->p_buffer
, block
->i_buffer
);
238 sys
->delay
+= block
->i_nb_samples
;
239 block_Release (block
);
242 static void Flush (audio_output_t
*aout
, bool wait
)
244 aout_sys_t
*sys
= aout
->sys
;
249 sio_start (sys
->hdl
);
253 static void VolumeChanged (void *arg
, unsigned volume
)
255 audio_output_t
*aout
= arg
;
256 float fvol
= (float)volume
/ (float)SIO_MAXVOL
;
258 aout_VolumeReport (aout
, fvol
);
259 aout_MuteReport (aout
, volume
== 0);
260 if (volume
) /* remember last non-zero volume to unmute later */
261 aout
->sys
->volume
= volume
;
264 static int VolumeSet (audio_output_t
*aout
, float fvol
)
266 aout_sys_t
*sys
= aout
->sys
;
273 volume
= lroundf (fvol
* SIO_MAXVOL
);
274 if (!sys
->mute
&& !sio_setvol (sys
->hdl
, volume
))
276 sys
->volume
= volume
;
280 static int MuteSet (audio_output_t
*aout
, bool mute
)
282 aout_sys_t
*sys
= aout
->sys
;
284 if (!sio_setvol (sys
->hdl
, mute
? 0 : sys
->volume
))
291 static int Open (vlc_object_t
*obj
)
293 audio_output_t
*aout
= (audio_output_t
*)obj
;
294 aout_sys_t
*sys
= malloc (sizeof (*sys
));
295 if (unlikely(sys
== NULL
))
301 /* FIXME: set volume/mute here */
305 static void Close (vlc_object_t
*obj
)
307 audio_output_t
*aout
= (audio_output_t
*)obj
;
308 aout_sys_t
*sys
= aout
->sys
;