5 * * Listening v4l compatible radio cards using line-in or
7 * * Grabbing audio data using -ao pcm or -dumpaudio
8 * (must be compiled with --enable-radio-capture).
10 * Initially written by Vladimir Voroshilov <voroshil@univer.omsk.su>.
11 * Based on tv.c and tvi_v4l2.c code.
13 * This file is part of MPlayer.
15 * MPlayer is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * MPlayer is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License along
26 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <sys/ioctl.h>
38 #ifdef CONFIG_RADIO_BSDBT848
39 #include <sys/param.h>
40 #ifdef IOCTL_BT848_H_NAME
41 #include IOCTL_BT848_H_NAME
44 #else /* CONFIG_RADIO_BSDBT848 */
46 #include <linux/types.h>
48 #ifdef CONFIG_RADIO_V4L2
49 #include <linux/videodev2.h>
52 #ifdef CONFIG_RADIO_V4L
53 #include <linux/videodev.h>
54 #warning "V4L is deprecated and will be removed in future"
57 #endif // !IOCTL_BT848_H_NAME
61 #include "libmpdemux/demuxer.h"
66 #include "stream_radio.h"
67 #include "libavutil/avstring.h"
69 #ifdef CONFIG_RADIO_CAPTURE
72 #ifdef HAVE_SYS_SOUNDCARD_H
73 #include <sys/soundcard.h>
75 #ifdef HAVE_SOUNDCARD_H
76 #include <soundcard.h>
78 #include <linux/soundcard.h>
84 typedef struct radio_channels_s
{
85 int index
; ///< channel index in channels list
86 float freq
; ///< frequency in MHz
87 char name
[20]; ///< channel name
88 struct radio_channels_s
* next
;
89 struct radio_channels_s
* prev
;
92 /// default values for options
93 radio_param_t stream_radio_defaults
={
94 #ifdef CONFIG_RADIO_BSDBT848
95 "/dev/tuner0", //device
99 "/dev/radio0", //device;
111 typedef struct radio_priv_s
{
112 int radio_fd
; ///< radio device descriptor
113 int frac
; ///< fraction value (see comment to init_frac)
114 radio_channels_t
* radio_channel_list
;
115 radio_channels_t
* radio_channel_current
;
116 float rangelow
; ///< lowest tunable frequency in MHz
117 float rangehigh
; ///< highest tunable frequency in MHz
118 const struct radio_driver_s
* driver
;
120 #ifdef CONFIG_RADIO_CAPTURE
121 volatile int do_capture
; ///< is capture enabled
123 unsigned char* audio_ringbuffer
;
124 int audio_head
; ///< start of meanfull data in ringbuffer
125 int audio_tail
; ///< end of meanfull data in ringbuffer
126 int audio_buffer_size
; ///< size of ringbuffer
127 int audio_cnt
; ///< size of meanfull data inringbuffer
128 int audio_drop
; ///< number of dropped bytes
129 int audio_initialized
;
131 radio_param_t
*radio_param
;
134 typedef struct radio_driver_s
{
137 int (*init_frac
)(radio_priv_t
* priv
);
138 void (*set_volume
)(radio_priv_t
* priv
,int volume
);
139 int (*get_volume
)(radio_priv_t
* priv
,int* volume
);
140 int (*set_frequency
)(radio_priv_t
* priv
,float frequency
);
141 int (*get_frequency
)(radio_priv_t
* priv
,float* frequency
);
144 #define ST_OFF(f) M_ST_OFF(radio_param_t,f)
145 static const m_option_t stream_opts_fields
[] = {
146 {"hostname", ST_OFF(freq_channel
), CONF_TYPE_FLOAT
, 0, 0 ,0, NULL
},
147 {"filename", ST_OFF(capture
), CONF_TYPE_STRING
, 0, 0 ,0, NULL
},
148 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
151 static const struct m_struct_st stream_opts
= {
153 sizeof(radio_param_t
),
154 &stream_radio_defaults
,
158 static void close_s(struct stream_st
* stream
);
159 #ifdef CONFIG_RADIO_CAPTURE
160 static int clear_buffer(radio_priv_t
* priv
);
164 /*****************************************************************
165 * \brief parse channels parameter and store result into list
166 * \param freq_channel if channels!=NULL this mean channel number, otherwise - frequency
167 * \param pfreq selected frequency (from selected channel or from URL)
168 * \result STREAM_OK if success, STREAM_ERROR otherwise
170 * channels option must be in the following format
171 * <frequency>-<name>,<frequency>-<name>,...
173 * '_' will be replaced with spaces.
175 * If channels option is not null, number in movie URL will be treated as
176 * channel position in channel list.
178 static int parse_channels(radio_priv_t
* priv
,float freq_channel
,float* pfreq
){
182 if (priv
->radio_param
->channels
){
183 /*parsing channels string*/
184 channels
=priv
->radio_param
->channels
;
186 mp_msg(MSGT_RADIO
, MSGL_INFO
, MSGTR_RADIO_ChannelNamesDetected
);
187 priv
->radio_channel_list
= malloc(sizeof(radio_channels_t
));
188 priv
->radio_channel_list
->index
=1;
189 priv
->radio_channel_list
->next
=NULL
;
190 priv
->radio_channel_list
->prev
=NULL
;
191 priv
->radio_channel_current
= priv
->radio_channel_list
;
194 char* tmp
= *(channels
++);
195 char* sep
= strchr(tmp
,'-');
196 if (!sep
) continue; // Wrong syntax, but mplayer should not crash
197 av_strlcpy(priv
->radio_channel_current
->name
, sep
+ 1,sizeof(priv
->radio_channel_current
->name
)-1);
201 priv
->radio_channel_current
->freq
=atof(tmp
);
203 if ((priv
->radio_channel_current
->freq
>priv
->rangehigh
)||(priv
->radio_channel_current
->freq
<priv
->rangelow
))
204 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_WrongFreqForChannel
,
205 priv
->radio_channel_current
->name
);
207 while ((sep
=strchr(priv
->radio_channel_current
->name
, '_'))) sep
[0] = ' ';
209 priv
->radio_channel_current
->next
= malloc(sizeof(radio_channels_t
));
210 priv
->radio_channel_current
->next
->index
= priv
->radio_channel_current
->index
+ 1;
211 priv
->radio_channel_current
->next
->prev
= priv
->radio_channel_current
;
212 priv
->radio_channel_current
->next
->next
= NULL
;
213 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
215 if (priv
->radio_channel_current
->prev
)
216 priv
->radio_channel_current
->prev
->next
= NULL
;
217 free(priv
->radio_channel_current
);
220 channel
= freq_channel
;
224 priv
->radio_channel_current
= priv
->radio_channel_list
;
225 for (i
= 1; i
< channel
; i
++)
226 if (priv
->radio_channel_current
->next
)
227 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
228 if (priv
->radio_channel_current
->index
!=channel
){
229 if (((float)((int)freq_channel
))!=freq_channel
)
230 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_WrongChannelNumberFloat
,freq_channel
);
232 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_WrongChannelNumberInt
,(int)freq_channel
);
235 mp_msg(MSGT_RADIO
, MSGL_INFO
, MSGTR_RADIO_SelectedChannel
, priv
->radio_channel_current
->index
,
236 priv
->radio_channel_current
->name
, priv
->radio_channel_current
->freq
);
237 *pfreq
=priv
->radio_channel_current
->freq
;
240 mp_msg(MSGT_RADIO
, MSGL_INFO
, MSGTR_RADIO_FreqParameterDetected
);
241 priv
->radio_channel_list
=malloc(sizeof(radio_channels_t
));
242 priv
->radio_channel_list
->next
=NULL
;
243 priv
->radio_channel_list
->prev
=NULL
;
244 priv
->radio_channel_list
->index
=1;
245 snprintf(priv
->radio_channel_list
->name
,sizeof(priv
->radio_channel_current
->name
)-1,"Freq: %.2f",freq_channel
);
247 priv
->radio_channel_current
=priv
->radio_channel_list
;
251 mp_msg(MSGT_RADIO
, MSGL_DBG2
, MSGTR_RADIO_DoneParsingChannels
);
255 #ifdef CONFIG_RADIO_V4L2
256 /*****************************************************************
257 * \brief get fraction value for using in set_frequency and get_frequency
258 * \return STREAM_OK if success, STREAM_ERROR otherwise
260 * V4L2_TUNER_CAP_LOW:
262 * frac= 1MHz/unit=1000000/62.5 =16000
266 * frac= 1MHz/unit=1000000/62500 =16
268 static int init_frac_v4l2(radio_priv_t
* priv
){
269 struct v4l2_tuner tuner
;
271 memset(&tuner
,0,sizeof(tuner
));
273 if (ioctl(priv
->radio_fd
, VIDIOC_G_TUNER
, &tuner
)<0){
274 mp_msg(MSGT_RADIO
,MSGL_WARN
,MSGTR_RADIO_GetTunerFailed
,strerror(errno
),priv
->frac
);
277 if(tuner
.type
!=V4L2_TUNER_RADIO
){
278 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_NotRadioDevice
,priv
->radio_param
->device
);
281 if(tuner
.capability
& V4L2_TUNER_CAP_LOW
){
283 mp_msg(MSGT_RADIO
,MSGL_DBG2
,MSGTR_RADIO_TunerCapLowYes
,priv
->frac
);
287 mp_msg(MSGT_RADIO
,MSGL_DBG2
,MSGTR_RADIO_TunerCapLowNo
,priv
->frac
);
290 priv
->rangelow
=((float)tuner
.rangelow
)/priv
->frac
;
291 priv
->rangehigh
=((float)tuner
.rangehigh
)/priv
->frac
;
292 mp_msg(MSGT_RADIO
,MSGL_V
,MSGTR_RADIO_FreqRange
,priv
->rangelow
,priv
->rangehigh
);
296 /*****************************************************************
297 * \brief tune card to given frequency
298 * \param frequency frequency in MHz
299 * \return STREAM_OK if success, STREAM_ERROR otherwise
301 static int set_frequency_v4l2(radio_priv_t
* priv
,float frequency
){
302 struct v4l2_frequency freq
;
304 memset(&freq
,0,sizeof(freq
));
306 freq
.type
=V4L2_TUNER_RADIO
;
307 freq
.frequency
=frequency
*priv
->frac
;
308 if(ioctl(priv
->radio_fd
,VIDIOC_S_FREQUENCY
,&freq
)<0){
309 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_SetFreqFailed
,freq
.frequency
,
310 frequency
,strerror(errno
));
316 /*****************************************************************
317 * \brief get current tuned frequency from card
318 * \param frequency where to store frequency in MHz
319 * \return STREAM_OK if success, STREAM_ERROR otherwise
321 static int get_frequency_v4l2(radio_priv_t
* priv
,float* frequency
){
322 struct v4l2_frequency freq
;
323 memset(&freq
,0,sizeof(freq
));
324 if (ioctl(priv
->radio_fd
, VIDIOC_G_FREQUENCY
, &freq
) < 0) {
325 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_GetFreqFailed
,strerror(errno
));
328 *frequency
=((float)freq
.frequency
)/priv
->frac
;
332 /*****************************************************************
333 * \brief set volume on radio card
334 * \param volume volume level (0..100)
335 * \return STREAM_OK if success, STREAM_ERROR otherwise
337 static void set_volume_v4l2(radio_priv_t
* priv
,int volume
){
338 struct v4l2_queryctrl qctrl
;
339 struct v4l2_control control
;
341 /*arg must be between 0 and 100*/
342 if (volume
> 100) volume
= 100;
343 if (volume
< 0) volume
= 0;
345 memset(&control
,0,sizeof(control
));
346 control
.id
=V4L2_CID_AUDIO_MUTE
;
347 control
.value
= (volume
==0?1:0);
348 if (ioctl(priv
->radio_fd
, VIDIOC_S_CTRL
, &control
)<0){
349 mp_msg(MSGT_RADIO
,MSGL_WARN
,MSGTR_RADIO_SetMuteFailed
,strerror(errno
));
352 memset(&qctrl
,0,sizeof(qctrl
));
353 qctrl
.id
= V4L2_CID_AUDIO_VOLUME
;
354 if (ioctl(priv
->radio_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
355 mp_msg(MSGT_RADIO
, MSGL_WARN
, MSGTR_RADIO_QueryControlFailed
,strerror(errno
));
359 memset(&control
,0,sizeof(control
));
360 control
.id
=V4L2_CID_AUDIO_VOLUME
;
361 control
.value
=qctrl
.minimum
+volume
*(qctrl
.maximum
-qctrl
.minimum
)/100;
362 if (ioctl(priv
->radio_fd
, VIDIOC_S_CTRL
, &control
) < 0) {
363 mp_msg(MSGT_RADIO
, MSGL_WARN
,MSGTR_RADIO_SetVolumeFailed
,strerror(errno
));
367 /*****************************************************************
368 * \brief get current volume from radio card
369 * \param volume where to store volume level (0..100)
370 * \return STREAM_OK if success, STREAM_ERROR otherwise
372 static int get_volume_v4l2(radio_priv_t
* priv
,int* volume
){
373 struct v4l2_queryctrl qctrl
;
374 struct v4l2_control control
;
376 memset(&qctrl
,0,sizeof(qctrl
));
377 qctrl
.id
= V4L2_CID_AUDIO_VOLUME
;
378 if (ioctl(priv
->radio_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
379 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_QueryControlFailed
,strerror(errno
));
383 memset(&control
,0,sizeof(control
));
384 control
.id
=V4L2_CID_AUDIO_VOLUME
;
385 if (ioctl(priv
->radio_fd
, VIDIOC_G_CTRL
, &control
) < 0) {
386 mp_msg(MSGT_RADIO
, MSGL_ERR
,MSGTR_RADIO_GetVolumeFailed
,strerror(errno
));
390 if (qctrl
.maximum
==qctrl
.minimum
)
391 *volume
=qctrl
.minimum
;
393 *volume
=100*(control
.value
-qctrl
.minimum
)/(qctrl
.maximum
-qctrl
.minimum
);
395 /*arg must be between 0 and 100*/
396 if (*volume
> 100) *volume
= 100;
397 if (*volume
< 0) *volume
= 0;
402 /* v4l2 driver info structure */
403 static const radio_driver_t radio_driver_v4l2
={
405 MSGTR_RADIO_DriverV4L2
,
412 #endif /* CONFIG_RADIO_V4L2 */
413 #ifdef CONFIG_RADIO_V4L
414 /*****************************************************************
415 * \brief get fraction value for using in set_frequency and get_frequency
416 * \return STREAM_OK if success, STREAM_ERROR otherwise
418 * V4L2_TUNER_CAP_LOW:
420 * frac= 1MHz/unit=1000000/62.5 =16000
424 * frac= 1MHz/unit=1000000/62500 =16
427 static int init_frac_v4l(radio_priv_t
* priv
){
428 struct video_tuner tuner
;
429 memset(&tuner
,0,sizeof(tuner
));
430 if (ioctl(priv
->radio_fd
, VIDIOCGTUNER
, &tuner
) <0){
431 mp_msg(MSGT_RADIO
,MSGL_WARN
,MSGTR_RADIO_GetTunerFailed
,strerror(errno
),priv
->frac
);
434 if(tuner
.flags
& VIDEO_TUNER_LOW
){
436 mp_msg(MSGT_RADIO
,MSGL_DBG2
,MSGTR_RADIO_TunerCapLowYes
,priv
->frac
);
439 mp_msg(MSGT_RADIO
,MSGL_DBG2
,MSGTR_RADIO_TunerCapLowNo
,priv
->frac
);
442 priv
->rangelow
=((float)tuner
.rangelow
)/priv
->frac
;
443 priv
->rangehigh
=((float)tuner
.rangehigh
)/priv
->frac
;
444 mp_msg(MSGT_RADIO
,MSGL_V
,MSGTR_RADIO_FreqRange
,priv
->rangelow
,priv
->rangehigh
);
449 /*****************************************************************
450 * \brief tune card to given frequency
451 * \param frequency frequency in MHz
452 * \return STREAM_OK if success, STREAM_ERROR otherwise
454 static int set_frequency_v4l(radio_priv_t
* priv
,float frequency
){
456 freq
=frequency
*priv
->frac
;
457 if (ioctl(priv
->radio_fd
, VIDIOCSFREQ
, &freq
) < 0) {
458 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_SetFreqFailed
,freq
,frequency
,strerror(errno
));
463 /*****************************************************************
464 * \brief get current tuned frequency from card
465 * \param frequency where to store frequency in MHz
466 * \return STREAM_OK if success, STREAM_ERROR otherwise
468 static int get_frequency_v4l(radio_priv_t
* priv
,float* frequency
){
470 if (ioctl(priv
->radio_fd
, VIDIOCGFREQ
, &freq
) < 0) {
471 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_GetFreqFailed
,strerror(errno
));
474 *frequency
=((float)freq
)/priv
->frac
;
478 /*****************************************************************
479 * \brief set volume on radio card
480 * \param volume volume level (0..100)
481 * \return STREAM_OK if success, STREAM_ERROR otherwise
483 static void set_volume_v4l(radio_priv_t
* priv
,int volume
){
484 struct video_audio audio
;
486 /*arg must be between 0 and 100*/
487 if (volume
> 100) volume
= 100;
488 if (volume
< 0) volume
= 0;
490 memset(&audio
,0,sizeof(audio
));
491 audio
.flags
= (volume
==0?VIDEO_AUDIO_MUTE
:0);
492 if (ioctl(priv
->radio_fd
, VIDIOCSAUDIO
, &audio
)<0){
493 mp_msg(MSGT_RADIO
,MSGL_WARN
,MSGTR_RADIO_SetMuteFailed
,strerror(errno
));
496 memset(&audio
,0,sizeof(audio
));
497 audio
.flags
= VIDEO_AUDIO_VOLUME
;
498 audio
.mode
= VIDEO_SOUND_STEREO
;
500 audio
.volume
= volume
* (65535 / 100);
502 if (ioctl(priv
->radio_fd
, VIDIOCSAUDIO
, &audio
) < 0){
503 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_SetVolumeFailed
,strerror(errno
));
507 /*****************************************************************
508 * \brief get current volume from radio card
509 * \param volume where to store volume level (0..100)
510 * \return STREAM_OK if success, STREAM_ERROR otherwise
512 static int get_volume_v4l(radio_priv_t
* priv
,int* volume
){
513 struct video_audio audio
;
515 memset(&audio
,0,sizeof(audio
));
517 if (ioctl(priv
->radio_fd
, VIDIOCGAUDIO
, &audio
) < 0){
518 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_GetVolumeFailed
,strerror(errno
));
522 if (audio
.flags
& VIDEO_AUDIO_VOLUME
){
523 *volume
=100*audio
.volume
/65535;
524 /*arg must be between 0 and 100*/
525 if (*volume
> 100) *volume
= 100;
526 if (*volume
< 0) *volume
= 0;
533 /* v4l driver info structure */
534 static const radio_driver_t radio_driver_v4l
={
536 MSGTR_RADIO_DriverV4L
,
543 #endif /* CONFIG_RADIO_V4L */
544 #ifdef CONFIG_RADIO_BSDBT848
546 /*****************************************************************
547 * \brief get fraction value for using in set_frequency and get_frequency
548 * \return STREAM_OK if success, STREAM_ERROR otherwise
550 * For *BSD BT848 frac=100
552 * Here is a coment from FreeBSD 5.2-RELEASE source code:
555 * * Programming the tuner properly is quite complicated.
556 * * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner.
557 * * The tuner (front end) covers 45.75 MHz - 855.25 MHz and an FM band of
558 * * 87.5 MHz to 108.0 MHz.
560 * Thus, frequency range is limited to 87.5-108.0, but you can change
561 * it, using freq_min and freq_max options
563 static int init_frac_bsdbt848(radio_priv_t
* priv
){
565 priv
->rangelow
=priv
->radio_param
->freq_min
;
566 priv
->rangehigh
=priv
->radio_param
->freq_max
;
570 /*****************************************************************
571 * \brief tune card to given frequency
572 * \param frequency frequency in MHz
573 * \return STREAM_OK if success, STREAM_ERROR otherwise
575 static int set_frequency_bsdbt848(radio_priv_t
* priv
,float frequency
){
577 freq
=frequency
*priv
->frac
;
578 if(ioctl(priv
->radio_fd
,RADIO_SETFREQ
,&freq
)<0){
579 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_SetFreqFailed
,freq
, frequency
, strerror(errno
));
585 /*****************************************************************
586 * \brief get current tuned frequency from card
587 * \param frequency where to store frequency in MHz
588 * \return STREAM_OK if success, STREAM_ERROR otherwise
590 static int get_frequency_bsdbt848(radio_priv_t
* priv
,float* frequency
){
592 if (ioctl(priv
->radio_fd
, RADIO_GETFREQ
, &freq
) < 0) {
593 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_GetFreqFailed
,strerror(errno
));
596 *frequency
=((float)freq
)/priv
->frac
;
600 /*****************************************************************
601 * \brief set volume on radio card
602 * \param volume volume level (0..100)
603 * \return STREAM_OK if success, STREAM_ERROR otherwise
605 * *BSD BT848 does not have volume changing abilities, so
606 * we will just mute sound if volume=0 and unmute it otherwise.
608 static void set_volume_bsdbt848(radio_priv_t
* priv
,int volume
){
611 /*arg must be between 0 and 100*/
612 if (volume
> 100) volume
= 100;
613 if (volume
< 0) volume
= 0;
615 audio_flags
= (volume
==0?AUDIO_MUTE
:AUDIO_UNMUTE
);
616 if (ioctl(priv
->radio_fd
, BT848_SAUDIO
, &audio_flags
)<0){
617 mp_msg(MSGT_RADIO
,MSGL_WARN
,MSGTR_RADIO_SetMuteFailed
,strerror(errno
));
621 /*****************************************************************
622 * \brief get current volume from radio card
623 * \param volume where to store volume level (0..100)
624 * \return previous STREAM_OK if success, STREAM_ERROR otherwise
626 * *BSD BT848 does not have volume changing abilities, so
627 * we will return 0 if sound is muted and 100 otherwise.
629 static int get_volume_bsdbt848(radio_priv_t
* priv
,int* volume
){
632 if (ioctl(priv
->radio_fd
, BT848_GAUDIO
, &audio_flags
)<0){
633 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_GetVolumeFailed
,strerror(errno
));
637 if (audio_flags
& AUDIO_MUTE
)
645 /* bsdbt848 driver info structure */
646 static const radio_driver_t radio_driver_bsdbt848
={
648 MSGTR_RADIO_DriverBSDBT848
,
652 set_frequency_bsdbt848
,
653 get_frequency_bsdbt848
655 #endif /* CONFIG_RADIO_BSDBT848 */
657 static inline int init_frac(radio_priv_t
* priv
){
658 return priv
->driver
->init_frac(priv
);
660 static inline int set_frequency(radio_priv_t
* priv
,float frequency
){
661 if ((frequency
<priv
->rangelow
)||(frequency
>priv
->rangehigh
)){
662 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_WrongFreq
,frequency
);
665 if(priv
->driver
->set_frequency(priv
,frequency
)!=STREAM_OK
)
668 #ifdef CONFIG_RADIO_CAPTURE
669 if(clear_buffer(priv
)!=STREAM_OK
){
670 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_ClearBufferFailed
,strerror(errno
));
676 static inline int get_frequency(radio_priv_t
* priv
,float* frequency
){
677 return priv
->driver
->get_frequency(priv
,frequency
);
679 static inline void set_volume(radio_priv_t
* priv
,int volume
){
680 priv
->driver
->set_volume(priv
,volume
);
682 static inline int get_volume(radio_priv_t
* priv
,int* volume
){
683 return priv
->driver
->get_volume(priv
,volume
);
687 #ifndef CONFIG_RADIO_CAPTURE
688 /*****************************************************************
689 * \brief stub, if capture disabled at compile-time
692 static inline int init_audio(radio_priv_t
*priv
){ return STREAM_OK
;}
694 /*****************************************************************
695 * \brief making buffer empty
696 * \return STREAM_OK if success, STREAM_ERROR otherwise
698 * when changing channel we must clear buffer to avoid large switching delay
700 static int clear_buffer(radio_priv_t
* priv
){
701 if (!priv
->do_capture
) return STREAM_OK
;
702 priv
->audio_tail
= 0;
703 priv
->audio_head
= 0;
705 memset(priv
->audio_ringbuffer
,0,priv
->audio_in
.blocksize
);
708 /*****************************************************************
709 * \brief read next part of data into buffer
710 * \return -1 if error occured or no data available yet, otherwise - bytes read
711 * NOTE: audio device works in non-blocking mode
713 static int read_chunk(audio_in_t
*ai
, unsigned char *buffer
)
720 //device opened in non-blocking mode
721 ret
= snd_pcm_readi(ai
->alsa
.handle
, buffer
, ai
->alsa
.chunk_size
);
722 if (ret
!= ai
->alsa
.chunk_size
) {
724 if (ret
==-EAGAIN
) return -1;
725 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio
, snd_strerror(ret
));
727 if (ai_alsa_xrun(ai
) == 0) {
728 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_MPDEMUX_AUDIOIN_XRUNSomeFramesMayBeLeftOut
);
730 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_MPDEMUX_AUDIOIN_ErrFatalCannotRecover
);
734 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_MPDEMUX_AUDIOIN_NotEnoughSamples
);
740 #ifdef CONFIG_OSS_AUDIO
745 we must return exactly blocksize bytes, so if we have got any bytes
746 at first call to read, we will loop untils get all blocksize bytes
747 otherwise we will return -1
749 while(bt
<ai
->blocksize
){
750 //device opened in non-blocking mode
751 ret
= read(ai
->oss
.audio_fd
, buffer
+bt
, ai
->blocksize
-bt
);
752 if (ret
==ai
->blocksize
) return ret
;
754 if (errno
==EAGAIN
&& bt
==0) return -1; //no data avail yet
755 if (errno
==EAGAIN
) { usleep(1000); continue;} //nilling buffer to blocksize size
756 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_MPDEMUX_AUDIOIN_ErrReadingAudio
, strerror(errno
));
768 /*****************************************************************
769 * \brief grab next frame from audio device
770 * \parameter buffer - store buffer
771 * \parameter len - store buffer size in bytes
772 * \return number of bytes written into buffer
774 * grabs len (or less) bytes from ringbuffer into buffer
775 * if ringbuffer is empty waits until len bytes of data will be available
777 * priv->audio_cnt - size (in bytes) of ringbuffer's filled part
778 * priv->audio_drop - size (in bytes) of dropped data (if no space in ringbuffer)
779 * priv->audio_head - index of first byte in filled part
780 * priv->audio_tail - index of last byte in filled part
782 * NOTE: audio_tail always aligned by priv->audio_in.blocksize
783 * audio_head may NOT.
785 static int grab_audio_frame(radio_priv_t
*priv
, char *buffer
, int len
)
788 mp_msg(MSGT_RADIO
, MSGL_DBG3
, MSGTR_RADIO_BufferString
,"grab_audio_frame",priv
->audio_cnt
,priv
->audio_drop
);
789 /* Cache buffer must be filled by some audio packets when playing starts.
790 Otherwise MPlayer will quit with EOF error.
791 Probably, there is need more carefull checking rather than simple 'for' loop
792 (something like timer or similar).
794 1000ms delay will happen only at first buffer filling. At next call function
795 just fills buffer until either buffer full or no data from driver available.
797 for (i
=0;i
<1000 && !priv
->audio_cnt
; i
++){
798 //read_chunk fills exact priv->blocksize bytes
799 if(read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
) < 0){
800 //sleppeing only when waiting first block to fill empty buffer
801 if (!priv
->audio_cnt
){
807 priv
->audio_cnt
+=priv
->audio_in
.blocksize
;
808 priv
->audio_tail
= (priv
->audio_tail
+priv
->audio_in
.blocksize
) % priv
->audio_buffer_size
;
810 if(priv
->audio_cnt
<len
)
812 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
,len
);
813 priv
->audio_head
= (priv
->audio_head
+len
) % priv
->audio_buffer_size
;
814 priv
->audio_cnt
-=len
;
817 /*****************************************************************
818 * \brief init audio device
819 * \return STREAM_OK if success, STREAM_ERROR otherwise
821 static int init_audio(radio_priv_t
*priv
)
826 if (priv
->audio_initialized
) return 1;
828 /* do_capture==0 mplayer was not started with capture keyword, so disabling capture*/
829 if(!priv
->do_capture
)
832 if (!priv
->radio_param
->adevice
){
838 mp_msg(MSGT_RADIO
,MSGL_V
,MSGTR_RADIO_CaptureStarting
);
840 while ((tmp
= strrchr(priv
->radio_param
->adevice
, '='))){
842 //adevice option looks like ALSA device name. Switching to ALSA
845 while ((tmp
= strrchr(priv
->radio_param
->adevice
, '.')))
849 if(audio_in_init(&priv
->audio_in
, is_oss
?AUDIO_IN_OSS
:AUDIO_IN_ALSA
)<0){
850 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_AudioInInitFailed
);
853 audio_in_set_device(&priv
->audio_in
, priv
->radio_param
->adevice
);
854 audio_in_set_channels(&priv
->audio_in
, priv
->radio_param
->achannels
);
855 audio_in_set_samplerate(&priv
->audio_in
, priv
->radio_param
->arate
);
857 if (audio_in_setup(&priv
->audio_in
) < 0) {
858 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_AudioInSetupFailed
, strerror(errno
));
861 #ifdef CONFIG_OSS_AUDIO
863 ioctl(priv
->audio_in
.oss
.audio_fd
, SNDCTL_DSP_NONBLOCK
, 0);
867 snd_pcm_nonblock(priv
->audio_in
.alsa
.handle
,1);
870 priv
->audio_buffer_size
= seconds
*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
871 priv
->audio_in
.bytes_per_sample
+priv
->audio_in
.blocksize
;
872 if (priv
->audio_buffer_size
< 256*priv
->audio_in
.blocksize
)
873 priv
->audio_buffer_size
= 256*priv
->audio_in
.blocksize
;
874 mp_msg(MSGT_RADIO
, MSGL_V
, MSGTR_RADIO_AudioBuffer
,
875 priv
->audio_buffer_size
,priv
->audio_in
.blocksize
);
877 priv
->audio_ringbuffer
= calloc(1, priv
->audio_buffer_size
);
878 if (!priv
->audio_ringbuffer
) {
879 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_AllocateBufferFailed
,priv
->audio_in
.blocksize
, priv
->audio_buffer_size
, strerror(errno
));
882 priv
->audio_head
= 0;
883 priv
->audio_tail
= 0;
885 priv
->audio_drop
= 0;
887 audio_in_start_capture(&priv
->audio_in
);
889 priv
->audio_initialized
= 1;
893 #endif /* CONFIG_RADIO_CAPTURE */
895 /*-------------------------------------------------------------------------
896 for call from mplayer.c
897 --------------------------------------------------------------------------*/
898 /*****************************************************************
899 * \brief public wrapper for get_frequency
900 * \parameter frequency pointer to float, which will contain frequency in MHz
901 * \return 1 if success,0 - otherwise
903 int radio_get_freq(struct stream_st
*stream
, float* frequency
){
904 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
908 if (get_frequency(priv
,frequency
)!=STREAM_OK
){
913 /*****************************************************************
914 * \brief public wrapper for set_frequency
915 * \parameter frequency frequency in MHz
916 * \return 1 if success,0 - otherwise
918 int radio_set_freq(struct stream_st
*stream
, float frequency
){
919 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
921 if (set_frequency(priv
,frequency
)!=STREAM_OK
){
924 if (get_frequency(priv
,&frequency
)!=STREAM_OK
){
927 mp_msg(MSGT_RADIO
, MSGL_INFO
, MSGTR_RADIO_CurrentFreq
,frequency
);
931 /*****************************************************************
932 * \brief tune current frequency by step_interval value
933 * \parameter step_interval increment value
934 * \return 1 if success,0 - otherwise
937 int radio_step_freq(struct stream_st
*stream
, float step_interval
){
939 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
941 if (get_frequency(priv
,&frequency
)!=STREAM_OK
)
944 frequency
+=step_interval
;
945 if (frequency
>priv
->rangehigh
)
946 frequency
=priv
->rangehigh
;
947 if (frequency
<priv
->rangelow
)
948 frequency
=priv
->rangelow
;
950 return radio_set_freq(stream
,frequency
);
952 /*****************************************************************
953 * \brief step channel up or down
954 * \parameter direction RADIO_CHANNEL_LOWER - go to prev channel,RADIO_CHANNEL_HIGHER - to next
955 * \return 1 if success,0 - otherwise
957 * if channel parameter is NULL function prints error message and does nothing, otherwise
958 * changes channel to prev or next in list
960 int radio_step_channel(struct stream_st
*stream
, int direction
) {
961 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
963 if (priv
->radio_channel_list
) {
965 case RADIO_CHANNEL_HIGHER
:
966 if (priv
->radio_channel_current
->next
)
967 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
969 priv
->radio_channel_current
= priv
->radio_channel_list
;
970 if(!radio_set_freq(stream
,priv
->radio_channel_current
->freq
))
972 mp_msg(MSGT_RADIO
, MSGL_V
, MSGTR_RADIO_SelectedChannel
,
973 priv
->radio_channel_current
->index
, priv
->radio_channel_current
->name
,
974 priv
->radio_channel_current
->freq
);
976 case RADIO_CHANNEL_LOWER
:
977 if (priv
->radio_channel_current
->prev
)
978 priv
->radio_channel_current
= priv
->radio_channel_current
->prev
;
980 while (priv
->radio_channel_current
->next
)
981 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
982 if(!radio_set_freq(stream
,priv
->radio_channel_current
->freq
))
984 mp_msg(MSGT_RADIO
, MSGL_V
, MSGTR_RADIO_SelectedChannel
,
985 priv
->radio_channel_current
->index
, priv
->radio_channel_current
->name
,
986 priv
->radio_channel_current
->freq
);
990 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_ChangeChannelNoChannelList
);
994 /*****************************************************************
995 * \brief change channel to one with given index
996 * \parameter channel string, containing channel number
997 * \return 1 if success,0 - otherwise
999 * if channel parameter is NULL function prints error message and does nothing, otherwise
1000 * changes channel to given
1002 int radio_set_channel(struct stream_st
*stream
, char *channel
) {
1003 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
1005 radio_channels_t
* tmp
;
1009 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_WrongChannelName
,channel
);
1011 if (priv
->radio_channel_list
) {
1012 channel_int
= strtol(channel
,&endptr
,10);
1013 tmp
= priv
->radio_channel_list
;
1015 //channel is not a number, so it contains channel name
1016 for ( ; tmp
; tmp
=tmp
->next
)
1017 if (!strncmp(channel
,tmp
->name
,sizeof(tmp
->name
)-1))
1020 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_WrongChannelName
,channel
);
1024 for (i
= 1; i
< channel_int
; i
++)
1029 if (tmp
->index
!=channel_int
){
1030 mp_msg(MSGT_RADIO
,MSGL_ERR
,MSGTR_RADIO_WrongChannelNumberInt
,channel_int
);
1034 priv
->radio_channel_current
=tmp
;
1035 mp_msg(MSGT_RADIO
, MSGL_V
, MSGTR_RADIO_SelectedChannel
, priv
->radio_channel_current
->index
,
1036 priv
->radio_channel_current
->name
, priv
->radio_channel_current
->freq
);
1037 if(!radio_set_freq(stream
, priv
->radio_channel_current
->freq
))
1040 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_ChangeChannelNoChannelList
);
1044 /*****************************************************************
1045 * \brief get current channel's name
1046 * \return pointer to string, containing current channel's name
1048 * NOTE: return value may be NULL (e.g. when channel list not initialized)
1050 char* radio_get_channel_name(struct stream_st
*stream
){
1051 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
1052 if (priv
->radio_channel_current
) {
1053 return priv
->radio_channel_current
->name
;
1058 /*****************************************************************
1059 * \brief fills given buffer with audio data
1060 * \return number of bytes, written into buffer
1062 static int fill_buffer_s(struct stream_st
*s
, char* buffer
, int max_len
){
1065 #ifdef CONFIG_RADIO_CAPTURE
1066 radio_priv_t
* priv
=(radio_priv_t
*)s
->priv
;
1068 if (priv
->do_capture
){
1069 len
=grab_audio_frame(priv
, buffer
,max_len
);
1073 memset(buffer
,0,len
);
1079 order if significant!
1080 when no driver explicitly specified first available will be used
1082 static const radio_driver_t
* radio_drivers
[]={
1083 #ifdef CONFIG_RADIO_BSDBT848
1084 &radio_driver_bsdbt848
,
1086 #ifdef CONFIG_RADIO_V4L2
1089 #ifdef CONFIG_RADIO_V4L
1095 /*****************************************************************
1096 * Stream initialization
1097 * \return STREAM_OK if success, STREAM_ERROR otherwise
1099 static int open_s(stream_t
*stream
,int mode
, void* opts
, int* file_format
) {
1104 if (strncmp("radio://",stream
->url
,8) != 0)
1105 return STREAM_UNSUPPORTED
;
1107 if(mode
!= STREAM_READ
)
1108 return STREAM_UNSUPPORTED
;
1110 priv
=calloc(1,sizeof(radio_priv_t
));
1113 return STREAM_ERROR
;
1116 priv
->radio_param
=opts
;
1118 #ifdef CONFIG_RADIO_CAPTURE
1119 if (priv
->radio_param
->capture
&& strncmp("capture",priv
->radio_param
->capture
,7)==0)
1127 if (strncmp(priv
->radio_param
->driver
,"default",7)==0)
1128 priv
->driver
=radio_drivers
[0];
1132 mp_msg(MSGT_RADIO
,MSGL_V
,MSGTR_RADIO_AvailableDrivers
);
1133 for(i
=0;radio_drivers
[i
];i
++){
1134 mp_msg(MSGT_RADIO
,MSGL_V
,"%s, ",radio_drivers
[i
]->name
);
1135 if(strcmp(priv
->radio_param
->driver
,radio_drivers
[i
]->name
)==0)
1136 priv
->driver
=radio_drivers
[i
];
1138 mp_msg(MSGT_RADIO
,MSGL_V
,"\n");
1141 mp_msg(MSGT_RADIO
, MSGL_INFO
, priv
->driver
->info
);
1143 mp_msg(MSGT_RADIO
, MSGL_INFO
, MSGTR_RADIO_DriverUnknownStr
,priv
->radio_param
->driver
);
1145 return STREAM_ERROR
;
1148 stream
->type
= STREAMTYPE_RADIO
;
1149 /* using rawaudio demuxer */
1150 *file_format
= DEMUXER_TYPE_RAWAUDIO
;
1151 stream
->flags
= STREAM_READ
;
1155 stream
->start_pos
=0;
1158 stream
->close
=close_s
;
1159 stream
->fill_buffer
=fill_buffer_s
;
1161 priv
->radio_fd
= open(priv
->radio_param
->device
, O_RDONLY
);
1162 if (priv
->radio_fd
< 0) {
1163 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_UnableOpenDevice
,
1164 priv
->radio_param
->device
, strerror(errno
));
1166 return STREAM_ERROR
;
1168 mp_msg(MSGT_RADIO
, MSGL_V
, MSGTR_RADIO_RadioDevice
, priv
->radio_fd
,priv
->radio_param
->device
);
1169 fcntl(priv
->radio_fd
, F_SETFD
, FD_CLOEXEC
);
1171 get_volume(priv
, &priv
->old_snd_volume
);
1174 if (init_frac(priv
)!=STREAM_OK
){
1176 return STREAM_ERROR
;
1179 if (parse_channels(priv
,priv
->radio_param
->freq_channel
,&frequency
)!=STREAM_OK
){
1181 return STREAM_ERROR
;
1184 if ((frequency
<priv
->rangelow
)||(frequency
>priv
->rangehigh
)){
1185 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_WrongFreq
,frequency
);
1187 return STREAM_ERROR
;
1189 mp_msg(MSGT_RADIO
, MSGL_INFO
, MSGTR_RADIO_UsingFreq
,frequency
);
1191 if(set_frequency(priv
,frequency
)!=STREAM_OK
){
1193 return STREAM_ERROR
;
1197 if (init_audio(priv
)!=STREAM_OK
){
1199 return STREAM_ERROR
;
1202 #if defined(CONFIG_RADIO_CAPTURE) && defined(CONFIG_STREAM_CACHE)
1203 if(priv
->do_capture
){
1205 if(!stream_enable_cache(stream
,5*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
1206 priv
->audio_in
.bytes_per_sample
,2*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
1207 priv
->audio_in
.bytes_per_sample
,priv
->audio_in
.blocksize
)) {
1208 mp_msg(MSGT_RADIO
, MSGL_ERR
, MSGTR_RADIO_StreamEnableCacheFailed
,strerror(errno
));
1210 return STREAM_ERROR
;
1215 set_volume(priv
,priv
->radio_param
->volume
);
1220 /*****************************************************************
1221 * Close stream. Clear structures.
1223 static void close_s(struct stream_st
* stream
){
1224 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
1225 radio_channels_t
* tmp
;
1228 #ifdef CONFIG_RADIO_CAPTURE
1229 if(priv
->audio_ringbuffer
){
1230 free(priv
->audio_ringbuffer
);
1231 priv
->audio_ringbuffer
=NULL
;
1237 while (priv
->radio_channel_list
) {
1238 tmp
=priv
->radio_channel_list
;
1239 priv
->radio_channel_list
=priv
->radio_channel_list
->next
;
1242 priv
->radio_channel_current
=NULL
;
1243 priv
->radio_channel_list
=NULL
;
1245 if (priv
->radio_fd
>0){
1246 set_volume(priv
, priv
->old_snd_volume
);
1247 close(priv
->radio_fd
);
1250 if(priv
->radio_param
)
1251 m_struct_free(&stream_opts
,priv
->radio_param
);
1256 const stream_info_t stream_info_radio
= {
1259 "Vladimir Voroshilov",
1264 1 // Urls are an option string