[vlc-devel] [PATCH 2/2] V4L2: Add support for radio devices.
Thierry Reding
thierry.reding at avionic-design.de
Thu Aug 4 09:53:52 CEST 2011
---
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;
+
/* 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;
}
@@ -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 )
@@ -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++ )
--
1.7.6
More information about the vlc-devel
mailing list