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 #endif // !IOCTL_BT848_H_NAME
56 #include "libmpdemux/demuxer.h"
60 #include "stream_radio.h"
61 #include "libavutil/avstring.h"
63 #ifdef CONFIG_RADIO_CAPTURE
66 #ifdef HAVE_SYS_SOUNDCARD_H
67 #include <sys/soundcard.h>
69 #ifdef HAVE_SOUNDCARD_H
70 #include <soundcard.h>
72 #include <linux/soundcard.h>
78 typedef struct radio_channels_s
{
79 int index
; ///< channel index in channels list
80 float freq
; ///< frequency in MHz
81 char name
[20]; ///< channel name
82 struct radio_channels_s
* next
;
83 struct radio_channels_s
* prev
;
86 /// default values for options
87 radio_param_t stream_radio_defaults
={
88 #ifdef CONFIG_RADIO_BSDBT848
89 "/dev/tuner0", //device
93 "/dev/radio0", //device;
105 typedef struct radio_priv_s
{
106 int radio_fd
; ///< radio device descriptor
107 int frac
; ///< fraction value (see comment to init_frac)
108 radio_channels_t
* radio_channel_list
;
109 radio_channels_t
* radio_channel_current
;
110 float rangelow
; ///< lowest tunable frequency in MHz
111 float rangehigh
; ///< highest tunable frequency in MHz
112 const struct radio_driver_s
* driver
;
114 #ifdef CONFIG_RADIO_CAPTURE
115 volatile int do_capture
; ///< is capture enabled
117 unsigned char* audio_ringbuffer
;
118 int audio_head
; ///< start of meanfull data in ringbuffer
119 int audio_tail
; ///< end of meanfull data in ringbuffer
120 int audio_buffer_size
; ///< size of ringbuffer
121 int audio_cnt
; ///< size of meanfull data inringbuffer
122 int audio_drop
; ///< number of dropped bytes
123 int audio_initialized
;
125 radio_param_t
*radio_param
;
128 typedef struct radio_driver_s
{
131 int (*init_frac
)(radio_priv_t
* priv
);
132 void (*set_volume
)(radio_priv_t
* priv
,int volume
);
133 int (*get_volume
)(radio_priv_t
* priv
,int* volume
);
134 int (*set_frequency
)(radio_priv_t
* priv
,float frequency
);
135 int (*get_frequency
)(radio_priv_t
* priv
,float* frequency
);
138 #define ST_OFF(f) M_ST_OFF(radio_param_t,f)
139 static const m_option_t stream_opts_fields
[] = {
140 {"hostname", ST_OFF(freq_channel
), CONF_TYPE_FLOAT
, 0, 0 ,0, NULL
},
141 {"filename", ST_OFF(capture
), CONF_TYPE_STRING
, 0, 0 ,0, NULL
},
142 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
145 static const struct m_struct_st stream_opts
= {
147 sizeof(radio_param_t
),
148 &stream_radio_defaults
,
152 static void close_s(struct stream
*stream
);
153 #ifdef CONFIG_RADIO_CAPTURE
154 static int clear_buffer(radio_priv_t
* priv
);
158 /*****************************************************************
159 * \brief parse channels parameter and store result into list
160 * \param freq_channel if channels!=NULL this mean channel number, otherwise - frequency
161 * \param pfreq selected frequency (from selected channel or from URL)
162 * \result STREAM_OK if success, STREAM_ERROR otherwise
164 * channels option must be in the following format
165 * <frequency>-<name>,<frequency>-<name>,...
167 * '_' will be replaced with spaces.
169 * If channels option is not null, number in movie URL will be treated as
170 * channel position in channel list.
172 static int parse_channels(radio_priv_t
* priv
,float freq_channel
,float* pfreq
){
176 if (priv
->radio_param
->channels
){
177 /*parsing channels string*/
178 channels
=priv
->radio_param
->channels
;
180 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Radio channel names detected.\n");
181 priv
->radio_channel_list
= malloc(sizeof(radio_channels_t
));
182 priv
->radio_channel_list
->index
=1;
183 priv
->radio_channel_list
->next
=NULL
;
184 priv
->radio_channel_list
->prev
=NULL
;
185 priv
->radio_channel_current
= priv
->radio_channel_list
;
188 char* tmp
= *(channels
++);
189 char* sep
= strchr(tmp
,'-');
190 if (!sep
) continue; // Wrong syntax, but mplayer should not crash
191 av_strlcpy(priv
->radio_channel_current
->name
, sep
+ 1,sizeof(priv
->radio_channel_current
->name
)-1);
195 priv
->radio_channel_current
->freq
=atof(tmp
);
197 if ((priv
->radio_channel_current
->freq
>priv
->rangehigh
)||(priv
->radio_channel_current
->freq
<priv
->rangelow
))
198 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong frequency for channel %s\n",
199 priv
->radio_channel_current
->name
);
201 while ((sep
=strchr(priv
->radio_channel_current
->name
, '_'))) sep
[0] = ' ';
203 priv
->radio_channel_current
->next
= malloc(sizeof(radio_channels_t
));
204 priv
->radio_channel_current
->next
->index
= priv
->radio_channel_current
->index
+ 1;
205 priv
->radio_channel_current
->next
->prev
= priv
->radio_channel_current
;
206 priv
->radio_channel_current
->next
->next
= NULL
;
207 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
209 if (priv
->radio_channel_current
->prev
)
210 priv
->radio_channel_current
->prev
->next
= NULL
;
211 free(priv
->radio_channel_current
);
214 channel
= freq_channel
;
218 priv
->radio_channel_current
= priv
->radio_channel_list
;
219 for (i
= 1; i
< channel
; i
++)
220 if (priv
->radio_channel_current
->next
)
221 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
222 if (priv
->radio_channel_current
->index
!=channel
){
223 if (((float)((int)freq_channel
))!=freq_channel
)
224 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong channel number: %.2f\n",freq_channel
);
226 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong channel number: %d\n",(int)freq_channel
);
229 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Selected channel: %d - %s (freq: %.2f)\n", priv
->radio_channel_current
->index
,
230 priv
->radio_channel_current
->name
, priv
->radio_channel_current
->freq
);
231 *pfreq
=priv
->radio_channel_current
->freq
;
234 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Radio frequency parameter detected.\n");
235 priv
->radio_channel_list
=malloc(sizeof(radio_channels_t
));
236 priv
->radio_channel_list
->next
=NULL
;
237 priv
->radio_channel_list
->prev
=NULL
;
238 priv
->radio_channel_list
->index
=1;
239 snprintf(priv
->radio_channel_list
->name
,sizeof(priv
->radio_channel_current
->name
)-1,"Freq: %.2f",freq_channel
);
241 priv
->radio_channel_current
=priv
->radio_channel_list
;
245 mp_tmsg(MSGT_RADIO
, MSGL_DBG2
, "[radio] Done parsing channels.\n");
249 #ifdef CONFIG_RADIO_V4L2
250 /*****************************************************************
251 * \brief get fraction value for using in set_frequency and get_frequency
252 * \return STREAM_OK if success, STREAM_ERROR otherwise
254 * V4L2_TUNER_CAP_LOW:
256 * frac= 1MHz/unit=1000000/62.5 =16000
260 * frac= 1MHz/unit=1000000/62500 =16
262 static int init_frac_v4l2(radio_priv_t
* priv
){
263 struct v4l2_tuner tuner
;
265 memset(&tuner
,0,sizeof(tuner
));
267 if (ioctl(priv
->radio_fd
, VIDIOC_G_TUNER
, &tuner
)<0){
268 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] Warning: ioctl get tuner failed: %s. Setting frac to %d.\n",strerror(errno
),priv
->frac
);
271 if(tuner
.type
!=V4L2_TUNER_RADIO
){
272 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] %s is no radio device!\n",priv
->radio_param
->device
);
275 if(tuner
.capability
& V4L2_TUNER_CAP_LOW
){
277 mp_tmsg(MSGT_RADIO
,MSGL_DBG2
,"[radio] tuner is low:yes frac=%d\n",priv
->frac
);
281 mp_tmsg(MSGT_RADIO
,MSGL_DBG2
,"[radio] tuner is low:no frac=%d\n",priv
->frac
);
284 priv
->rangelow
=((float)tuner
.rangelow
)/priv
->frac
;
285 priv
->rangehigh
=((float)tuner
.rangehigh
)/priv
->frac
;
286 mp_tmsg(MSGT_RADIO
,MSGL_V
,"[radio] Allowed frequency range is %.2f-%.2f MHz.\n",priv
->rangelow
,priv
->rangehigh
);
290 /*****************************************************************
291 * \brief tune card to given frequency
292 * \param frequency frequency in MHz
293 * \return STREAM_OK if success, STREAM_ERROR otherwise
295 static int set_frequency_v4l2(radio_priv_t
* priv
,float frequency
){
296 struct v4l2_frequency freq
;
298 memset(&freq
,0,sizeof(freq
));
300 freq
.type
=V4L2_TUNER_RADIO
;
301 freq
.frequency
=frequency
*priv
->frac
;
302 if(ioctl(priv
->radio_fd
,VIDIOC_S_FREQUENCY
,&freq
)<0){
303 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl set frequency 0x%x (%.2f) failed: %s\n",freq
.frequency
,
304 frequency
,strerror(errno
));
310 /*****************************************************************
311 * \brief get current tuned frequency from card
312 * \param frequency where to store frequency in MHz
313 * \return STREAM_OK if success, STREAM_ERROR otherwise
315 static int get_frequency_v4l2(radio_priv_t
* priv
,float* frequency
){
316 struct v4l2_frequency freq
;
317 memset(&freq
,0,sizeof(freq
));
318 if (ioctl(priv
->radio_fd
, VIDIOC_G_FREQUENCY
, &freq
) < 0) {
319 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get frequency failed: %s\n",strerror(errno
));
322 *frequency
=((float)freq
.frequency
)/priv
->frac
;
326 /*****************************************************************
327 * \brief set volume on radio card
328 * \param volume volume level (0..100)
329 * \return STREAM_OK if success, STREAM_ERROR otherwise
331 static void set_volume_v4l2(radio_priv_t
* priv
,int volume
){
332 struct v4l2_queryctrl qctrl
;
333 struct v4l2_control control
;
335 /*arg must be between 0 and 100*/
336 if (volume
> 100) volume
= 100;
337 if (volume
< 0) volume
= 0;
339 memset(&control
,0,sizeof(control
));
340 control
.id
=V4L2_CID_AUDIO_MUTE
;
341 control
.value
= (volume
==0?1:0);
342 if (ioctl(priv
->radio_fd
, VIDIOC_S_CTRL
, &control
)<0){
343 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] ioctl set mute failed: %s\n",strerror(errno
));
346 memset(&qctrl
,0,sizeof(qctrl
));
347 qctrl
.id
= V4L2_CID_AUDIO_VOLUME
;
348 if (ioctl(priv
->radio_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
349 mp_tmsg(MSGT_RADIO
, MSGL_WARN
, "[radio] ioctl query control failed: %s\n",strerror(errno
));
353 memset(&control
,0,sizeof(control
));
354 control
.id
=V4L2_CID_AUDIO_VOLUME
;
355 control
.value
=qctrl
.minimum
+volume
*(qctrl
.maximum
-qctrl
.minimum
)/100;
356 if (ioctl(priv
->radio_fd
, VIDIOC_S_CTRL
, &control
) < 0) {
357 mp_tmsg(MSGT_RADIO
, MSGL_WARN
,"[radio] ioctl set volume failed: %s\n",strerror(errno
));
361 /*****************************************************************
362 * \brief get current volume from radio card
363 * \param volume where to store volume level (0..100)
364 * \return STREAM_OK if success, STREAM_ERROR otherwise
366 static int get_volume_v4l2(radio_priv_t
* priv
,int* volume
){
367 struct v4l2_queryctrl qctrl
;
368 struct v4l2_control control
;
370 memset(&qctrl
,0,sizeof(qctrl
));
371 qctrl
.id
= V4L2_CID_AUDIO_VOLUME
;
372 if (ioctl(priv
->radio_fd
, VIDIOC_QUERYCTRL
, &qctrl
) < 0) {
373 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] ioctl query control failed: %s\n",strerror(errno
));
377 memset(&control
,0,sizeof(control
));
378 control
.id
=V4L2_CID_AUDIO_VOLUME
;
379 if (ioctl(priv
->radio_fd
, VIDIOC_G_CTRL
, &control
) < 0) {
380 mp_tmsg(MSGT_RADIO
, MSGL_ERR
,"[radio] ioctl get volume failed: %s\n",strerror(errno
));
384 if (qctrl
.maximum
==qctrl
.minimum
)
385 *volume
=qctrl
.minimum
;
387 *volume
=100*(control
.value
-qctrl
.minimum
)/(qctrl
.maximum
-qctrl
.minimum
);
389 /*arg must be between 0 and 100*/
390 if (*volume
> 100) *volume
= 100;
391 if (*volume
< 0) *volume
= 0;
396 /* v4l2 driver info structure */
397 static const radio_driver_t radio_driver_v4l2
={
399 _("[radio] Using V4Lv2 radio interface.\n"),
406 #endif /* CONFIG_RADIO_V4L2 */
407 #ifdef CONFIG_RADIO_BSDBT848
409 /*****************************************************************
410 * \brief get fraction value for using in set_frequency and get_frequency
411 * \return STREAM_OK if success, STREAM_ERROR otherwise
413 * For *BSD BT848 frac=100
415 * Here is a coment from FreeBSD 5.2-RELEASE source code:
418 * * Programming the tuner properly is quite complicated.
419 * * Here are some notes, based on a FM1246 data sheet for a PAL-I tuner.
420 * * The tuner (front end) covers 45.75 MHz - 855.25 MHz and an FM band of
421 * * 87.5 MHz to 108.0 MHz.
423 * Thus, frequency range is limited to 87.5-108.0, but you can change
424 * it, using freq_min and freq_max options
426 static int init_frac_bsdbt848(radio_priv_t
* priv
){
428 priv
->rangelow
=priv
->radio_param
->freq_min
;
429 priv
->rangehigh
=priv
->radio_param
->freq_max
;
433 /*****************************************************************
434 * \brief tune card to given frequency
435 * \param frequency frequency in MHz
436 * \return STREAM_OK if success, STREAM_ERROR otherwise
438 static int set_frequency_bsdbt848(radio_priv_t
* priv
,float frequency
){
440 freq
=frequency
*priv
->frac
;
441 if(ioctl(priv
->radio_fd
,RADIO_SETFREQ
,&freq
)<0){
442 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl set frequency 0x%x (%.2f) failed: %s\n",freq
, frequency
, strerror(errno
));
448 /*****************************************************************
449 * \brief get current tuned frequency from card
450 * \param frequency where to store frequency in MHz
451 * \return STREAM_OK if success, STREAM_ERROR otherwise
453 static int get_frequency_bsdbt848(radio_priv_t
* priv
,float* frequency
){
455 if (ioctl(priv
->radio_fd
, RADIO_GETFREQ
, &freq
) < 0) {
456 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get frequency failed: %s\n",strerror(errno
));
459 *frequency
=((float)freq
)/priv
->frac
;
463 /*****************************************************************
464 * \brief set volume on radio card
465 * \param volume volume level (0..100)
466 * \return STREAM_OK if success, STREAM_ERROR otherwise
468 * *BSD BT848 does not have volume changing abilities, so
469 * we will just mute sound if volume=0 and unmute it otherwise.
471 static void set_volume_bsdbt848(radio_priv_t
* priv
,int volume
){
474 /*arg must be between 0 and 100*/
475 if (volume
> 100) volume
= 100;
476 if (volume
< 0) volume
= 0;
478 audio_flags
= (volume
==0?AUDIO_MUTE
:AUDIO_UNMUTE
);
479 if (ioctl(priv
->radio_fd
, BT848_SAUDIO
, &audio_flags
)<0){
480 mp_tmsg(MSGT_RADIO
,MSGL_WARN
,"[radio] ioctl set mute failed: %s\n",strerror(errno
));
484 /*****************************************************************
485 * \brief get current volume from radio card
486 * \param volume where to store volume level (0..100)
487 * \return previous STREAM_OK if success, STREAM_ERROR otherwise
489 * *BSD BT848 does not have volume changing abilities, so
490 * we will return 0 if sound is muted and 100 otherwise.
492 static int get_volume_bsdbt848(radio_priv_t
* priv
,int* volume
){
495 if (ioctl(priv
->radio_fd
, BT848_GAUDIO
, &audio_flags
)<0){
496 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] ioctl get volume failed: %s\n",strerror(errno
));
500 if (audio_flags
& AUDIO_MUTE
)
508 /* bsdbt848 driver info structure */
509 static const radio_driver_t radio_driver_bsdbt848
={
511 _("[radio] Using *BSD BT848 radio interface.\n"),
515 set_frequency_bsdbt848
,
516 get_frequency_bsdbt848
518 #endif /* CONFIG_RADIO_BSDBT848 */
520 static inline int init_frac(radio_priv_t
* priv
){
521 return priv
->driver
->init_frac(priv
);
523 static inline int set_frequency(radio_priv_t
* priv
,float frequency
){
524 if ((frequency
<priv
->rangelow
)||(frequency
>priv
->rangehigh
)){
525 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong frequency: %.2f\n",frequency
);
528 if(priv
->driver
->set_frequency(priv
,frequency
)!=STREAM_OK
)
531 #ifdef CONFIG_RADIO_CAPTURE
532 if(clear_buffer(priv
)!=STREAM_OK
){
533 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Clearing buffer failed: %s\n",strerror(errno
));
539 static inline int get_frequency(radio_priv_t
* priv
,float* frequency
){
540 return priv
->driver
->get_frequency(priv
,frequency
);
542 static inline void set_volume(radio_priv_t
* priv
,int volume
){
543 priv
->driver
->set_volume(priv
,volume
);
545 static inline int get_volume(radio_priv_t
* priv
,int* volume
){
546 return priv
->driver
->get_volume(priv
,volume
);
550 #ifndef CONFIG_RADIO_CAPTURE
551 /*****************************************************************
552 * \brief stub, if capture disabled at compile-time
555 static inline int init_audio(radio_priv_t
*priv
){ return STREAM_OK
;}
557 /*****************************************************************
558 * \brief making buffer empty
559 * \return STREAM_OK if success, STREAM_ERROR otherwise
561 * when changing channel we must clear buffer to avoid large switching delay
563 static int clear_buffer(radio_priv_t
* priv
){
564 if (!priv
->do_capture
) return STREAM_OK
;
565 priv
->audio_tail
= 0;
566 priv
->audio_head
= 0;
568 memset(priv
->audio_ringbuffer
,0,priv
->audio_in
.blocksize
);
571 /*****************************************************************
572 * \brief read next part of data into buffer
573 * \return -1 if error occured or no data available yet, otherwise - bytes read
574 * NOTE: audio device works in non-blocking mode
576 static int read_chunk(audio_in_t
*ai
, unsigned char *buffer
)
583 //device opened in non-blocking mode
584 ret
= snd_pcm_readi(ai
->alsa
.handle
, buffer
, ai
->alsa
.chunk_size
);
585 if (ret
!= ai
->alsa
.chunk_size
) {
587 if (ret
==-EAGAIN
) return -1;
588 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "\nError reading audio: %s\n", snd_strerror(ret
));
590 if (ai_alsa_xrun(ai
) == 0) {
591 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "Recovered from cross-run, some frames may be left out!\n");
593 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "Fatal error, cannot recover!\n");
597 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "\nNot enough audio samples!\n");
603 #ifdef CONFIG_OSS_AUDIO
608 we must return exactly blocksize bytes, so if we have got any bytes
609 at first call to read, we will loop untils get all blocksize bytes
610 otherwise we will return -1
612 while(bt
<ai
->blocksize
){
613 //device opened in non-blocking mode
614 ret
= read(ai
->oss
.audio_fd
, buffer
+bt
, ai
->blocksize
-bt
);
615 if (ret
==ai
->blocksize
) return ret
;
617 if (errno
==EAGAIN
&& bt
==0) return -1; //no data avail yet
618 if (errno
==EAGAIN
) { usleep(1000); continue;} //nilling buffer to blocksize size
619 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "\nError reading audio: %s\n", strerror(errno
));
631 /*****************************************************************
632 * \brief grab next frame from audio device
633 * \parameter buffer - store buffer
634 * \parameter len - store buffer size in bytes
635 * \return number of bytes written into buffer
637 * grabs len (or less) bytes from ringbuffer into buffer
638 * if ringbuffer is empty waits until len bytes of data will be available
640 * priv->audio_cnt - size (in bytes) of ringbuffer's filled part
641 * priv->audio_drop - size (in bytes) of dropped data (if no space in ringbuffer)
642 * priv->audio_head - index of first byte in filled part
643 * priv->audio_tail - index of last byte in filled part
645 * NOTE: audio_tail always aligned by priv->audio_in.blocksize
646 * audio_head may NOT.
648 static int grab_audio_frame(radio_priv_t
*priv
, char *buffer
, int len
)
651 mp_tmsg(MSGT_RADIO
, MSGL_DBG3
, "[radio] %s: in buffer=%d dropped=%d\n","grab_audio_frame",priv
->audio_cnt
,priv
->audio_drop
);
652 /* Cache buffer must be filled by some audio packets when playing starts.
653 Otherwise MPlayer will quit with EOF error.
654 Probably, there is need more carefull checking rather than simple 'for' loop
655 (something like timer or similar).
657 1000ms delay will happen only at first buffer filling. At next call function
658 just fills buffer until either buffer full or no data from driver available.
660 for (i
=0;i
<1000 && !priv
->audio_cnt
; i
++){
661 //read_chunk fills exact priv->blocksize bytes
662 if(read_chunk(&priv
->audio_in
, priv
->audio_ringbuffer
+priv
->audio_tail
) < 0){
663 //sleppeing only when waiting first block to fill empty buffer
664 if (!priv
->audio_cnt
){
670 priv
->audio_cnt
+=priv
->audio_in
.blocksize
;
671 priv
->audio_tail
= (priv
->audio_tail
+priv
->audio_in
.blocksize
) % priv
->audio_buffer_size
;
673 if(priv
->audio_cnt
<len
)
675 memcpy(buffer
, priv
->audio_ringbuffer
+priv
->audio_head
,len
);
676 priv
->audio_head
= (priv
->audio_head
+len
) % priv
->audio_buffer_size
;
677 priv
->audio_cnt
-=len
;
680 /*****************************************************************
681 * \brief init audio device
682 * \return STREAM_OK if success, STREAM_ERROR otherwise
684 static int init_audio(radio_priv_t
*priv
)
689 if (priv
->audio_initialized
) return 1;
691 /* do_capture==0 mplayer was not started with capture keyword, so disabling capture*/
692 if(!priv
->do_capture
)
695 if (!priv
->radio_param
->adevice
){
701 mp_tmsg(MSGT_RADIO
,MSGL_V
,"[radio] Starting capture stuff.\n");
703 while ((tmp
= strrchr(priv
->radio_param
->adevice
, '='))){
705 //adevice option looks like ALSA device name. Switching to ALSA
708 while ((tmp
= strrchr(priv
->radio_param
->adevice
, '.')))
712 if(audio_in_init(&priv
->audio_in
, is_oss
?AUDIO_IN_OSS
:AUDIO_IN_ALSA
)<0){
713 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] audio_in_init failed.\n");
716 audio_in_set_device(&priv
->audio_in
, priv
->radio_param
->adevice
);
717 audio_in_set_channels(&priv
->audio_in
, priv
->radio_param
->achannels
);
718 audio_in_set_samplerate(&priv
->audio_in
, priv
->radio_param
->arate
);
720 if (audio_in_setup(&priv
->audio_in
) < 0) {
721 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] audio_in_setup call failed: %s\n", strerror(errno
));
724 #ifdef CONFIG_OSS_AUDIO
726 ioctl(priv
->audio_in
.oss
.audio_fd
, SNDCTL_DSP_NONBLOCK
, 0);
730 snd_pcm_nonblock(priv
->audio_in
.alsa
.handle
,1);
733 priv
->audio_buffer_size
= seconds
*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
734 priv
->audio_in
.bytes_per_sample
+priv
->audio_in
.blocksize
;
735 if (priv
->audio_buffer_size
< 256*priv
->audio_in
.blocksize
)
736 priv
->audio_buffer_size
= 256*priv
->audio_in
.blocksize
;
737 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Audio capture - buffer=%d bytes (block=%d bytes).\n",
738 priv
->audio_buffer_size
,priv
->audio_in
.blocksize
);
740 priv
->audio_ringbuffer
= calloc(1, priv
->audio_buffer_size
);
741 if (!priv
->audio_ringbuffer
) {
742 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
));
745 priv
->audio_head
= 0;
746 priv
->audio_tail
= 0;
748 priv
->audio_drop
= 0;
750 audio_in_start_capture(&priv
->audio_in
);
752 priv
->audio_initialized
= 1;
756 #endif /* CONFIG_RADIO_CAPTURE */
758 /*-------------------------------------------------------------------------
759 for call from mplayer.c
760 --------------------------------------------------------------------------*/
761 /*****************************************************************
762 * \brief public wrapper for get_frequency
763 * \parameter frequency pointer to float, which will contain frequency in MHz
764 * \return 1 if success,0 - otherwise
766 int radio_get_freq(struct stream
*stream
, float *frequency
){
767 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
771 if (get_frequency(priv
,frequency
)!=STREAM_OK
){
776 /*****************************************************************
777 * \brief public wrapper for set_frequency
778 * \parameter frequency frequency in MHz
779 * \return 1 if success,0 - otherwise
781 int radio_set_freq(struct stream
*stream
, float frequency
){
782 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
784 if (set_frequency(priv
,frequency
)!=STREAM_OK
){
787 if (get_frequency(priv
,&frequency
)!=STREAM_OK
){
790 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Current frequency: %.2f\n",frequency
);
794 /*****************************************************************
795 * \brief tune current frequency by step_interval value
796 * \parameter step_interval increment value
797 * \return 1 if success,0 - otherwise
800 int radio_step_freq(struct stream
*stream
, float step_interval
){
802 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
804 if (get_frequency(priv
,&frequency
)!=STREAM_OK
)
807 frequency
+=step_interval
;
808 if (frequency
>priv
->rangehigh
)
809 frequency
=priv
->rangehigh
;
810 if (frequency
<priv
->rangelow
)
811 frequency
=priv
->rangelow
;
813 return radio_set_freq(stream
,frequency
);
815 /*****************************************************************
816 * \brief step channel up or down
817 * \parameter direction RADIO_CHANNEL_LOWER - go to prev channel,RADIO_CHANNEL_HIGHER - to next
818 * \return 1 if success,0 - otherwise
820 * if channel parameter is NULL function prints error message and does nothing, otherwise
821 * changes channel to prev or next in list
823 int radio_step_channel(struct stream
*stream
, int direction
) {
824 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
826 if (priv
->radio_channel_list
) {
828 case RADIO_CHANNEL_HIGHER
:
829 if (priv
->radio_channel_current
->next
)
830 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
832 priv
->radio_channel_current
= priv
->radio_channel_list
;
833 if(!radio_set_freq(stream
,priv
->radio_channel_current
->freq
))
835 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Selected channel: %d - %s (freq: %.2f)\n",
836 priv
->radio_channel_current
->index
, priv
->radio_channel_current
->name
,
837 priv
->radio_channel_current
->freq
);
839 case RADIO_CHANNEL_LOWER
:
840 if (priv
->radio_channel_current
->prev
)
841 priv
->radio_channel_current
= priv
->radio_channel_current
->prev
;
843 while (priv
->radio_channel_current
->next
)
844 priv
->radio_channel_current
= priv
->radio_channel_current
->next
;
845 if(!radio_set_freq(stream
,priv
->radio_channel_current
->freq
))
847 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Selected channel: %d - %s (freq: %.2f)\n",
848 priv
->radio_channel_current
->index
, priv
->radio_channel_current
->name
,
849 priv
->radio_channel_current
->freq
);
853 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Can not change channel: no channel list given.\n");
857 /*****************************************************************
858 * \brief change channel to one with given index
859 * \parameter channel string, containing channel number
860 * \return 1 if success,0 - otherwise
862 * if channel parameter is NULL function prints error message and does nothing, otherwise
863 * changes channel to given
865 int radio_set_channel(struct stream
*stream
, char *channel
) {
866 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
868 radio_channels_t
* tmp
;
872 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong channel name: %s\n",channel
);
874 if (priv
->radio_channel_list
) {
875 channel_int
= strtol(channel
,&endptr
,10);
876 tmp
= priv
->radio_channel_list
;
878 //channel is not a number, so it contains channel name
879 for ( ; tmp
; tmp
=tmp
->next
)
880 if (!strncmp(channel
,tmp
->name
,sizeof(tmp
->name
)-1))
883 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong channel name: %s\n",channel
);
887 for (i
= 1; i
< channel_int
; i
++)
892 if (tmp
->index
!=channel_int
){
893 mp_tmsg(MSGT_RADIO
,MSGL_ERR
,"[radio] Wrong channel number: %d\n",channel_int
);
897 priv
->radio_channel_current
=tmp
;
898 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Selected channel: %d - %s (freq: %.2f)\n", priv
->radio_channel_current
->index
,
899 priv
->radio_channel_current
->name
, priv
->radio_channel_current
->freq
);
900 if(!radio_set_freq(stream
, priv
->radio_channel_current
->freq
))
903 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Can not change channel: no channel list given.\n");
907 /*****************************************************************
908 * \brief get current channel's name
909 * \return pointer to string, containing current channel's name
911 * NOTE: return value may be NULL (e.g. when channel list not initialized)
913 char* radio_get_channel_name(struct stream
*stream
){
914 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
915 if (priv
->radio_channel_current
) {
916 return priv
->radio_channel_current
->name
;
921 /*****************************************************************
922 * \brief fills given buffer with audio data
923 * \return number of bytes, written into buffer
925 static int fill_buffer_s(struct stream
*s
, char *buffer
, int max_len
){
928 #ifdef CONFIG_RADIO_CAPTURE
929 radio_priv_t
* priv
=(radio_priv_t
*)s
->priv
;
931 if (priv
->do_capture
){
932 len
=grab_audio_frame(priv
, buffer
,max_len
);
936 memset(buffer
,0,len
);
942 order if significant!
943 when no driver explicitly specified first available will be used
945 static const radio_driver_t
* radio_drivers
[]={
946 #ifdef CONFIG_RADIO_BSDBT848
947 &radio_driver_bsdbt848
,
949 #ifdef CONFIG_RADIO_V4L2
955 /*****************************************************************
956 * Stream initialization
957 * \return STREAM_OK if success, STREAM_ERROR otherwise
959 static int open_s(stream_t
*stream
,int mode
, void* opts
, int* file_format
) {
964 if (strncmp("radio://",stream
->url
,8) != 0)
965 return STREAM_UNSUPPORTED
;
967 if(mode
!= STREAM_READ
)
968 return STREAM_UNSUPPORTED
;
970 priv
=calloc(1,sizeof(radio_priv_t
));
976 priv
->radio_param
=opts
;
978 #ifdef CONFIG_RADIO_CAPTURE
979 if (priv
->radio_param
->capture
&& strncmp("capture",priv
->radio_param
->capture
,7)==0)
987 if (strncmp(priv
->radio_param
->driver
,"default",7)==0)
988 priv
->driver
=radio_drivers
[0];
992 mp_tmsg(MSGT_RADIO
,MSGL_V
,"[radio] Available drivers: ");
993 for(i
=0;radio_drivers
[i
];i
++){
994 mp_msg(MSGT_RADIO
,MSGL_V
,"%s, ",radio_drivers
[i
]->name
);
995 if(strcmp(priv
->radio_param
->driver
,radio_drivers
[i
]->name
)==0)
996 priv
->driver
=radio_drivers
[i
];
998 mp_msg(MSGT_RADIO
,MSGL_V
,"\n");
1001 mp_msg(MSGT_RADIO
, MSGL_INFO
, priv
->driver
->info
);
1003 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Unknown driver name: %s\n",priv
->radio_param
->driver
);
1005 return STREAM_ERROR
;
1008 stream
->type
= STREAMTYPE_RADIO
;
1009 /* using rawaudio demuxer */
1010 *file_format
= DEMUXER_TYPE_RAWAUDIO
;
1011 stream
->flags
= STREAM_READ
;
1015 stream
->start_pos
=0;
1018 stream
->close
=close_s
;
1019 stream
->fill_buffer
=fill_buffer_s
;
1021 priv
->radio_fd
= open(priv
->radio_param
->device
, O_RDONLY
);
1022 if (priv
->radio_fd
< 0) {
1023 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Unable to open '%s': %s\n",
1024 priv
->radio_param
->device
, strerror(errno
));
1026 return STREAM_ERROR
;
1028 mp_tmsg(MSGT_RADIO
, MSGL_V
, "[radio] Radio fd: %d, %s\n", priv
->radio_fd
,priv
->radio_param
->device
);
1029 fcntl(priv
->radio_fd
, F_SETFD
, FD_CLOEXEC
);
1031 get_volume(priv
, &priv
->old_snd_volume
);
1034 if (init_frac(priv
)!=STREAM_OK
){
1036 return STREAM_ERROR
;
1039 if (parse_channels(priv
,priv
->radio_param
->freq_channel
,&frequency
)!=STREAM_OK
){
1041 return STREAM_ERROR
;
1044 if ((frequency
<priv
->rangelow
)||(frequency
>priv
->rangehigh
)){
1045 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Wrong frequency: %.2f\n",frequency
);
1047 return STREAM_ERROR
;
1049 mp_tmsg(MSGT_RADIO
, MSGL_INFO
, "[radio] Using frequency: %.2f.\n",frequency
);
1051 if(set_frequency(priv
,frequency
)!=STREAM_OK
){
1053 return STREAM_ERROR
;
1057 if (init_audio(priv
)!=STREAM_OK
){
1059 return STREAM_ERROR
;
1062 #if defined(CONFIG_RADIO_CAPTURE) && defined(CONFIG_STREAM_CACHE)
1063 if(priv
->do_capture
){
1065 if(!stream_enable_cache(stream
,5*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
1066 priv
->audio_in
.bytes_per_sample
,2*priv
->audio_in
.samplerate
*priv
->audio_in
.channels
*
1067 priv
->audio_in
.bytes_per_sample
,priv
->audio_in
.blocksize
)) {
1068 mp_tmsg(MSGT_RADIO
, MSGL_ERR
, "[radio] Call to stream_enable_cache failed: %s\n",strerror(errno
));
1070 return STREAM_ERROR
;
1075 set_volume(priv
,priv
->radio_param
->volume
);
1080 /*****************************************************************
1081 * Close stream. Clear structures.
1083 static void close_s(struct stream
*stream
){
1084 radio_priv_t
* priv
=(radio_priv_t
*)stream
->priv
;
1085 radio_channels_t
* tmp
;
1088 #ifdef CONFIG_RADIO_CAPTURE
1089 free(priv
->audio_ringbuffer
);
1090 priv
->audio_ringbuffer
= NULL
;
1095 while (priv
->radio_channel_list
) {
1096 tmp
=priv
->radio_channel_list
;
1097 priv
->radio_channel_list
=priv
->radio_channel_list
->next
;
1100 priv
->radio_channel_current
=NULL
;
1101 priv
->radio_channel_list
=NULL
;
1103 if (priv
->radio_fd
>0){
1104 set_volume(priv
, priv
->old_snd_volume
);
1105 close(priv
->radio_fd
);
1108 if(priv
->radio_param
)
1109 m_struct_free(&stream_opts
,priv
->radio_param
);
1114 const stream_info_t stream_info_radio
= {
1117 "Vladimir Voroshilov",
1122 1 // Urls are an option string