[vlc-devel] [PATCH 2/2] V4L2: Add support for radio devices.
Rémi Denis-Courmont
remi at remlab.net
Thu Aug 4 11:21:35 CEST 2011
Hello,
Do I get this right that this is meant to control analog audio tuners but
the data is fetched with an ALSA input slave?
Comments inline...
On Thu, 4 Aug 2011 09:53:52 +0200, Thierry Reding
<thierry.reding at avionic-design.de> wrote:
> ---
> modules/access/v4l2.c | 130
> ++++++++++++++++++++++++++++++++++++++++++++++---
> 1 files changed, 122 insertions(+), 8 deletions(-)
>
> diff --git a/modules/access/v4l2.c b/modules/access/v4l2.c
> index f074a9c..eec8f09 100644
> --- a/modules/access/v4l2.c
> +++ b/modules/access/v4l2.c
> @@ -416,8 +416,10 @@ static bool IsPixelFormatSupported( demux_t
*p_demux,
> unsigned int i_pixelformat );
>
> static int InitVideoDev( vlc_object_t *, demux_sys_t *, bool );
> -static int ProbeVideoDev( vlc_object_t *, demux_sys_t *,
> +static int InitRadioDev( vlc_object_t *, demux_sys_t *, bool );
> +static int ProbeDev( vlc_object_t *, demux_sys_t *,
> const char *psz_device );
> +static bool IsRadioDev( demux_sys_t *p_sys );
>
> static int ControlList( vlc_object_t *, demux_sys_t *, int , bool, bool
);
> static int Control( vlc_object_t *, demux_sys_t *, int i_fd,
> @@ -645,11 +647,19 @@ static int FindMainDevice( vlc_object_t *p_this,
> demux_sys_t *p_sys,
> /* TODO: if using default device, loop through all /dev/video*
until
> * one works */
> msg_Dbg( p_this, "opening device '%s'", p_sys->psz_device );
> - p_sys->i_fd = ProbeVideoDev( p_this, p_sys, p_sys->psz_device );
> + p_sys->i_fd = ProbeDev( p_this, p_sys, p_sys->psz_device );
> if( p_sys->i_fd >= 0 )
> {
> - msg_Dbg( p_this, "'%s' is a video device", p_sys->psz_device );
> - InitVideoDev( p_this, p_sys, b_demux );
> + if( IsRadioDev( p_sys ) )
> + {
> + msg_Dbg( p_this, "'%s' is a radio device",
p_sys->psz_device
> );
> + InitRadioDev( p_this, p_sys, b_demux );
> + }
> + else
> + {
> + msg_Dbg( p_this, "'%s' is a video device",
p_sys->psz_device
> );
> + InitVideoDev( p_this, p_sys, b_demux );
> + }
> }
>
> if( p_sys->i_fd < 0 ) return VLC_EGENERIC;
> @@ -1035,6 +1045,9 @@ static void DemuxClose( vlc_object_t *p_this )
> demux_t *p_demux = (demux_t *)p_this;
> demux_sys_t *p_sys = p_demux->p_sys;
>
> + if( IsRadioDev( p_sys ) )
> + goto common;
> +
IMHO, a separate "access_demux" radio sub-module with dedicated Open and
Close functions would be cleaner. In fact, it seems like there is not that
much common code, so you might even consider creating a completely new
plug-in. What do you think?
> /* Stop video capture */
> if( p_sys->i_fd >= 0 )
> {
> @@ -1099,6 +1112,7 @@ static void DemuxClose( vlc_object_t *p_this )
> free( p_sys->p_buffers );
> }
>
> +common:
> CommonClose( p_this, p_sys );
> }
>
> @@ -1268,7 +1282,10 @@ static block_t *AccessRead( access_t * p_access )
>
> /* Wait for data */
> if( poll( &fd, 1, 500 ) > 0 ) /* Timeout after 0.5 seconds since I
> don't know if pf_demux can be blocking. */
> - return GrabVideo( VLC_OBJECT(p_access), p_sys );
> + {
> + if( !IsRadioDev( p_sys ) )
> + return GrabVideo( VLC_OBJECT(p_access), p_sys );
> + }
>
> return NULL;
> }
If there is never going to be any data, then AccessOpen() should fail. So
AccessRead() should never be reached to begin with.
> @@ -1335,7 +1352,7 @@ static int Demux( demux_t *p_demux )
> return -1;
> }
>
> - if( fd.revents )
> + if( fd.revents && !IsRadioDev( p_sys ) )
> {
> block_t *p_block = GrabVideo( VLC_OBJECT(p_demux), p_sys );
> if( p_block )
poll() should be used if events are not dealt with. I guess you can just
set pf_demux to NULL, as in access/screen/xcb.c.
> @@ -2368,9 +2385,98 @@ open_failed:
> }
>
>
/*****************************************************************************
> - * ProbeVideoDev: probe video for capabilities
> + * InitRadioDev: set up the radio device and probe for capabilities
> +
>
*****************************************************************************/
> +static int InitRadioDev( vlc_object_t *p_obj, demux_sys_t *p_sys, bool
> b_demux )
> +{
> + /* Tune the tuner */
> + if( p_sys->i_frequency >= 0 )
> + {
> + if( p_sys->i_cur_tuner < 0 || (unsigned)p_sys->i_cur_tuner >=
> p_sys->i_tuner )
> + {
> + msg_Err( p_obj, "invalid tuner %d.", p_sys->i_cur_tuner );
> + goto open_failed;
> + }
> + struct v4l2_frequency frequency;
> + memset( &frequency, 0, sizeof( frequency ) );
> + frequency.tuner = p_sys->i_cur_tuner;
> + frequency.type = p_sys->p_tuners[p_sys->i_cur_tuner].type;
> + frequency.frequency = p_sys->i_frequency / 62.5;
> + if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_FREQUENCY, &frequency ) <
0
> )
> + {
> + msg_Err( p_obj, "cannot set tuner frequency (%m)" );
> + goto open_failed;
> + }
> + msg_Dbg( p_obj, "Tuner frequency set" );
> + }
> +
> + /* Set the tuner's audio mode */
> + if( p_sys->i_audio_mode >= 0 )
> + {
> + if( p_sys->i_cur_tuner < 0 || (unsigned)p_sys->i_cur_tuner >=
> p_sys->i_tuner )
> + {
> + msg_Err( p_obj, "invalid tuner %d.", p_sys->i_cur_tuner );
> + goto open_failed;
> + }
> + struct v4l2_tuner tuner;
> + memset( &tuner, 0, sizeof( tuner ) );
> + tuner.index = p_sys->i_cur_tuner;
> + tuner.audmode = p_sys->i_audio_mode;
> + if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_TUNER, &tuner ) < 0 )
> + {
> + msg_Err( p_obj, "cannot set tuner audio mode (%m)" );
> + goto open_failed;
> + }
> + msg_Dbg( p_obj, "Tuner audio mode set" );
> + }
> +
> + /* Select input */
> + if( p_sys->i_selected_input >= p_sys->i_input )
> + {
> + msg_Warn( p_obj, "invalid input. Using the default one" );
> + p_sys->i_selected_input = 0;
> + }
> +
> + if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_INPUT,
&p_sys->i_selected_input
> ) < 0 )
> + {
> + msg_Err( p_obj, "cannot set input (%m)" );
> + goto open_failed;
> + }
> +
> + /* Set audio input */
> + if( p_sys->i_audio > 0 )
> + {
> + if( p_sys->i_selected_audio_input < 0
> + || (unsigned)p_sys->i_selected_audio_input >= p_sys->i_audio )
> + {
> + msg_Warn( p_obj, "invalid audio input. Using the default
one"
> );
> + p_sys->i_selected_audio_input = 0;
> + }
> +
> + if( v4l2_ioctl( p_sys->i_fd, VIDIOC_S_AUDIO,
> &p_sys->p_audios[p_sys->i_selected_audio_input] ) < 0 )
> + {
> + msg_Err( p_obj, "cannot set audio input (%m)" );
> + goto open_failed;
> + }
> + msg_Dbg( p_obj, "Audio input set to %d",
> p_sys->i_selected_audio_input );
> + }
> +
> + ControlList( p_obj, p_sys, p_sys->i_fd,
> + var_GetBool( p_obj, "v4l2-controls-reset" ), b_demux
);
> + SetAvailControlsByString( p_obj, p_sys, p_sys->i_fd );
> +
> + return VLC_SUCCESS;
> +
> +open_failed:
> + if( p_sys->i_fd >= 0 ) v4l2_close( p_sys->i_fd );
> + return VLC_EGENERIC;
> +
> +}
> +
>
+/*****************************************************************************
> + * ProbeDev: probe device for capabilities
>
*****************************************************************************/
> -static int ProbeVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
> +static int ProbeDev( vlc_object_t *p_obj, demux_sys_t *p_sys,
> const char *psz_device )
> {
> int i_fd;
> @@ -2737,6 +2843,14 @@ open_failed:
>
> }
>
> +static bool IsRadioDev( demux_sys_t *p_sys )
> +{
> + if ( p_sys && ( p_sys->dev_cap.capabilities & V4L2_CAP_RADIO ) )
> + return true;
> +
> + return false;
> +}
> +
> static void name2var( unsigned char *name )
> {
> for( ; *name; name++ )
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list