]> git.sesse.net Git - vlc/blobdiff - modules/access/v4l2.c
Fix menu control value display code.
[vlc] / modules / access / v4l2.c
index 48452ba3da43f871ae1e81ab118c2e919497047c..e215a03254a381723685f57a9969314b5c4b34c0 100644 (file)
@@ -74,10 +74,6 @@ static void Close( vlc_object_t * );
 #define DEV_LONGTEXT N_( \
     "Name of the device to use. " \
     "If you don't specify anything, /dev/video0 will be used.")
-#define ADEV_TEXT N_("Audio device name")
-#define ADEV_LONGTEXT N_( \
-    "Name of the audio device to use. " \
-    "If you don't specify anything, /dev/dsp will be used.")
 #define STANDARD_TEXT N_( "Standard" )
 #define STANDARD_LONGTEXT N_( \
     "Video standard (Default, SECAM, PAL, or NTSC)." )
@@ -98,6 +94,13 @@ static void Close( vlc_object_t * );
 #define HEIGHT_TEXT N_( "Height" )
 #define HEIGHT_LONGTEXT N_( \
     "Force height (-1 for autodetect)." )
+#define FPS_TEXT N_( "Framerate" )
+#define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \
+    "(-1 for autodetect)." )
+
+#define VIDEOCTRL_RESET_TEXT N_( "Reset video controls" )
+#define VIDEOCTRL_RESET_LONGTEXT N_( \
+    "Reset video controls to defaults provided by the v4l2 driver." )
 #define BRIGHTNESS_TEXT N_( "Brightness" )
 #define BRIGHTNESS_LONGTEXT N_( \
     "Brightness of the video input." )
@@ -110,9 +113,14 @@ static void Close( vlc_object_t * );
 #define HUE_TEXT N_( "Hue" )
 #define HUE_LONGTEXT N_( \
     "Hue of the video input." )
-#define FPS_TEXT N_( "Framerate" )
-#define FPS_LONGTEXT N_( "Framerate to capture, if applicable " \
-    "(-1 for autodetect)." )
+#define GAMMA_TEXT N_( "Gamma" )
+#define GAMMA_LONGTEXT N_( \
+    "Gamma of the video input." )
+
+#define ADEV_TEXT N_("Audio device name")
+#define ADEV_LONGTEXT N_( \
+    "Name of the audio device to use. " \
+    "If you don't specify anything, /dev/dsp will be used.")
 #define ALSA_TEXT N_( "Use Alsa" )
 #define ALSA_LONGTEXT N_( \
     "Use ALSA instead of OSS for audio" )
@@ -122,6 +130,7 @@ static void Close( vlc_object_t * );
 #define SAMPLERATE_TEXT N_( "Samplerate" )
 #define SAMPLERATE_LONGTEXT N_( \
     "Samplerate of the captured audio stream, in Hz (eg: 11025, 22050, 44100, 48000)" )
+
 #define CACHING_TEXT N_("Caching value in ms")
 #define CACHING_LONGTEXT N_( \
     "Caching value for V4L2 captures. This " \
@@ -149,10 +158,9 @@ vlc_module_begin();
     set_category( CAT_INPUT );
     set_subcategory( SUBCAT_INPUT_ACCESS );
 
+    set_section( N_( "Video input" ), NULL );
     add_string( "v4l2-dev", "/dev/video0", 0, DEV_TEXT, DEV_LONGTEXT,
                 VLC_FALSE );
-    add_string( "v4l2-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT,
-                VLC_FALSE );
     add_integer( "v4l2-standard", 0, NULL, STANDARD_TEXT, STANDARD_LONGTEXT,
                 VLC_FALSE );
         change_integer_list( i_standards_list, psz_standards_list_text, 0 );
@@ -167,6 +175,11 @@ vlc_module_begin();
                 WIDTH_LONGTEXT, VLC_TRUE );
     add_integer( "v4l2-height", 0, NULL, HEIGHT_TEXT,
                 HEIGHT_LONGTEXT, VLC_TRUE );
+    add_float( "v4l2-fps", 0, NULL, FPS_TEXT, FPS_LONGTEXT, VLC_TRUE );
+
+    set_section( N_( "Video controls" ), NULL );
+    add_bool( "v4l2-videocontrol-reset", VLC_FALSE, NULL, VIDEOCTRL_RESET_TEXT,
+              VIDEOCTRL_RESET_LONGTEXT, VLC_TRUE );
     add_integer( "v4l2-brightness", -1, NULL, BRIGHTNESS_TEXT,
                 BRIGHTNESS_LONGTEXT, VLC_TRUE );
     add_integer( "v4l2-contrast", -1, NULL, CONTRAST_TEXT,
@@ -175,7 +188,12 @@ vlc_module_begin();
                 SATURATION_LONGTEXT, VLC_TRUE );
     add_integer( "v4l2-hue", -1, NULL, HUE_TEXT,
                 HUE_LONGTEXT, VLC_TRUE );
-    add_float( "v4l2-fps", 0, NULL, FPS_TEXT, FPS_LONGTEXT, VLC_TRUE );
+    add_integer( "v4l2-gamma", -1, NULL, GAMMA_TEXT,
+                GAMMA_LONGTEXT, VLC_TRUE );
+
+    set_section( N_( "Audio input" ), NULL );
+    add_string( "v4l2-adev", "/dev/dsp", 0, ADEV_TEXT, ADEV_LONGTEXT,
+                VLC_FALSE );
 #ifdef HAVE_ALSA
     add_bool( "v4l2-alsa", VLC_FALSE, NULL, ALSA_TEXT, ALSA_LONGTEXT,
                 VLC_TRUE );
@@ -213,7 +231,7 @@ static int OpenAudioDev( demux_t *, char *psz_device );
 static vlc_bool_t ProbeVideoDev( demux_t *, char *psz_device );
 static vlc_bool_t ProbeAudioDev( demux_t *, char *psz_device );
 
-static int VideoControlList( demux_t *p_demux, int i_fd );
+static int VideoControlList( demux_t *p_demux, int i_fd, vlc_bool_t b_reset );
 static int VideoControl( demux_t *, int i_fd,
                          const char *psz_label, int i_cid, int i_value );
 static int VideoControlCallback( vlc_object_t *p_this,
@@ -296,10 +314,12 @@ struct demux_sys_t
     mtime_t i_video_pts;    /* only used when f_fps > 0 */
     int i_fourcc;
 
+    vlc_bool_t b_videoctrl_reset;
     int i_brightness;
     int i_contrast;
     int i_saturation;
     int i_hue;
+    int i_gamma;
 
     picture_t pic;
     int i_video_frame_size;
@@ -361,6 +381,8 @@ static int Open( vlc_object_t *p_this )
     p_sys->i_width = var_CreateGetInteger( p_demux, "v4l2-width" );
     p_sys->i_height = var_CreateGetInteger( p_demux, "v4l2-height" );
 
+    p_sys->b_videoctrl_reset =
+        var_CreateGetBool( p_demux, "v4l2-videocontrol-reset" );
     p_sys->i_brightness =
         var_CreateGetIntegerCommand( p_demux, "v4l2-brightness" );
     p_sys->i_contrast =
@@ -369,11 +391,17 @@ static int Open( vlc_object_t *p_this )
         var_CreateGetIntegerCommand( p_demux, "v4l2-saturation" );
     p_sys->i_hue =
         var_CreateGetIntegerCommand( p_demux, "v4l2-hue" );
+    p_sys->i_gamma =
+        var_CreateGetIntegerCommand( p_demux, "v4l2-gamma" );
 
     var_AddCallback( p_demux, "v4l2-brightness", VideoControlCallback, NULL );
     var_AddCallback( p_demux, "v4l2-contrast", VideoControlCallback, NULL );
     var_AddCallback( p_demux, "v4l2-saturation", VideoControlCallback, NULL );
     var_AddCallback( p_demux, "v4l2-hue", VideoControlCallback, NULL );
+    var_AddCallback( p_demux, "v4l2-gamma", VideoControlCallback, NULL );
+
+    var_Create( p_demux, "videocontrol", VLC_VAR_STRING | VLC_VAR_ISCOMMAND );
+    var_AddCallback( p_demux, "videocontrol", VideoControlCallback, NULL );
 
     var_Create( p_demux, "v4l2-fps", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
     var_Get( p_demux, "v4l2-fps", &val );
@@ -638,6 +666,12 @@ static void ParseMRL( demux_t *p_demux )
                     strtol( psz_parser + strlen( "height=" ),
                             &psz_parser, 0 );
             }
+            else if( !strncmp( psz_parser, "videocontrol-reset",
+                               strlen( "videocontrol-reset" ) ) )
+            {
+                p_sys->b_videoctrl_reset = VLC_TRUE;
+                psz_parser += strlen( "videocontrol-reset" );
+            }
             else if( !strncmp( psz_parser, "brightness=",
                                strlen( "brightness=" ) ) )
             {
@@ -666,6 +700,13 @@ static void ParseMRL( demux_t *p_demux )
                     strtol( psz_parser + strlen( "hue=" ),
                             &psz_parser, 0 );
             }
+            else if( !strncmp( psz_parser, "gamma=",
+                               strlen( "gamma=" ) ) )
+            {
+                p_sys->i_gamma =
+                    strtol( psz_parser + strlen( "gamma=" ),
+                            &psz_parser, 0 );
+            }
             else if( !strncmp( psz_parser, "samplerate=",
                                strlen( "samplerate=" ) ) )
             {
@@ -1527,7 +1568,7 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
     }
 #endif
 
-    VideoControlList( p_demux, i_fd );
+    VideoControlList( p_demux, i_fd, p_sys->b_videoctrl_reset );
 
     VideoControl( p_demux, i_fd,
                   "brightness", V4L2_CID_BRIGHTNESS, p_sys->i_brightness );
@@ -1536,6 +1577,7 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
     VideoControl( p_demux, i_fd,
                   "saturation", V4L2_CID_SATURATION, p_sys->i_saturation );
     VideoControl( p_demux, i_fd, "hue", V4L2_CID_HUE, p_sys->i_hue );
+    VideoControl( p_demux, i_fd, "gamma", V4L2_CID_GAMMA, p_sys->i_gamma );
 
     /* Init vout Picture */
     vout_InitPicture( VLC_OBJECT(p_demux), &p_sys->pic, p_sys->i_fourcc,
@@ -2282,10 +2324,82 @@ open_failed:
 /*****************************************************************************
  * List available controls
  *****************************************************************************/
-static int VideoControlList( demux_t *p_demux, int i_fd )
+static void VideoControlListPrint( demux_t *p_demux, int i_fd,
+                                   struct v4l2_queryctrl queryctrl,
+                                   vlc_bool_t b_reset )
 {
-    struct v4l2_queryctrl queryctrl;
     struct v4l2_querymenu querymenu;
+    if( queryctrl.flags & V4L2_CTRL_FLAG_GRABBED )
+        msg_Dbg( p_demux, "    control is busy" );
+    if( queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY )
+        msg_Dbg( p_demux, "    control is read-only" );
+    switch( queryctrl.type )
+    {
+        case V4L2_CTRL_TYPE_INTEGER:
+            msg_Dbg( p_demux, "    integer control" );
+            msg_Dbg( p_demux,
+                     "    valid values: %d to %d by steps of %d",
+                     queryctrl.minimum, queryctrl.maximum,
+                     queryctrl.step );
+            break;
+        case V4L2_CTRL_TYPE_BOOLEAN:
+            msg_Dbg( p_demux, "    boolean control" );
+            break;
+        case V4L2_CTRL_TYPE_MENU:
+            msg_Dbg( p_demux, "    menu control" );
+            memset( &querymenu, 0, sizeof( querymenu ) );
+            querymenu.id = queryctrl.id;
+            for( querymenu.index = queryctrl.minimum;
+                 querymenu.index <= (unsigned)queryctrl.maximum;
+                 querymenu.index++ )
+            {
+                if( ioctl( i_fd, VIDIOC_QUERYMENU, &querymenu ) >= 0 )
+                {
+                    msg_Dbg( p_demux, "        %d: %s",
+                             querymenu.index, querymenu.name );
+                }
+            }
+            break;
+        case V4L2_CTRL_TYPE_BUTTON:
+            msg_Dbg( p_demux, "    button control" );
+            break;
+        default:
+            msg_Dbg( p_demux, "    unknown control type (FIXME)" );
+            /* FIXME */
+            break;
+    }
+
+    switch( queryctrl.type )
+    {
+        case V4L2_CTRL_TYPE_INTEGER:
+        case V4L2_CTRL_TYPE_BOOLEAN:
+        case V4L2_CTRL_TYPE_MENU:
+            {
+                struct v4l2_control control;
+                msg_Dbg( p_demux, "    default value: %d",
+                         queryctrl.default_value );
+                memset( &control, 0, sizeof( control ) );
+                control.id = queryctrl.id;
+                if( ioctl( i_fd, VIDIOC_G_CTRL, &control ) >= 0 )
+                {
+                    msg_Dbg( p_demux, "    current value: %d", control.value );
+                }
+                if( b_reset && queryctrl.default_value != control.value )
+                {
+                    msg_Dbg( p_demux, "    reset value to default" );
+                    VideoControl( p_demux, i_fd, NULL,
+                                  queryctrl.id, queryctrl.default_value );
+                }
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+static int VideoControlList( demux_t *p_demux, int i_fd, vlc_bool_t b_reset )
+{
+    struct v4l2_queryctrl queryctrl;
 
     memset( &queryctrl, 0, sizeof( queryctrl ) );
 
@@ -2300,50 +2414,7 @@ static int VideoControlList( demux_t *p_demux, int i_fd )
                 continue;
             msg_Dbg( p_demux, "Available control: %s (%x)",
                      queryctrl.name, queryctrl.id );
-            if( queryctrl.flags & V4L2_CTRL_FLAG_GRABBED )
-                msg_Dbg( p_demux, "    control is busy" );
-            if( queryctrl.flags & V4L2_CTRL_FLAG_READ_ONLY )
-                msg_Dbg( p_demux, "    control is read-only" );
-            switch( queryctrl.type )
-            {
-                case V4L2_CTRL_TYPE_INTEGER:
-                    msg_Dbg( p_demux, "    integer control" );
-                    msg_Dbg( p_demux,
-                             "    valid values: %d to %d by steps of %d",
-                             queryctrl.minimum, queryctrl.maximum,
-                             queryctrl.step );
-                    msg_Dbg( p_demux, "    default value: %d",
-                             queryctrl.default_value );
-                    break;
-                case V4L2_CTRL_TYPE_BOOLEAN:
-                    msg_Dbg( p_demux, "    boolean control" );
-                    msg_Dbg( p_demux, "    default value: %d",
-                             queryctrl.default_value );
-                    break;
-                case V4L2_CTRL_TYPE_MENU:
-                    msg_Dbg( p_demux, "    menu control" );
-                    memset( &querymenu, 0, sizeof( querymenu ) );
-                    for( querymenu.index = queryctrl.minimum;
-                         querymenu.index <= (unsigned)queryctrl.maximum;
-                         querymenu.index++ )
-                    {
-                        if( ioctl( i_fd, VIDIOC_QUERYMENU, &querymenu ) >= 0 )
-                        {
-                            msg_Dbg( p_demux, "        %d: %s",
-                                     querymenu.index, querymenu.name );
-                        }
-                    }
-                    msg_Dbg( p_demux, "    default value: %d",
-                             queryctrl.default_value );
-                    break;
-                case V4L2_CTRL_TYPE_BUTTON:
-                    msg_Dbg( p_demux, "    button control" );
-                    break;
-                default:
-                    msg_Dbg( p_demux, "    unknown control type (FIXME)" );
-                    /* FIXME */
-                    break;
-            }
+            VideoControlListPrint( p_demux, i_fd, queryctrl, b_reset );
         }
     }
 
@@ -2356,8 +2427,9 @@ static int VideoControlList( demux_t *p_demux, int i_fd )
         {
             if( queryctrl.flags & V4L2_CTRL_FLAG_DISABLED )
                 continue;
-            msg_Dbg( p_demux, "Available private control: %s",
-                     queryctrl.name );
+            msg_Dbg( p_demux, "Available private control: %s (%x)",
+                     queryctrl.name, queryctrl.id );
+            VideoControlListPrint( p_demux, i_fd, queryctrl, b_reset );
         }
         else
             break;
@@ -2373,6 +2445,10 @@ static int VideoControl( demux_t *p_demux, int i_fd,
 {
     struct v4l2_queryctrl queryctrl;
     struct v4l2_control control;
+
+    if( i_value == -1 )
+        return VLC_SUCCESS;
+
     memset( &queryctrl, 0, sizeof( queryctrl ) );
 
     queryctrl.id = i_cid;
@@ -2380,11 +2456,14 @@ static int VideoControl( demux_t *p_demux, int i_fd,
     if( ioctl( i_fd, VIDIOC_QUERYCTRL, &queryctrl ) < 0
         || queryctrl.flags & V4L2_CTRL_FLAG_DISABLED )
     {
-        msg_Warn( p_demux, "%s (%x) control is not supported.", psz_label,
-                 i_value );
+        msg_Err( p_demux, "%s (%x) control is not supported.", psz_label,
+                 i_cid );
         return VLC_EGENERIC;
     }
 
+    if( !psz_label )
+        psz_label = (const char*)queryctrl.name;
+
     memset( &control, 0, sizeof( control ) );
     control.id = i_cid;
 
@@ -2420,31 +2499,43 @@ static int VideoControlCallback( vlc_object_t *p_this,
     if( i_fd < 0 )
         return VLC_EGENERIC;
 
-    if( !strcmp( psz_var, "brightness" ) )
+    if( !strcmp( psz_var, "v4l2-brightness" ) )
     {
         p_sys->i_brightness = newval.i_int;
         return VideoControl( p_demux, i_fd,
                     "brightness", V4L2_CID_BRIGHTNESS, p_sys->i_brightness );
     }
-    else if( !strcmp( psz_var, "contrast" ) )
+    else if( !strcmp( psz_var, "v4l2-contrast" ) )
     {
         p_sys->i_contrast = newval.i_int;
         return VideoControl( p_demux, i_fd,
                     "contrast", V4L2_CID_CONTRAST, p_sys->i_contrast );
     }
-    else if( !strcmp( psz_var, "saturation" ) )
+    else if( !strcmp( psz_var, "v4l2-saturation" ) )
     {
         p_sys->i_saturation = newval.i_int;
         return VideoControl( p_demux, i_fd,
                     "saturation", V4L2_CID_SATURATION, p_sys->i_saturation );
     }
-    else if( !strcmp( psz_var, "hue" ) )
+    else if( !strcmp( psz_var, "v4l2-hue" ) )
     {
         p_sys->i_hue = newval.i_int;
         return VideoControl( p_demux, i_fd,
                     "hue", V4L2_CID_HUE, p_sys->i_hue );
     }
-    else
-        return VLC_EGENERIC;
-    return VLC_SUCCESS;
+    else if( !strcmp( psz_var, "v4l2-gamma" ) )
+    {
+        p_sys->i_gamma = newval.i_int;
+        return VideoControl( p_demux, i_fd,
+                    "gamma", V4L2_CID_HUE, p_sys->i_gamma );
+    }
+    else if( !strcmp( psz_var, "videocontrol" ) )
+    {
+        char *psz_var = newval.psz_string;
+        int i_cid = strtol( psz_var, &psz_var, 16 );
+        int i_value = strtol( psz_var, &psz_var, 0 );
+        return VideoControl( p_demux, i_fd, NULL, i_cid, i_value );
+    }
+
+    return VLC_EGENERIC;
 }