From 132f395aacb2c658e91b8845076115f98158edce Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 13 Apr 2014 18:51:43 +0200 Subject: Remove radio:// It was disabled by default, works only for analogue radio, and I bet nobody uses it. --- stream/stream.c | 4 - stream/stream_radio.c | 977 -------------------------------------------------- stream/stream_radio.h | 59 --- 3 files changed, 1040 deletions(-) delete mode 100644 stream/stream_radio.c delete mode 100644 stream/stream_radio.h (limited to 'stream') diff --git a/stream/stream.c b/stream/stream.c index a7990595d2..99e871d5a0 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -64,7 +64,6 @@ extern const stream_info_t stream_info_vcd; extern const stream_info_t stream_info_cdda; extern const stream_info_t stream_info_dvb; extern const stream_info_t stream_info_tv; -extern const stream_info_t stream_info_radio; extern const stream_info_t stream_info_pvr; extern const stream_info_t stream_info_smb; extern const stream_info_t stream_info_null; @@ -97,9 +96,6 @@ static const stream_info_t *const stream_list[] = { #if HAVE_TV &stream_info_tv, #endif -#if HAVE_RADIO - &stream_info_radio, -#endif #if HAVE_PVR &stream_info_pvr, #endif diff --git a/stream/stream_radio.c b/stream/stream_radio.c deleted file mode 100644 index 4dc60ae112..0000000000 --- a/stream/stream_radio.c +++ /dev/null @@ -1,977 +0,0 @@ -/* - * radio support - * - * Abilities: - * * Listening v4l compatible radio cards using line-in or - * similar cable - * * Grabbing audio data using -ao pcm or -dumpaudio - * (must be compiled with --enable-radio-capture). - * - * Initially written by Vladimir Voroshilov . - * Based on tv.c and tvi_v4l2.c code. - * - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#if HAVE_RADIO_V4L2 -#include -#endif - -#include - -#include "stream.h" -#include "options/m_option.h" -#include "common/msg.h" -#include "stream_radio.h" - -#include "osdep/io.h" - -#if HAVE_RADIO_CAPTURE -#include "audio_in.h" - -#if HAVE_SYS_SOUNDCARD_H -#include -#else -#if HAVE_SOUNDCARD_H -#include -#else -#include -#endif -#endif - -#endif - -#define _(x) (x) - -typedef struct radio_channels_s { - int index; ///< channel index in channels list - float freq; ///< frequency in MHz - char name[20]; ///< channel name - struct radio_channels_s * next; - struct radio_channels_s * prev; -} radio_channels_t; - -/// default values for options -radio_param_t stream_radio_defaults={ - "/dev/radio0", //device; - "default", //driver - NULL, //channels - 100, //volume - NULL, //adevice - 44100, //arate - 2, //achannels - 0, //freq_channel - NULL, //capture -}; - -typedef struct radio_priv_s { - struct mp_log *log; - int radio_fd; ///< radio device descriptor - int frac; ///< fraction value (see comment to init_frac) - radio_channels_t* radio_channel_list; - radio_channels_t* radio_channel_current; - float rangelow; ///< lowest tunable frequency in MHz - float rangehigh; ///< highest tunable frequency in MHz - const struct radio_driver_s* driver; - int old_snd_volume; -#if HAVE_RADIO_CAPTURE - volatile int do_capture; ///< is capture enabled - audio_in_t audio_in; - unsigned char* audio_ringbuffer; - int audio_head; ///< start of meanfull data in ringbuffer - int audio_tail; ///< end of meanfull data in ringbuffer - int audio_buffer_size; ///< size of ringbuffer - int audio_cnt; ///< size of meanfull data inringbuffer - int audio_drop; ///< number of dropped bytes - int audio_initialized; -#endif - radio_param_t *radio_param; -} radio_priv_t; - -typedef struct radio_driver_s { - char* name; - char* info; - int (*init_frac)(radio_priv_t* priv); - void (*set_volume)(radio_priv_t* priv,int volume); - int (*get_volume)(radio_priv_t* priv,int* volume); - int (*set_frequency)(radio_priv_t* priv,float frequency); - int (*get_frequency)(radio_priv_t* priv,float* frequency); -} radio_driver_t; - -#define OPT_BASE_STRUCT radio_param_t -static const m_option_t stream_opts_fields[] = { - OPT_FLOAT("title", freq_channel, 0), - OPT_STRING("capture", capture, 0), - {0} -}; - -static void close_s(struct stream *stream); -#if HAVE_RADIO_CAPTURE -static int clear_buffer(radio_priv_t* priv); -#endif - - -/***************************************************************** - * \brief parse channels parameter and store result into list - * \param freq_channel if channels!=NULL this mean channel number, otherwise - frequency - * \param pfreq selected frequency (from selected channel or from URL) - * \result STREAM_OK if success, STREAM_ERROR otherwise - * - * channels option must be in the following format - * -,-,... - * - * '_' will be replaced with spaces. - * - * If channels option is not null, number in movie URL will be treated as - * channel position in channel list. - */ -static int parse_channels(radio_priv_t* priv,float freq_channel,float* pfreq){ - char** channels; - int i; - int channel = 0; - if (priv->radio_param->channels){ - /*parsing channels string*/ - channels=priv->radio_param->channels; - - MP_INFO(priv, "Radio channel names detected.\n"); - priv->radio_channel_list = malloc(sizeof(radio_channels_t)); - priv->radio_channel_list->index=1; - priv->radio_channel_list->next=NULL; - priv->radio_channel_list->prev=NULL; - priv->radio_channel_current = priv->radio_channel_list; - - while (*channels) { - char* tmp = *(channels++); - char* sep = strchr(tmp,'-'); - if (!sep) continue; // Wrong syntax, but mplayer should not crash - av_strlcpy(priv->radio_channel_current->name, sep + 1,sizeof(priv->radio_channel_current->name)-1); - - sep[0] = '\0'; - - priv->radio_channel_current->freq=atof(tmp); - - if ((priv->radio_channel_current->freq>priv->rangehigh)||(priv->radio_channel_current->freqrangelow)) - MP_ERR(priv, "Wrong frequency for channel %s\n", - priv->radio_channel_current->name); - - while ((sep=strchr(priv->radio_channel_current->name, '_'))) sep[0] = ' '; - - priv->radio_channel_current->next = malloc(sizeof(radio_channels_t)); - priv->radio_channel_current->next->index = priv->radio_channel_current->index + 1; - priv->radio_channel_current->next->prev = priv->radio_channel_current; - priv->radio_channel_current->next->next = NULL; - priv->radio_channel_current = priv->radio_channel_current->next; - } - if (priv->radio_channel_current->prev) - priv->radio_channel_current->prev->next = NULL; - free(priv->radio_channel_current); - - if (freq_channel) - channel = freq_channel; - else - channel = 1; - - priv->radio_channel_current = priv->radio_channel_list; - for (i = 1; i < channel; i++) - if (priv->radio_channel_current->next) - priv->radio_channel_current = priv->radio_channel_current->next; - if (priv->radio_channel_current->index!=channel){ - if (((float)((int)freq_channel))!=freq_channel) - MP_ERR(priv, "Wrong channel number: %.2f\n",freq_channel); - else - MP_ERR(priv, "Wrong channel number: %d\n",(int)freq_channel); - return STREAM_ERROR; - } - MP_INFO(priv, "Selected channel: %d - %s (freq: %.2f)\n", priv->radio_channel_current->index, - priv->radio_channel_current->name, priv->radio_channel_current->freq); - *pfreq=priv->radio_channel_current->freq; - }else{ - if (freq_channel){ - MP_INFO(priv, "Radio frequency parameter detected.\n"); - priv->radio_channel_list=malloc(sizeof(radio_channels_t)); - priv->radio_channel_list->next=NULL; - priv->radio_channel_list->prev=NULL; - priv->radio_channel_list->index=1; - snprintf(priv->radio_channel_list->name,sizeof(priv->radio_channel_current->name)-1,"Freq: %.2f",freq_channel); - - priv->radio_channel_current=priv->radio_channel_list; - *pfreq=freq_channel; - } - } - MP_DBG(priv, "Done parsing channels.\n"); - return STREAM_OK; -} - -#if HAVE_RADIO_V4L2 -/***************************************************************** - * \brief get fraction value for using in set_frequency and get_frequency - * \return STREAM_OK if success, STREAM_ERROR otherwise - * - * V4L2_TUNER_CAP_LOW: - * unit=62.5Hz - * frac= 1MHz/unit=1000000/62.5 =16000 - * - * otherwise: - * unit=62500Hz - * frac= 1MHz/unit=1000000/62500 =16 - */ -static int init_frac_v4l2(radio_priv_t* priv){ - struct v4l2_tuner tuner; - - memset(&tuner,0,sizeof(tuner)); - tuner.index=0; - if (ioctl(priv->radio_fd, VIDIOC_G_TUNER, &tuner)<0){ - MP_WARN(priv, "Warning: ioctl get tuner failed: %s. Setting frac to %d.\n",strerror(errno),priv->frac); - return STREAM_ERROR; - } - if(tuner.type!=V4L2_TUNER_RADIO){ - MP_ERR(priv, "%s is no radio device!\n",priv->radio_param->device); - return STREAM_ERROR; - } - if(tuner.capability & V4L2_TUNER_CAP_LOW){ - priv->frac=16000; - MP_DBG(priv, "tuner is low:yes frac=%d\n",priv->frac); - } - else{ - priv->frac=16; - MP_DBG(priv, "tuner is low:no frac=%d\n",priv->frac); - } - - priv->rangelow=((float)tuner.rangelow)/priv->frac; - priv->rangehigh=((float)tuner.rangehigh)/priv->frac; - MP_VERBOSE(priv, "Allowed frequency range is %.2f-%.2f MHz.\n",priv->rangelow,priv->rangehigh); - return STREAM_OK; -} - -/***************************************************************** - * \brief tune card to given frequency - * \param frequency frequency in MHz - * \return STREAM_OK if success, STREAM_ERROR otherwise - */ -static int set_frequency_v4l2(radio_priv_t* priv,float frequency){ - struct v4l2_frequency freq; - - memset(&freq,0,sizeof(freq)); - freq.tuner=0; - freq.type=V4L2_TUNER_RADIO; - freq.frequency=frequency*priv->frac; - if(ioctl(priv->radio_fd,VIDIOC_S_FREQUENCY,&freq)<0){ - MP_ERR(priv, "ioctl set frequency 0x%x (%.2f) failed: %s\n",freq.frequency, - frequency,strerror(errno)); - return STREAM_ERROR; - } - return STREAM_OK; -} - -/***************************************************************** - * \brief get current tuned frequency from card - * \param frequency where to store frequency in MHz - * \return STREAM_OK if success, STREAM_ERROR otherwise - */ -static int get_frequency_v4l2(radio_priv_t* priv,float* frequency){ - struct v4l2_frequency freq; - memset(&freq,0,sizeof(freq)); - if (ioctl(priv->radio_fd, VIDIOC_G_FREQUENCY, &freq) < 0) { - MP_ERR(priv, "ioctl get frequency failed: %s\n",strerror(errno)); - return STREAM_ERROR; - } - *frequency=((float)freq.frequency)/priv->frac; - return STREAM_OK; -} - -/***************************************************************** - * \brief set volume on radio card - * \param volume volume level (0..100) - * \return STREAM_OK if success, STREAM_ERROR otherwise - */ -static void set_volume_v4l2(radio_priv_t* priv,int volume){ - struct v4l2_queryctrl qctrl; - struct v4l2_control control; - - /*arg must be between 0 and 100*/ - if (volume > 100) volume = 100; - if (volume < 0) volume = 0; - - memset(&control,0,sizeof(control)); - control.id=V4L2_CID_AUDIO_MUTE; - control.value = (volume==0?1:0); - if (ioctl(priv->radio_fd, VIDIOC_S_CTRL, &control)<0){ - MP_WARN(priv, "ioctl set mute failed: %s\n",strerror(errno)); - } - - memset(&qctrl,0,sizeof(qctrl)); - qctrl.id = V4L2_CID_AUDIO_VOLUME; - if (ioctl(priv->radio_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) { - MP_WARN(priv, "ioctl query control failed: %s\n",strerror(errno)); - return; - } - - memset(&control,0,sizeof(control)); - control.id=V4L2_CID_AUDIO_VOLUME; - control.value=qctrl.minimum+volume*(qctrl.maximum-qctrl.minimum)/100; - if (ioctl(priv->radio_fd, VIDIOC_S_CTRL, &control) < 0) { - MP_WARN(priv, "ioctl set volume failed: %s\n",strerror(errno)); - } -} - -/***************************************************************** - * \brief get current volume from radio card - * \param volume where to store volume level (0..100) - * \return STREAM_OK if success, STREAM_ERROR otherwise - */ -static int get_volume_v4l2(radio_priv_t* priv,int* volume){ - struct v4l2_queryctrl qctrl; - struct v4l2_control control; - - memset(&qctrl,0,sizeof(qctrl)); - qctrl.id = V4L2_CID_AUDIO_VOLUME; - if (ioctl(priv->radio_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) { - MP_ERR(priv, "ioctl query control failed: %s\n",strerror(errno)); - return STREAM_ERROR; - } - - memset(&control,0,sizeof(control)); - control.id=V4L2_CID_AUDIO_VOLUME; - if (ioctl(priv->radio_fd, VIDIOC_G_CTRL, &control) < 0) { - MP_ERR(priv, "ioctl get volume failed: %s\n",strerror(errno)); - return STREAM_ERROR; - } - - if (qctrl.maximum==qctrl.minimum) - *volume=qctrl.minimum; - else - *volume=100*(control.value-qctrl.minimum)/(qctrl.maximum-qctrl.minimum); - - /*arg must be between 0 and 100*/ - if (*volume > 100) *volume = 100; - if (*volume < 0) *volume = 0; - - return STREAM_OK; -} - -/* v4l2 driver info structure */ -static const radio_driver_t radio_driver_v4l2={ - "v4l2", - _("Using V4Lv2 radio interface.\n"), - init_frac_v4l2, - set_volume_v4l2, - get_volume_v4l2, - set_frequency_v4l2, - get_frequency_v4l2 -}; -#endif /* HAVE_RADIO_V4L2 */ - -static inline int init_frac(radio_priv_t* priv){ - return priv->driver->init_frac(priv); -} -static inline int set_frequency(radio_priv_t* priv,float frequency){ - if ((frequencyrangelow)||(frequency>priv->rangehigh)){ - MP_ERR(priv, "Wrong frequency: %.2f\n",frequency); - return STREAM_ERROR; - } - if(priv->driver->set_frequency(priv,frequency)!=STREAM_OK) - return STREAM_ERROR; - -#if HAVE_RADIO_CAPTURE - if(clear_buffer(priv)!=STREAM_OK){ - MP_ERR(priv, "Clearing buffer failed: %s\n",strerror(errno)); - return STREAM_ERROR; - } -#endif - return STREAM_OK; -} -static inline int get_frequency(radio_priv_t* priv,float* frequency){ - return priv->driver->get_frequency(priv,frequency); -} -static inline void set_volume(radio_priv_t* priv,int volume){ - priv->driver->set_volume(priv,volume); -} -static inline int get_volume(radio_priv_t* priv,int* volume){ - return priv->driver->get_volume(priv,volume); -} - - -#if !HAVE_RADIO_CAPTURE -/***************************************************************** - * \brief stub, if capture disabled at compile-time - * \return STREAM_OK - */ -static inline int init_audio(radio_priv_t *priv){ return STREAM_OK;} -#else -/***************************************************************** - * \brief making buffer empty - * \return STREAM_OK if success, STREAM_ERROR otherwise - * - * when changing channel we must clear buffer to avoid large switching delay - */ -static int clear_buffer(radio_priv_t* priv){ - if (!priv->do_capture) return STREAM_OK; - priv->audio_tail = 0; - priv->audio_head = 0; - priv->audio_cnt=0; - memset(priv->audio_ringbuffer,0,priv->audio_in.blocksize); - return STREAM_OK; -} -/***************************************************************** - * \brief read next part of data into buffer - * \return -1 if error occured or no data available yet, otherwise - bytes read - * NOTE: audio device works in non-blocking mode - */ -static int read_chunk(audio_in_t *ai, unsigned char *buffer) -{ - int ret; - - switch (ai->type) { -#if HAVE_ALSA - case AUDIO_IN_ALSA: - //device opened in non-blocking mode - ret = snd_pcm_readi(ai->alsa.handle, buffer, ai->alsa.chunk_size); - if (ret != ai->alsa.chunk_size) { - if (ret < 0) { - if (ret==-EAGAIN) return -1; - MP_ERR(ai, "\nError reading audio: %s\n", snd_strerror(ret)); - if (ret == -EPIPE) { - if (ai_alsa_xrun(ai) == 0) { - MP_ERR(ai, "Recovered from cross-run, some frames may be left out!\n"); - } else { - MP_ERR(ai, "Fatal error, cannot recover!\n"); - } - } - } else { - MP_ERR(ai, "\nNot enough audio samples!\n"); - } - return -1; - } - return ret; -#endif -#if HAVE_OSS_AUDIO - case AUDIO_IN_OSS: - { - int bt=0; - /* - we must return exactly blocksize bytes, so if we have got any bytes - at first call to read, we will loop untils get all blocksize bytes - otherwise we will return -1 - */ - while(btblocksize){ - //device opened in non-blocking mode - ret = read(ai->oss.audio_fd, buffer+bt, ai->blocksize-bt); - if (ret==ai->blocksize) return ret; - if (ret<0){ - if (errno==EAGAIN && bt==0) return -1; //no data avail yet - if (errno==EAGAIN) { usleep(1000); continue;} //nilling buffer to blocksize size - MP_ERR(ai, "\nError reading audio: %s\n", strerror(errno)); - return -1; - } - bt+=ret; - } - return bt; - } -#endif - default: - return -1; - } -} -/***************************************************************** - * \brief grab next frame from audio device - * \parameter buffer - store buffer - * \parameter len - store buffer size in bytes - * \return number of bytes written into buffer - * - * grabs len (or less) bytes from ringbuffer into buffer - * if ringbuffer is empty waits until len bytes of data will be available - * - * priv->audio_cnt - size (in bytes) of ringbuffer's filled part - * priv->audio_drop - size (in bytes) of dropped data (if no space in ringbuffer) - * priv->audio_head - index of first byte in filled part - * priv->audio_tail - index of last byte in filled part - * - * NOTE: audio_tail always aligned by priv->audio_in.blocksize - * audio_head may NOT. - */ -static int grab_audio_frame(radio_priv_t *priv, char *buffer, int len) -{ - int i; - MP_TRACE(priv, "%s: in buffer=%d dropped=%d\n","grab_audio_frame",priv->audio_cnt,priv->audio_drop); - /* Cache buffer must be filled by some audio packets when playing starts. - Otherwise MPlayer will quit with EOF error. - Probably, there is need more carefull checking rather than simple 'for' loop - (something like timer or similar). - - 1000ms delay will happen only at first buffer filling. At next call function - just fills buffer until either buffer full or no data from driver available. - */ - for (i=0;i<1000 && !priv->audio_cnt; i++){ - //read_chunk fills exact priv->blocksize bytes - if(read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail) < 0){ - //sleppeing only when waiting first block to fill empty buffer - if (!priv->audio_cnt){ - usleep(1000); - continue; - }else - break; - } - priv->audio_cnt+=priv->audio_in.blocksize; - priv->audio_tail = (priv->audio_tail+priv->audio_in.blocksize) % priv->audio_buffer_size; - } - if(priv->audio_cntaudio_cnt; - memcpy(buffer, priv->audio_ringbuffer+priv->audio_head,len); - priv->audio_head = (priv->audio_head+len) % priv->audio_buffer_size; - priv->audio_cnt-=len; - return len; -} -/***************************************************************** - * \brief init audio device - * \return STREAM_OK if success, STREAM_ERROR otherwise - */ -static int init_audio(radio_priv_t *priv) -{ - int is_oss=1; - int seconds=2; - char* tmp; - if (priv->audio_initialized) return 1; - - /* do_capture==0 mplayer was not started with capture keyword, so disabling capture*/ - if(!priv->do_capture) - return STREAM_OK; - - if (!priv->radio_param->adevice){ - priv->do_capture=0; - return STREAM_OK; - } - - priv->do_capture=1; - MP_VERBOSE(priv, "Starting capture stuff.\n"); -#if HAVE_ALSA - while ((tmp = strrchr(priv->radio_param->adevice, '='))){ - tmp[0] = ':'; - //adevice option looks like ALSA device name. Switching to ALSA - is_oss=0; - } - while ((tmp = strrchr(priv->radio_param->adevice, '.'))) - tmp[0] = ','; -#endif - - if(audio_in_init(&priv->audio_in, priv->log, is_oss?AUDIO_IN_OSS:AUDIO_IN_ALSA)<0){ - MP_ERR(priv, "audio_in_init failed.\n"); - } - - audio_in_set_device(&priv->audio_in, priv->radio_param->adevice); - audio_in_set_channels(&priv->audio_in, priv->radio_param->achannels); - audio_in_set_samplerate(&priv->audio_in, priv->radio_param->arate); - - if (audio_in_setup(&priv->audio_in) < 0) { - MP_ERR(priv, "audio_in_setup call failed: %s\n", strerror(errno)); - return STREAM_ERROR; - } -#if HAVE_OSS_AUDIO - if(is_oss) - ioctl(priv->audio_in.oss.audio_fd, SNDCTL_DSP_NONBLOCK, 0); -#endif -#if HAVE_ALSA - if(!is_oss) - snd_pcm_nonblock(priv->audio_in.alsa.handle,1); -#endif - - priv->audio_buffer_size = seconds*priv->audio_in.samplerate*priv->audio_in.channels* - priv->audio_in.bytes_per_sample+priv->audio_in.blocksize; - if (priv->audio_buffer_size < 256*priv->audio_in.blocksize) - priv->audio_buffer_size = 256*priv->audio_in.blocksize; - MP_VERBOSE(priv, "Audio capture - buffer=%d bytes (block=%d bytes).\n", - priv->audio_buffer_size,priv->audio_in.blocksize); - /* start capture */ - priv->audio_ringbuffer = calloc(1, priv->audio_buffer_size); - if (!priv->audio_ringbuffer) { - MP_ERR(priv, "cannot allocate audio buffer (block=%d,buf=%d): %s\n",priv->audio_in.blocksize, priv->audio_buffer_size, strerror(errno)); - return STREAM_ERROR; - } - priv->audio_head = 0; - priv->audio_tail = 0; - priv->audio_cnt = 0; - priv->audio_drop = 0; - - audio_in_start_capture(&priv->audio_in); - - priv->audio_initialized = 1; - - return STREAM_OK; -} -#endif /* HAVE_RADIO_CAPTURE */ - -/*------------------------------------------------------------------------- - for call from mplayer.c ---------------------------------------------------------------------------*/ -/***************************************************************** - * \brief public wrapper for get_frequency - * \parameter frequency pointer to float, which will contain frequency in MHz - * \return 1 if success,0 - otherwise - */ -int radio_get_freq(struct stream *stream, float *frequency){ - radio_priv_t* priv=(radio_priv_t*)stream->priv; - - if (!frequency) - return 0; - if (get_frequency(priv,frequency)!=STREAM_OK){ - return 0; - } - return 1; -} -/***************************************************************** - * \brief public wrapper for set_frequency - * \parameter frequency frequency in MHz - * \return 1 if success,0 - otherwise - */ -int radio_set_freq(struct stream *stream, float frequency){ - radio_priv_t* priv=(radio_priv_t*)stream->priv; - - if (set_frequency(priv,frequency)!=STREAM_OK){ - return 0; - } - if (get_frequency(priv,&frequency)!=STREAM_OK){ - return 0; - } - MP_INFO(priv, "Current frequency: %.2f\n",frequency); - return 1; -} - -/***************************************************************** - * \brief tune current frequency by step_interval value - * \parameter step_interval increment value - * \return 1 if success,0 - otherwise - * - */ -int radio_step_freq(struct stream *stream, float step_interval){ - float frequency; - radio_priv_t* priv=(radio_priv_t*)stream->priv; - - if (get_frequency(priv,&frequency)!=STREAM_OK) - return 0; - - frequency+=step_interval; - if (frequency>priv->rangehigh) - frequency=priv->rangehigh; - if (frequencyrangelow) - frequency=priv->rangelow; - - return radio_set_freq(stream,frequency); -} -/***************************************************************** - * \brief step channel up or down - * \parameter direction RADIO_CHANNEL_LOWER - go to prev channel,RADIO_CHANNEL_HIGHER - to next - * \return 1 if success,0 - otherwise - * - * if channel parameter is NULL function prints error message and does nothing, otherwise - * changes channel to prev or next in list - */ -int radio_step_channel(struct stream *stream, int direction) { - radio_priv_t* priv=(radio_priv_t*)stream->priv; - - if (priv->radio_channel_list) { - switch (direction){ - case RADIO_CHANNEL_HIGHER: - if (priv->radio_channel_current->next) - priv->radio_channel_current = priv->radio_channel_current->next; - else - priv->radio_channel_current = priv->radio_channel_list; - if(!radio_set_freq(stream,priv->radio_channel_current->freq)) - return 0; - MP_VERBOSE(priv, "Selected channel: %d - %s (freq: %.2f)\n", - priv->radio_channel_current->index, priv->radio_channel_current->name, - priv->radio_channel_current->freq); - break; - case RADIO_CHANNEL_LOWER: - if (priv->radio_channel_current->prev) - priv->radio_channel_current = priv->radio_channel_current->prev; - else - while (priv->radio_channel_current->next) - priv->radio_channel_current = priv->radio_channel_current->next; - if(!radio_set_freq(stream,priv->radio_channel_current->freq)) - return 0; - MP_VERBOSE(priv, "Selected channel: %d - %s (freq: %.2f)\n", - priv->radio_channel_current->index, priv->radio_channel_current->name, - priv->radio_channel_current->freq); - break; - } - }else - MP_ERR(priv, "Can not change channel: no channel list given.\n"); - return 1; -} - -/***************************************************************** - * \brief change channel to one with given index - * \parameter channel string, containing channel number - * \return 1 if success,0 - otherwise - * - * if channel parameter is NULL function prints error message and does nothing, otherwise - * changes channel to given - */ -int radio_set_channel(struct stream *stream, char *channel) { - radio_priv_t* priv=(radio_priv_t*)stream->priv; - int i, channel_int; - radio_channels_t* tmp; - char* endptr; - - if (*channel=='\0') - MP_ERR(priv, "Wrong channel name: %s\n",channel); - - if (priv->radio_channel_list) { - channel_int = strtol(channel,&endptr,10); - tmp = priv->radio_channel_list; - if (*endptr!='\0'){ - //channel is not a number, so it contains channel name - for ( ; tmp; tmp=tmp->next) - if (!strncmp(channel,tmp->name,sizeof(tmp->name)-1)) - break; - if (!tmp){ - MP_ERR(priv, "Wrong channel name: %s\n",channel); - return 0; - } - }else{ - for (i = 1; i < channel_int; i++) - if (tmp->next) - tmp = tmp->next; - else - break; - if (tmp->index!=channel_int){ - MP_ERR(priv, "Wrong channel number: %d\n",channel_int); - return 0; - } - } - priv->radio_channel_current=tmp; - MP_VERBOSE(priv, "Selected channel: %d - %s (freq: %.2f)\n", priv->radio_channel_current->index, - priv->radio_channel_current->name, priv->radio_channel_current->freq); - if(!radio_set_freq(stream, priv->radio_channel_current->freq)) - return 0; - } else - MP_ERR(priv, "Can not change channel: no channel list given.\n"); - return 1; -} - -/***************************************************************** - * \brief get current channel's name - * \return pointer to string, containing current channel's name - * - * NOTE: return value may be NULL (e.g. when channel list not initialized) - */ -char* radio_get_channel_name(struct stream *stream){ - radio_priv_t* priv=(radio_priv_t*)stream->priv; - if (priv->radio_channel_current) { - return priv->radio_channel_current->name; - } - return NULL; -} - -/***************************************************************** - * \brief fills given buffer with audio data - * \return number of bytes, written into buffer - */ -static int fill_buffer_s(struct stream *s, char *buffer, int max_len){ - int len=max_len; - -#if HAVE_RADIO_CAPTURE - radio_priv_t* priv=(radio_priv_t*)s->priv; - - if (priv->do_capture){ - len=grab_audio_frame(priv, buffer,max_len); - } - else -#endif - memset(buffer,0,len); - return len; -} - - -/* - order if significant! - when no driver explicitly specified first available will be used - */ -static const radio_driver_t* radio_drivers[]={ -#if HAVE_RADIO_V4L2 - &radio_driver_v4l2, -#endif - 0 -}; - -/***************************************************************** - * Stream initialization - * \return STREAM_OK if success, STREAM_ERROR otherwise - */ -static int open_s(stream_t *stream,int mode) -{ - radio_priv_t* priv; - float frequency=0; - int i; - - if (strncmp("radio://",stream->url,8) != 0) - return STREAM_UNSUPPORTED; - - if(mode != STREAM_READ) - return STREAM_UNSUPPORTED; - - priv=calloc(1,sizeof(radio_priv_t)); - - if (!priv) - return STREAM_ERROR; - - - priv->log = stream->log; - priv->radio_param=stream->priv; - stream->priv=NULL; - -#if HAVE_RADIO_CAPTURE - if (priv->radio_param->capture && strncmp("capture",priv->radio_param->capture,7)==0) - priv->do_capture=1; - else - priv->do_capture=0; -#endif - - - - if (strncmp(priv->radio_param->driver,"default",7)==0) - priv->driver=radio_drivers[0]; - else - priv->driver=NULL; - - MP_VERBOSE(priv, "Available drivers: "); - for(i=0;radio_drivers[i];i++){ - MP_VERBOSE(priv, "%s, ",radio_drivers[i]->name); - if(strcmp(priv->radio_param->driver,radio_drivers[i]->name)==0) - priv->driver=radio_drivers[i]; - } - MP_VERBOSE(priv, "\n"); - - if(priv->driver) - MP_INFO(priv, "%s", priv->driver->info); - else{ - MP_INFO(priv, "Unknown driver name: %s\n",priv->radio_param->driver); - close_s(stream); - return STREAM_ERROR; - } - - stream->type = STREAMTYPE_RADIO; - /* using rawaudio demuxer */ - stream->demuxer = "lavf"; - stream->flags = STREAM_READ; - - priv->radio_fd=-1; - - stream->start_pos=0; - stream->end_pos=0; - stream->priv=priv; - stream->close=close_s; - stream->fill_buffer=fill_buffer_s; - - priv->radio_fd = open(priv->radio_param->device, O_RDONLY | O_CLOEXEC); - if (priv->radio_fd < 0) { - MP_ERR(priv, "Unable to open '%s': %s\n", - priv->radio_param->device, strerror(errno)); - close_s(stream); - return STREAM_ERROR; - } - MP_VERBOSE(priv, "Radio fd: %d, %s\n", priv->radio_fd,priv->radio_param->device); - fcntl(priv->radio_fd, F_SETFD, FD_CLOEXEC); - - get_volume(priv, &priv->old_snd_volume); - set_volume(priv,0); - - if (init_frac(priv)!=STREAM_OK){ - close_s(stream); - return STREAM_ERROR; - }; - - if (parse_channels(priv,priv->radio_param->freq_channel,&frequency)!=STREAM_OK){ - close_s(stream); - return STREAM_ERROR; - } - - if ((frequencyrangelow)||(frequency>priv->rangehigh)){ - MP_ERR(priv, "Wrong frequency: %.2f\n",frequency); - close_s(stream); - return STREAM_ERROR; - }else - MP_INFO(priv, "Using frequency: %.2f.\n",frequency); - - if(set_frequency(priv,frequency)!=STREAM_OK){ - close_s(stream); - return STREAM_ERROR; - } - - - if (init_audio(priv)!=STREAM_OK){ - close_s(stream); - return STREAM_ERROR; - } - - set_volume(priv,priv->radio_param->volume); - - return STREAM_OK; -} - -/***************************************************************** - * Close stream. Clear structures. - */ -static void close_s(struct stream *stream){ - radio_priv_t* priv=(radio_priv_t*)stream->priv; - radio_channels_t * tmp; - if (!priv) return; - -#if HAVE_RADIO_CAPTURE - free(priv->audio_ringbuffer); - priv->audio_ringbuffer = NULL; - - priv->do_capture=0; -#endif - - while (priv->radio_channel_list) { - tmp=priv->radio_channel_list; - priv->radio_channel_list=priv->radio_channel_list->next; - free(tmp); - } - priv->radio_channel_current=NULL; - priv->radio_channel_list=NULL; - - if (priv->radio_fd>0){ - set_volume(priv, priv->old_snd_volume); - close(priv->radio_fd); - } - - free(priv); - stream->priv=NULL; -} - -const stream_info_t stream_info_radio = { - .name = "radio", - .open = open_s, - .protocols = (const char*[]){ "radio", NULL }, - .priv_size = sizeof(radio_param_t), - .priv_defaults = &stream_radio_defaults, - .options = stream_opts_fields, - .url_options = (const char*[]){ - "hostname=freqchannel", - "filename=capture", - NULL - }, -}; diff --git a/stream/stream_radio.h b/stream/stream_radio.h deleted file mode 100644 index ac8d19aa1f..0000000000 --- a/stream/stream_radio.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_STREAM_RADIO_H -#define MPLAYER_STREAM_RADIO_H - -#include "config.h" -#include "stream.h" - -#define RADIO_CHANNEL_LOWER 1 -#define RADIO_CHANNEL_HIGHER 2 - -typedef struct radio_param_s{ - /** name of radio device file */ - char* device; - /** radio driver (v4l,v4l2) */ - char* driver; - /** channels list (see man page) */ - char** channels; - /** initial volume for radio device */ - int volume; - /** name of audio device file to grab data from */ - char* adevice; - /** audio framerate (please also set -rawaudio rate - parameter to the same value) */ - int arate; - /** number of audio channels */ - int achannels; - /** if channels parameter exist, here will be channel - number otherwise - frequency */ - float freq_channel; - char* capture; -} radio_param_t; - -extern radio_param_t stream_radio_defaults; - -int radio_set_freq(struct stream *stream, float freq); -int radio_get_freq(struct stream *stream, float* freq); -char* radio_get_channel_name(struct stream *stream); -int radio_set_channel(struct stream *stream, char *channel); -int radio_step_channel(struct stream *stream, int direction); -int radio_step_freq(struct stream *stream, float step_interval); - -#endif /* MPLAYER_STREAM_RADIO_H */ -- cgit v1.2.3