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>
56 #endif // !IOCTL_BT848_H_NAME
60 #include "libmpdemux/demuxer.h"
64 #include "stream_radio.h"
65 #include "libavutil/avstring.h"
67 #ifdef CONFIG_RADIO_CAPTURE
70 #ifdef HAVE_SYS_SOUNDCARD_H
71 #include <sys/soundcard.h>
73 #ifdef HAVE_SOUNDCARD_H
74 #include <soundcard.h>
76 #include <linux/soundcard.h>
82 typedef struct radio_channels_s
{
83 int index
; ///< channel index in channels list
84 float freq
; ///< frequency in MHz
85 char name
[20]; ///< channel name
86 struct radio_channels_s
* next
;
87 struct radio_channels_s
* prev
;
90 /// default values for options
91 radio_param_t stream_radio_defaults
={
92 #ifdef CONFIG_RADIO_BSDBT848
93 "/dev/tuner0", //device
97 "/dev/radio0", //device;
109 typedef struct radio_priv_s
{
110 int radio_fd
; ///< radio device descriptor
111 int frac
; ///< fraction value (see comment to init_frac)
112 radio_channels_t
* radio_channel_list
;
113 radio_channels_t
* radio_channel_current
;
114 float rangelow
; ///< lowest tunable frequency in MHz
115 float rangehigh
; ///< highest tunable frequency in MHz
116 const struct radio_driver_s
* driver
;
118 #ifdef CONFIG_RADIO_CAPTURE
119 volatile int do_capture
; ///< is capture enabled
121 unsigned char* audio_ringbuffer
;
122 int audio_head
; ///< start of meanfull data in ringbuffer
123 int audio_tail
; ///< end of meanfull data in ringbuffer
124 int audio_buffer_size
; ///< size of ringbuffer
125 int audio_cnt
; ///< size of meanfull data inringbuffer
126 int audio_drop
; ///< number of dropped bytes
127 int audio_initialized
;
129 radio_param_t
*radio_param
;
132 typedef struct radio_driver_s
{
135 int (*init_frac
)(radio_priv_t
* priv
);
136 void (*set_volume
)(radio_priv_t
* priv
,int volume
);
137 int (*get_volume
)(radio_priv_t
* priv
,int* volume
);
138 int (*set_frequency
)(radio_priv_t
* priv
,float frequency
);
139 int (*get_frequency
)(radio_priv_t
* priv
,float* frequency
);
142 #define ST_OFF(f) M_ST_OFF(radio_param_t,f)
143 static const m_option_t stream_opts_fields
[] = {
144 {"hostname", ST_OFF(freq_channel
), CONF_TYPE_FLOAT
, 0, 0 ,0, NULL
},
145 {"filename", ST_OFF(capture
), CONF_TYPE_STRING
, 0, 0 ,0, NULL
},
146 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
149 static const struct m_struct_st stream_opts
= {
151 sizeof(radio_param_t
),
152 &stream_radio_defaults
,
156 static void close_s(struct stream
*stream
);
157 #ifdef CONFIG_RADIO_CAPTURE
158 static int clear_buffer(radio_priv_t
* priv
);
162 /*****************************************************************
163 * \brief parse channels parameter and store result into list
164 * \param freq_channel if channels!=NULL this mean channel number, otherwise - frequency
165 * \param pfreq selected frequency (from selected channel or from URL)
166 * \result STREAM_OK if success, STREAM_ERROR otherwise
168 * channels option must be in the following format
169 * <frequency>-<name>,<frequency>-<name>,...
171 * '_' will be replaced with spaces.
173 * If channels option is not null, number in movie URL will be treated as
174 * channel position in channel list.
176 static int parse_channels(radio_priv_t
* priv
,float freq_channel
,float* pfreq
){
180 if (priv
->radio_param
->channels
){
181 /*parsing channels string*/
182 channels
=priv
->radio_param
->channels
;
184 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Radio channel names detected.\n");
185 priv
->radio_channel_list
= malloc(sizeof(radio_channels_t
));
186 priv
->radio_channel_list
->index
=1;
187 priv
->radio_channel_list
->next
=NULL
;
188 priv
->radio_channel_list
->prev
=NULL
;
189 priv
->radio_channel_current
= priv
->radio_channel_list
;
192 char* tmp
= *(channels
++);
193 char* sep
= strchr(tmp
,'-');
194 if (!sep
) continue; // Wrong syntax, but mplayer should not crash
195 av_strlcpy(priv
->radio_channel_current
->name
, sep
+ 1,sizeof(priv
->radio_channel_current
->name
)-1);
199 priv
->radio_channel_current
->freq
=atof(tmp
);
201 if ((priv
->radio_channel_current
->freq
>priv
->rangehigh
)||(priv
->radio_channel_current
->freq
<priv
->rangelow
))
202 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong frequency for channel %s\n",
203 priv
->radio_channel_current
->name
);
205 while ((sep
=strchr(priv
->radio_channel_current
->name
, '_'))) sep
[0] = ' ';
207 priv
->radio_channel_current
->next
= malloc(sizeof(radio_channels_t
));
208 priv
->radio_channel_current
->next
->index
= priv
->radio_channel_current
->index
+ 1;
209 priv
->radio_channel_current
->next
->prev
= priv
->radio_channel_current
;
210 priv
->radio_channel_current
->next
->next
= NULL
;
211 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
213 if (priv
->radio_channel_current
->prev
)
214 priv
->radio_channel_current
->prev
->next
= NULL
;
215 free(priv
->radio_channel_current
);
218 channel
= freq_channel
;
222 priv
->radio_channel_current
= priv
->radio_channel_list
;
223 for (i
= 1; i
< channel
; i
++)
224 if (priv
->radio_channel_current
->next
)
225 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
226 if (priv
->radio_channel_current
->index
!=channel
){
227 if (((float)((int)freq_channel
))!=freq_channel
)
228 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong channel number: %.2f\n",freq_channel
);
230 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong channel number: %d\n",(int)freq_channel
);
233 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Selected channel: %d - %s (freq: %.2f)\n", priv
->radio_channel_current
->index
,
234 priv
->radio_channel_current
->name
, priv
->radio_channel_current
->freq
);
235 *pfreq
=priv
->radio_channel_current
->freq
;
238 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Radio frequency parameter detected.\n");
239 priv
->radio_channel_list
=malloc(sizeof(radio_channels_t
));
240 priv
->radio_channel_list
->next
=NULL
;
241 priv
->radio_channel_list
->prev
=NULL
;
242 priv
->radio_channel_list
->index
=1;
243 snprintf(priv
->radio_channel_list
->name
,sizeof(priv
->radio_channel_current
->name
)-1,"Freq: %.2f",freq_channel
);
245 priv
->radio_channel_current
=priv
->radio_channel_list
;
249 mp_tmsg(MSGT_RADIO
, MSGL_DBG2
, "[radio] Done parsing channels.\n");
253 #ifdef CONFIG_RADIO_V4L2
254 /*****************************************************************
255 * \brief get fraction value for using in set_frequency and get_frequency
256 * \return STREAM_OK if success, STREAM_ERROR otherwise
258 * V4L2_TUNER_CAP_LOW:
260 * frac= 1MHz/unit=1000000/62.5 =16000
264 * frac= 1MHz/unit=1000000/62500 =16
266 static int init_frac_v4l2(radio_priv_t
* priv
){
267 struct v4l2_tuner tuner
;
269 memset(&tuner
,0,sizeof(tuner
));
271 if (ioctl(priv
->radio_fd
, VIDIOC_G_TUNER
, &tuner
)<0){
272 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] Warning: ioctl get tuner failed: %s. Setting frac to %d.\n",strerror(errno
),priv
->frac
);
275 if(tuner
.type
!=V4L2_TUNER_RADIO
){
276 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] %s is no radio device!\n",priv
->radio_param
->device
);
279 if(tuner
.capability
& V4L2_TUNER_CAP_LOW
){
281 mp_tmsg(MSGT_RADIO
,MSGL_DBG2
,"[radio] tuner is low:yes frac=%d\n",priv
->frac
);
285 mp_tmsg(MSGT_RADIO
,MSGL_DBG2
,"[radio] tuner is low:no frac=%d\n",priv
->frac
);
288 priv
->rangelow
=((float)tuner
.rangelow
)/priv
->frac
;
289 priv
->rangehigh
=((float)tuner
.rangehigh
)/priv
->frac
;
290 mp_tmsg(MSGT_RADIO
,MSGL_V
,"[radio] Allowed frequency range is %.2f-%.2f MHz.\n",priv
->rangelow
,priv
->rangehigh
);
294 /*****************************************************************
295 * \brief tune card to given frequency
296 * \param frequency frequency in MHz
297 * \return STREAM_OK if success, STREAM_ERROR otherwise
299 static int set_frequency_v4l2(radio_priv_t
* priv
,float frequency
){
300 struct v4l2_frequency freq
;
302 memset(&freq
,0,sizeof(freq
));
304 freq
.type
=V4L2_TUNER_RADIO
;
305 freq
.frequency
=frequency
*priv
->frac
;
306 if(ioctl(priv
->radio_fd
,VIDIOC_S_FREQUENCY
,&freq
)<0){
307 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl set frequency 0x%x (%.2f) failed: %s\n",freq
.frequency
,
308 frequency
,strerror(errno
));
314 /*****************************************************************
315 * \brief get current tuned frequency from card
316 * \param frequency where to store frequency in MHz
317 * \return STREAM_OK if success, STREAM_ERROR otherwise
319 static int get_frequency_v4l2(radio_priv_t
* priv
,float* frequency
){
320 struct v4l2_frequency freq
;
321 memset(&freq
,0,sizeof(freq
));
322 if (ioctl(priv
->radio_fd
, VIDIOC_G_FREQUENCY
, &freq
) < 0) {
323 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get frequency failed: %s\n",strerror(errno
));
326 *frequency
=((float)freq
.frequency
)/priv
->frac
;
330 /*****************************************************************
331 * \brief set volume on radio card
332 * \param volume volume level (0..100)
333 * \return STREAM_OK if success, STREAM_ERROR otherwise
335 static void set_volume_v4l2(radio_priv_t
* priv
,int volume
){
336 struct v4l2_queryctrl qctrl
;
337 struct v4l2_control control
;
339 /*arg must be between 0 and 100*/
340 if (volume
> 100) volume
= 100;
341 if (volume
< 0) volume
= 0;
343 memset(&control
,0,sizeof(control
));
344 control
.id
=V4L2_CID_AUDIO_MUTE
;
345 control
.value
= (volume
==0?1:0);
346 if (ioctl(priv
->radio_fd
, VIDIOC_S_CTRL
, &control
)<0){
347 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] ioctl set mute failed: %s\n",strerror(errno
));
350 memset(&qctrl
,0,sizeof(qctrl
));
351 qctrl
.id
= V4L2_CID_AUDIO_VOLUME
;
352 if (ioctl(priv
->radio_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
353 mp_tmsg(MSGT_RADIO
, MSGL_WARN
, "[radio] ioctl query control failed: %s\n",strerror(errno
));
357 memset(&control
,0,sizeof(control
));
358 control
.id
=V4L2_CID_AUDIO_VOLUME
;
359 control
.value
=qctrl
.minimum
+volume
*(qctrl
.maximum
-qctrl
.minimum
)/100;
360 if (ioctl(priv
->radio_fd
, VIDIOC_S_CTRL
, &control
) < 0) {
361 mp_tmsg(MSGT_RADIO
, MSGL_WARN
,"[radio] ioctl set volume failed: %s\n",strerror(errno
));
365 /*****************************************************************
366 * \brief get current volume from radio card
367 * \param volume where to store volume level (0..100)
368 * \return STREAM_OK if success, STREAM_ERROR otherwise
370 static int get_volume_v4l2(radio_priv_t
* priv
,int* volume
){
371 struct v4l2_queryctrl qctrl
;
372 struct v4l2_control control
;
374 memset(&qctrl
,0,sizeof(qctrl
));
375 qctrl
.id
= V4L2_CID_AUDIO_VOLUME
;
376 if (ioctl(priv
->radio_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
377 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] ioctl query control failed: %s\n",strerror(errno
));
381 memset(&control
,0,sizeof(control
));
382 control
.id
=V4L2_CID_AUDIO_VOLUME
;
383 if (ioctl(priv
->radio_fd
, VIDIOC_G_CTRL
, &control
) < 0) {
384 mp_tmsg(MSGT_RADIO
, MSGL_ERR
,"[radio] ioctl get volume failed: %s\n",strerror(errno
));
388 if (qctrl
.maximum
==qctrl
.minimum
)
389 *volume
=qctrl
.minimum
;
391 *volume
=100*(control
.value
-qctrl
.minimum
)/(qctrl
.maximum
-qctrl
.minimum
);
393 /*arg must be between 0 and 100*/
394 if (*volume
> 100) *volume
= 100;
395 if (*volume
< 0) *volume
= 0;
400 /* v4l2 driver info structure */
401 static const radio_driver_t radio_driver_v4l2
={
403 _("[radio] Using V4Lv2 radio interface.\n"),
410 #endif /* CONFIG_RADIO_V4L2 */
411 #ifdef CONFIG_RADIO_V4L
412 /*****************************************************************
413 * \brief get fraction value for using in set_frequency and get_frequency
414 * \return STREAM_OK if success, STREAM_ERROR otherwise
416 * V4L2_TUNER_CAP_LOW:
418 * frac= 1MHz/unit=1000000/62.5 =16000
422 * frac= 1MHz/unit=1000000/62500 =16
425 static int init_frac_v4l(radio_priv_t
* priv
){
426 struct video_tuner tuner
;
427 memset(&tuner
,0,sizeof(tuner
));
428 if (ioctl(priv
->radio_fd
, VIDIOCGTUNER
, &tuner
) <0){
429 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] Warning: ioctl get tuner failed: %s. Setting frac to %d.\n",strerror(errno
),priv
->frac
);
432 if(tuner
.flags
& VIDEO_TUNER_LOW
){
434 mp_tmsg(MSGT_RADIO
,MSGL_DBG2
,"[radio] tuner is low:yes frac=%d\n",priv
->frac
);
437 mp_tmsg(MSGT_RADIO
,MSGL_DBG2
,"[radio] tuner is low:no frac=%d\n",priv
->frac
);
440 priv
->rangelow
=((float)tuner
.rangelow
)/priv
->frac
;
441 priv
->rangehigh
=((float)tuner
.rangehigh
)/priv
->frac
;
442 mp_tmsg(MSGT_RADIO
,MSGL_V
,"[radio] Allowed frequency range is %.2f-%.2f MHz.\n",priv
->rangelow
,priv
->rangehigh
);
447 /*****************************************************************
448 * \brief tune card to given frequency
449 * \param frequency frequency in MHz
450 * \return STREAM_OK if success, STREAM_ERROR otherwise
452 static int set_frequency_v4l(radio_priv_t
* priv
,float frequency
){
454 freq
=frequency
*priv
->frac
;
455 if (ioctl(priv
->radio_fd
, VIDIOCSFREQ
, &freq
) < 0) {
456 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl set frequency 0x%x (%.2f) failed: %s\n",freq
,frequency
,strerror(errno
));
461 /*****************************************************************
462 * \brief get current tuned frequency from card
463 * \param frequency where to store frequency in MHz
464 * \return STREAM_OK if success, STREAM_ERROR otherwise
466 static int get_frequency_v4l(radio_priv_t
* priv
,float* frequency
){
468 if (ioctl(priv
->radio_fd
, VIDIOCGFREQ
, &freq
) < 0) {
469 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get frequency failed: %s\n",strerror(errno
));
472 *frequency
=((float)freq
)/priv
->frac
;
476 /*****************************************************************
477 * \brief set volume on radio card
478 * \param volume volume level (0..100)
479 * \return STREAM_OK if success, STREAM_ERROR otherwise
481 static void set_volume_v4l(radio_priv_t
* priv
,int volume
){
482 struct video_audio audio
;
484 /*arg must be between 0 and 100*/
485 if (volume
> 100) volume
= 100;
486 if (volume
< 0) volume
= 0;
488 memset(&audio
,0,sizeof(audio
));
489 audio
.flags
= (volume
==0?VIDEO_AUDIO_MUTE
:0);
490 if (ioctl(priv
->radio_fd
, VIDIOCSAUDIO
, &audio
)<0){
491 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] ioctl set mute failed: %s\n",strerror(errno
));
494 memset(&audio
,0,sizeof(audio
));
495 audio
.flags
= VIDEO_AUDIO_VOLUME
;
496 audio
.mode
= VIDEO_SOUND_STEREO
;
498 audio
.volume
= volume
* (65535 / 100);
500 if (ioctl(priv
->radio_fd
, VIDIOCSAUDIO
, &audio
) < 0){
501 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl set volume failed: %s\n",strerror(errno
));
505 /*****************************************************************
506 * \brief get current volume from radio card
507 * \param volume where to store volume level (0..100)
508 * \return STREAM_OK if success, STREAM_ERROR otherwise
510 static int get_volume_v4l(radio_priv_t
* priv
,int* volume
){
511 struct video_audio audio
;
513 memset(&audio
,0,sizeof(audio
));
515 if (ioctl(priv
->radio_fd
, VIDIOCGAUDIO
, &audio
) < 0){
516 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get volume failed: %s\n",strerror(errno
));
520 if (audio
.flags
& VIDEO_AUDIO_VOLUME
){
521 *volume
=100*audio
.volume
/65535;
522 /*arg must be between 0 and 100*/
523 if (*volume
> 100) *volume
= 100;
524 if (*volume
< 0) *volume
= 0;
531 /* v4l driver info structure */
532 static const radio_driver_t radio_driver_v4l
={
534 _("[radio] Using V4Lv1 radio interface.\n"),
541 #endif /* CONFIG_RADIO_V4L */
542 #ifdef CONFIG_RADIO_BSDBT848
544 /*****************************************************************
545 * \brief get fraction value for using in set_frequency and get_frequency
546 * \return STREAM_OK if success, STREAM_ERROR otherwise
548 * For *BSD BT848 frac=100
550 * Here is a coment from FreeBSD 5.2-RELEASE source code:
553 * * Programming the tuner properly is quite complicated.
554 * * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner.
555 * * The tuner (front end) covers 45.75 MHz - 855.25 MHz and an FM band of
556 * * 87.5 MHz to 108.0 MHz.
558 * Thus, frequency range is limited to 87.5-108.0, but you can change
559 * it, using freq_min and freq_max options
561 static int init_frac_bsdbt848(radio_priv_t
* priv
){
563 priv
->rangelow
=priv
->radio_param
->freq_min
;
564 priv
->rangehigh
=priv
->radio_param
->freq_max
;
568 /*****************************************************************
569 * \brief tune card to given frequency
570 * \param frequency frequency in MHz
571 * \return STREAM_OK if success, STREAM_ERROR otherwise
573 static int set_frequency_bsdbt848(radio_priv_t
* priv
,float frequency
){
575 freq
=frequency
*priv
->frac
;
576 if(ioctl(priv
->radio_fd
,RADIO_SETFREQ
,&freq
)<0){
577 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl set frequency 0x%x (%.2f) failed: %s\n",freq
, frequency
, strerror(errno
));
583 /*****************************************************************
584 * \brief get current tuned frequency from card
585 * \param frequency where to store frequency in MHz
586 * \return STREAM_OK if success, STREAM_ERROR otherwise
588 static int get_frequency_bsdbt848(radio_priv_t
* priv
,float* frequency
){
590 if (ioctl(priv
->radio_fd
, RADIO_GETFREQ
, &freq
) < 0) {
591 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get frequency failed: %s\n",strerror(errno
));
594 *frequency
=((float)freq
)/priv
->frac
;
598 /*****************************************************************
599 * \brief set volume on radio card
600 * \param volume volume level (0..100)
601 * \return STREAM_OK if success, STREAM_ERROR otherwise
603 * *BSD BT848 does not have volume changing abilities, so
604 * we will just mute sound if volume=0 and unmute it otherwise.
606 static void set_volume_bsdbt848(radio_priv_t
* priv
,int volume
){
609 /*arg must be between 0 and 100*/
610 if (volume
> 100) volume
= 100;
611 if (volume
< 0) volume
= 0;
613 audio_flags
= (volume
==0?AUDIO_MUTE
:AUDIO_UNMUTE
);
614 if (ioctl(priv
->radio_fd
, BT848_SAUDIO
, &audio_flags
)<0){
615 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] ioctl set mute failed: %s\n",strerror(errno
));
619 /*****************************************************************
620 * \brief get current volume from radio card
621 * \param volume where to store volume level (0..100)
622 * \return previous STREAM_OK if success, STREAM_ERROR otherwise
624 * *BSD BT848 does not have volume changing abilities, so
625 * we will return 0 if sound is muted and 100 otherwise.
627 static int get_volume_bsdbt848(radio_priv_t
* priv
,int* volume
){
630 if (ioctl(priv
->radio_fd
, BT848_GAUDIO
, &audio_flags
)<0){
631 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get volume failed: %s\n",strerror(errno
));
635 if (audio_flags
& AUDIO_MUTE
)
643 /* bsdbt848 driver info structure */
644 static const radio_driver_t radio_driver_bsdbt848
={
646 _("[radio] Using *BSD BT848 radio interface.\n"),
650 set_frequency_bsdbt848
,
651 get_frequency_bsdbt848
653 #endif /* CONFIG_RADIO_BSDBT848 */
655 static inline int init_frac(radio_priv_t
* priv
){
656 return priv
->driver
->init_frac(priv
);
658 static inline int set_frequency(radio_priv_t
* priv
,float frequency
){
659 if ((frequency
<priv
->rangelow
)||(frequency
>priv
->rangehigh
)){
660 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong frequency: %.2f\n",frequency
);
663 if(priv
->driver
->set_frequency(priv
,frequency
)!=STREAM_OK
)
666 #ifdef CONFIG_RADIO_CAPTURE
667 if(clear_buffer(priv
)!=STREAM_OK
){
668 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Clearing buffer failed: %s\n",strerror(errno
));
674 static inline int get_frequency(radio_priv_t
* priv
,float* frequency
){
675 return priv
->driver
->get_frequency(priv
,frequency
);
677 static inline void set_volume(radio_priv_t
* priv
,int volume
){
678 priv
->driver
->set_volume(priv
,volume
);
680 static inline int get_volume(radio_priv_t
* priv
,int* volume
){
681 return priv
->driver
->get_volume(priv
,volume
);
685 #ifndef CONFIG_RADIO_CAPTURE
686 /*****************************************************************
687 * \brief stub, if capture disabled at compile-time
690 static inline int init_audio(radio_priv_t
*priv
){ return STREAM_OK
;}
692 /*****************************************************************
693 * \brief making buffer empty
694 * \return STREAM_OK if success, STREAM_ERROR otherwise
696 * when changing channel we must clear buffer to avoid large switching delay
698 static int clear_buffer(radio_priv_t
* priv
){
699 if (!priv
->do_capture
) return STREAM_OK
;
700 priv
->audio_tail
= 0;
701 priv
->audio_head
= 0;
703 memset(priv
->audio_ringbuffer
,0,priv
->audio_in
.blocksize
);
706 /*****************************************************************
707 * \brief read next part of data into buffer
708 * \return -1 if error occured or no data available yet, otherwise - bytes read
709 * NOTE: audio device works in non-blocking mode
711 static int read_chunk(audio_in_t
*ai
, unsigned char *buffer
)
718 //device opened in non-blocking mode
719 ret
= snd_pcm_readi(ai
->alsa
.handle
, buffer
, ai
->alsa
.chunk_size
);
720 if (ret
!= ai
->alsa
.chunk_size
) {
722 if (ret
==-EAGAIN
) return -1;
723 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "\nError reading audio: %s\n", snd_strerror(ret
));
725 if (ai_alsa_xrun(ai
) == 0) {
726 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "Recovered from cross-run, some frames may be left out!\n");
728 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "Fatal error, cannot recover!\n");
732 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "\nNot enough audio samples!\n");
738 #ifdef CONFIG_OSS_AUDIO
743 we must return exactly blocksize bytes, so if we have got any bytes
744 at first call to read, we will loop untils get all blocksize bytes
745 otherwise we will return -1
747 while(bt
<ai
->blocksize
){
748 //device opened in non-blocking mode
749 ret
= read(ai
->oss
.audio_fd
, buffer
+bt
, ai
->blocksize
-bt
);
750 if (ret
==ai
->blocksize
) return ret
;
752 if (errno
==EAGAIN
&& bt
==0) return -1; //no data avail yet
753 if (errno
==EAGAIN
) { usleep(1000); continue;} //nilling buffer to blocksize size
754 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "\nError reading audio: %s\n", strerror(errno
));
766 /*****************************************************************
767 * \brief grab next frame from audio device
768 * \parameter buffer - store buffer
769 * \parameter len - store buffer size in bytes
770 * \return number of bytes written into buffer
772 * grabs len (or less) bytes from ringbuffer into buffer
773 * if ringbuffer is empty waits until len bytes of data will be available
775 * priv->audio_cnt - size (in bytes) of ringbuffer's filled part
776 * priv->audio_drop - size (in bytes) of dropped data (if no space in ringbuffer)
777 * priv->audio_head - index of first byte in filled part
778 * priv->audio_tail - index of last byte in filled part
780 * NOTE: audio_tail always aligned by priv->audio_in.blocksize
781 * audio_head may NOT.
783 static int grab_audio_frame(radio_priv_t
*priv
, char *buffer
, int len
)
786 mp_tmsg(MSGT_RADIO
, MSGL_DBG3
, "[radio] %s: in buffer=%d dropped=%d\n","grab_audio_frame",priv
->audio_cnt
,priv
->audio_drop
);
787 /* Cache buffer must be filled by some audio packets when playing starts.
788 Otherwise MPlayer will quit with EOF error.
789 Probably, there is need more carefull checking rather than simple 'for' loop
790 (something like timer or similar).
792 1000ms delay will happen only at first buffer filling. At next call function
793 just fills buffer until either buffer full or no data from driver available.
795 for (i
=0;i
<1000 && !priv
->audio_cnt
; i
++){
796 //read_chunk fills exact priv->blocksize bytes
797 if(read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
) < 0){
798 //sleppeing only when waiting first block to fill empty buffer
799 if (!priv
->audio_cnt
){
805 priv
->audio_cnt
+=priv
->audio_in
.blocksize
;
806 priv
->audio_tail
= (priv
->audio_tail
+priv
->audio_in
.blocksize
) % priv
->audio_buffer_size
;
808 if(priv
->audio_cnt
<len
)
810 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
,len
);
811 priv
->audio_head
= (priv
->audio_head
+len
) % priv
->audio_buffer_size
;
812 priv
->audio_cnt
-=len
;
815 /*****************************************************************
816 * \brief init audio device
817 * \return STREAM_OK if success, STREAM_ERROR otherwise
819 static int init_audio(radio_priv_t
*priv
)
824 if (priv
->audio_initialized
) return 1;
826 /* do_capture==0 mplayer was not started with capture keyword, so disabling capture*/
827 if(!priv
->do_capture
)
830 if (!priv
->radio_param
->adevice
){
836 mp_tmsg(MSGT_RADIO
,MSGL_V
,"[radio] Starting capture stuff.\n");
838 while ((tmp
= strrchr(priv
->radio_param
->adevice
, '='))){
840 //adevice option looks like ALSA device name. Switching to ALSA
843 while ((tmp
= strrchr(priv
->radio_param
->adevice
, '.')))
847 if(audio_in_init(&priv
->audio_in
, is_oss
?AUDIO_IN_OSS
:AUDIO_IN_ALSA
)<0){
848 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] audio_in_init failed.\n");
851 audio_in_set_device(&priv
->audio_in
, priv
->radio_param
->adevice
);
852 audio_in_set_channels(&priv
->audio_in
, priv
->radio_param
->achannels
);
853 audio_in_set_samplerate(&priv
->audio_in
, priv
->radio_param
->arate
);
855 if (audio_in_setup(&priv
->audio_in
) < 0) {
856 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] audio_in_setup call failed: %s\n", strerror(errno
));
859 #ifdef CONFIG_OSS_AUDIO
861 ioctl(priv
->audio_in
.oss
.audio_fd
, SNDCTL_DSP_NONBLOCK
, 0);
865 snd_pcm_nonblock(priv
->audio_in
.alsa
.handle
,1);
868 priv
->audio_buffer_size
= seconds
*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
869 priv
->audio_in
.bytes_per_sample
+priv
->audio_in
.blocksize
;
870 if (priv
->audio_buffer_size
< 256*priv
->audio_in
.blocksize
)
871 priv
->audio_buffer_size
= 256*priv
->audio_in
.blocksize
;
872 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Audio capture - buffer=%d bytes (block=%d bytes).\n",
873 priv
->audio_buffer_size
,priv
->audio_in
.blocksize
);
875 priv
->audio_ringbuffer
= calloc(1, priv
->audio_buffer_size
);
876 if (!priv
->audio_ringbuffer
) {
877 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] cannot allocate audio buffer (block=%d,buf=%d): %s\n",priv
->audio_in
.blocksize
, priv
->audio_buffer_size
, strerror(errno
));
880 priv
->audio_head
= 0;
881 priv
->audio_tail
= 0;
883 priv
->audio_drop
= 0;
885 audio_in_start_capture(&priv
->audio_in
);
887 priv
->audio_initialized
= 1;
891 #endif /* CONFIG_RADIO_CAPTURE */
893 /*-------------------------------------------------------------------------
894 for call from mplayer.c
895 --------------------------------------------------------------------------*/
896 /*****************************************************************
897 * \brief public wrapper for get_frequency
898 * \parameter frequency pointer to float, which will contain frequency in MHz
899 * \return 1 if success,0 - otherwise
901 int radio_get_freq(struct stream
*stream
, float *frequency
){
902 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
906 if (get_frequency(priv
,frequency
)!=STREAM_OK
){
911 /*****************************************************************
912 * \brief public wrapper for set_frequency
913 * \parameter frequency frequency in MHz
914 * \return 1 if success,0 - otherwise
916 int radio_set_freq(struct stream
*stream
, float frequency
){
917 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
919 if (set_frequency(priv
,frequency
)!=STREAM_OK
){
922 if (get_frequency(priv
,&frequency
)!=STREAM_OK
){
925 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Current frequency: %.2f\n",frequency
);
929 /*****************************************************************
930 * \brief tune current frequency by step_interval value
931 * \parameter step_interval increment value
932 * \return 1 if success,0 - otherwise
935 int radio_step_freq(struct stream
*stream
, float step_interval
){
937 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
939 if (get_frequency(priv
,&frequency
)!=STREAM_OK
)
942 frequency
+=step_interval
;
943 if (frequency
>priv
->rangehigh
)
944 frequency
=priv
->rangehigh
;
945 if (frequency
<priv
->rangelow
)
946 frequency
=priv
->rangelow
;
948 return radio_set_freq(stream
,frequency
);
950 /*****************************************************************
951 * \brief step channel up or down
952 * \parameter direction RADIO_CHANNEL_LOWER - go to prev channel,RADIO_CHANNEL_HIGHER - to next
953 * \return 1 if success,0 - otherwise
955 * if channel parameter is NULL function prints error message and does nothing, otherwise
956 * changes channel to prev or next in list
958 int radio_step_channel(struct stream
*stream
, int direction
) {
959 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
961 if (priv
->radio_channel_list
) {
963 case RADIO_CHANNEL_HIGHER
:
964 if (priv
->radio_channel_current
->next
)
965 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
967 priv
->radio_channel_current
= priv
->radio_channel_list
;
968 if(!radio_set_freq(stream
,priv
->radio_channel_current
->freq
))
970 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Selected channel: %d - %s (freq: %.2f)\n",
971 priv
->radio_channel_current
->index
, priv
->radio_channel_current
->name
,
972 priv
->radio_channel_current
->freq
);
974 case RADIO_CHANNEL_LOWER
:
975 if (priv
->radio_channel_current
->prev
)
976 priv
->radio_channel_current
= priv
->radio_channel_current
->prev
;
978 while (priv
->radio_channel_current
->next
)
979 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
980 if(!radio_set_freq(stream
,priv
->radio_channel_current
->freq
))
982 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Selected channel: %d - %s (freq: %.2f)\n",
983 priv
->radio_channel_current
->index
, priv
->radio_channel_current
->name
,
984 priv
->radio_channel_current
->freq
);
988 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Can not change channel: no channel list given.\n");
992 /*****************************************************************
993 * \brief change channel to one with given index
994 * \parameter channel string, containing channel number
995 * \return 1 if success,0 - otherwise
997 * if channel parameter is NULL function prints error message and does nothing, otherwise
998 * changes channel to given
1000 int radio_set_channel(struct stream
*stream
, char *channel
) {
1001 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
1003 radio_channels_t
* tmp
;
1007 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong channel name: %s\n",channel
);
1009 if (priv
->radio_channel_list
) {
1010 channel_int
= strtol(channel
,&endptr
,10);
1011 tmp
= priv
->radio_channel_list
;
1013 //channel is not a number, so it contains channel name
1014 for ( ; tmp
; tmp
=tmp
->next
)
1015 if (!strncmp(channel
,tmp
->name
,sizeof(tmp
->name
)-1))
1018 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong channel name: %s\n",channel
);
1022 for (i
= 1; i
< channel_int
; i
++)
1027 if (tmp
->index
!=channel_int
){
1028 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong channel number: %d\n",channel_int
);
1032 priv
->radio_channel_current
=tmp
;
1033 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Selected channel: %d - %s (freq: %.2f)\n", priv
->radio_channel_current
->index
,
1034 priv
->radio_channel_current
->name
, priv
->radio_channel_current
->freq
);
1035 if(!radio_set_freq(stream
, priv
->radio_channel_current
->freq
))
1038 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Can not change channel: no channel list given.\n");
1042 /*****************************************************************
1043 * \brief get current channel's name
1044 * \return pointer to string, containing current channel's name
1046 * NOTE: return value may be NULL (e.g. when channel list not initialized)
1048 char* radio_get_channel_name(struct stream
*stream
){
1049 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
1050 if (priv
->radio_channel_current
) {
1051 return priv
->radio_channel_current
->name
;
1056 /*****************************************************************
1057 * \brief fills given buffer with audio data
1058 * \return number of bytes, written into buffer
1060 static int fill_buffer_s(struct stream
*s
, char *buffer
, int max_len
){
1063 #ifdef CONFIG_RADIO_CAPTURE
1064 radio_priv_t
* priv
=(radio_priv_t
*)s
->priv
;
1066 if (priv
->do_capture
){
1067 len
=grab_audio_frame(priv
, buffer
,max_len
);
1071 memset(buffer
,0,len
);
1077 order if significant!
1078 when no driver explicitly specified first available will be used
1080 static const radio_driver_t
* radio_drivers
[]={
1081 #ifdef CONFIG_RADIO_BSDBT848
1082 &radio_driver_bsdbt848
,
1084 #ifdef CONFIG_RADIO_V4L2
1087 #ifdef CONFIG_RADIO_V4L
1093 /*****************************************************************
1094 * Stream initialization
1095 * \return STREAM_OK if success, STREAM_ERROR otherwise
1097 static int open_s(stream_t
*stream
,int mode
, void* opts
, int* file_format
) {
1102 if (strncmp("radio://",stream
->url
,8) != 0)
1103 return STREAM_UNSUPPORTED
;
1105 if(mode
!= STREAM_READ
)
1106 return STREAM_UNSUPPORTED
;
1108 priv
=calloc(1,sizeof(radio_priv_t
));
1111 return STREAM_ERROR
;
1114 priv
->radio_param
=opts
;
1116 #ifdef CONFIG_RADIO_CAPTURE
1117 if (priv
->radio_param
->capture
&& strncmp("capture",priv
->radio_param
->capture
,7)==0)
1125 if (strncmp(priv
->radio_param
->driver
,"default",7)==0)
1126 priv
->driver
=radio_drivers
[0];
1130 mp_tmsg(MSGT_RADIO
,MSGL_V
,"[radio] Available drivers: ");
1131 for(i
=0;radio_drivers
[i
];i
++){
1132 mp_msg(MSGT_RADIO
,MSGL_V
,"%s, ",radio_drivers
[i
]->name
);
1133 if(strcmp(priv
->radio_param
->driver
,radio_drivers
[i
]->name
)==0)
1134 priv
->driver
=radio_drivers
[i
];
1136 mp_msg(MSGT_RADIO
,MSGL_V
,"\n");
1139 mp_msg(MSGT_RADIO
, MSGL_INFO
, priv
->driver
->info
);
1141 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Unknown driver name: %s\n",priv
->radio_param
->driver
);
1143 return STREAM_ERROR
;
1146 stream
->type
= STREAMTYPE_RADIO
;
1147 /* using rawaudio demuxer */
1148 *file_format
= DEMUXER_TYPE_RAWAUDIO
;
1149 stream
->flags
= STREAM_READ
;
1153 stream
->start_pos
=0;
1156 stream
->close
=close_s
;
1157 stream
->fill_buffer
=fill_buffer_s
;
1159 priv
->radio_fd
= open(priv
->radio_param
->device
, O_RDONLY
);
1160 if (priv
->radio_fd
< 0) {
1161 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Unable to open '%s': %s\n",
1162 priv
->radio_param
->device
, strerror(errno
));
1164 return STREAM_ERROR
;
1166 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Radio fd: %d, %s\n", priv
->radio_fd
,priv
->radio_param
->device
);
1167 fcntl(priv
->radio_fd
, F_SETFD
, FD_CLOEXEC
);
1169 get_volume(priv
, &priv
->old_snd_volume
);
1172 if (init_frac(priv
)!=STREAM_OK
){
1174 return STREAM_ERROR
;
1177 if (parse_channels(priv
,priv
->radio_param
->freq_channel
,&frequency
)!=STREAM_OK
){
1179 return STREAM_ERROR
;
1182 if ((frequency
<priv
->rangelow
)||(frequency
>priv
->rangehigh
)){
1183 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong frequency: %.2f\n",frequency
);
1185 return STREAM_ERROR
;
1187 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Using frequency: %.2f.\n",frequency
);
1189 if(set_frequency(priv
,frequency
)!=STREAM_OK
){
1191 return STREAM_ERROR
;
1195 if (init_audio(priv
)!=STREAM_OK
){
1197 return STREAM_ERROR
;
1200 #if defined(CONFIG_RADIO_CAPTURE) && defined(CONFIG_STREAM_CACHE)
1201 if(priv
->do_capture
){
1203 if(!stream_enable_cache(stream
,5*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
1204 priv
->audio_in
.bytes_per_sample
,2*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
1205 priv
->audio_in
.bytes_per_sample
,priv
->audio_in
.blocksize
)) {
1206 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Call to stream_enable_cache failed: %s\n",strerror(errno
));
1208 return STREAM_ERROR
;
1213 set_volume(priv
,priv
->radio_param
->volume
);
1218 /*****************************************************************
1219 * Close stream. Clear structures.
1221 static void close_s(struct stream
*stream
){
1222 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
1223 radio_channels_t
* tmp
;
1226 #ifdef CONFIG_RADIO_CAPTURE
1227 free(priv
->audio_ringbuffer
);
1228 priv
->audio_ringbuffer
= NULL
;
1233 while (priv
->radio_channel_list
) {
1234 tmp
=priv
->radio_channel_list
;
1235 priv
->radio_channel_list
=priv
->radio_channel_list
->next
;
1238 priv
->radio_channel_current
=NULL
;
1239 priv
->radio_channel_list
=NULL
;
1241 if (priv
->radio_fd
>0){
1242 set_volume(priv
, priv
->old_snd_volume
);
1243 close(priv
->radio_fd
);
1246 if(priv
->radio_param
)
1247 m_struct_free(&stream_opts
,priv
->radio_param
);
1252 const stream_info_t stream_info_radio
= {
1255 "Vladimir Voroshilov",
1260 1 // Urls are an option string