[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