* http://www.alsa-project.org
*/
-/*
- * TODO: Tuner partial implementation.
- */
-
/*****************************************************************************
* Preamble
*****************************************************************************/
"To list available controls, increase verbosity (-vvv) " \
"or use the v4l2-ctl application." )
+#define TUNER_TEXT N_("Tuner id")
+#define TUNER_LONGTEXT N_( \
+ "Tuner id (see debug output)." )
+#define FREQUENCY_TEXT N_("Frequency")
+#define FREQUENCY_LONGTEXT N_( \
+ "Tuner frequency in Hz or kHz (see debug output)" )
+#define TUNER_AUDIO_MODE_TEXT N_("Audio mode")
+#define TUNER_AUDIO_MODE_LONGTEXT N_( \
+ "Tuner audio mono/stereo and track selection." )
+
typedef enum {
IO_METHOD_READ,
IO_METHOD_MMAP,
static const char *psz_iomethod_list_text[] =
{ N_("READ"), N_("MMAP"), N_("USERPTR") };
+static int i_tuner_audio_modes_list[] =
+ { V4L2_TUNER_MODE_MONO, V4L2_TUNER_MODE_STEREO,
+ V4L2_TUNER_MODE_LANG1, V4L2_TUNER_MODE_LANG2,
+ V4L2_TUNER_MODE_SAP, V4L2_TUNER_MODE_LANG1_LANG2 };
+static const char *psz_tuner_audio_modes_list_text[] =
+ { N_( "Mono" ),
+ N_( "Stereo" ),
+ N_( "Primary language (Analog TV tuners only)" ),
+ N_( "Secondary language (Analog TV tuners only)" ),
+ N_( "Second audio program (Analog TV tuners only)" ),
+ N_( "Primary language left, Secondary language right" ) };
+
#define FIND_VIDEO 1
#define FIND_AUDIO 2
add_integer( CFG_PREFIX "caching", DEFAULT_PTS_DELAY / 1000, NULL,
CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
+ set_section( N_( "Tuner" ), NULL );
+ add_integer( CFG_PREFIX "tuner", 0, NULL, TUNER_TEXT, TUNER_LONGTEXT,
+ VLC_TRUE );
+ add_integer( CFG_PREFIX "tuner-frequency", -1, NULL, FREQUENCY_TEXT,
+ FREQUENCY_LONGTEXT, VLC_TRUE );
+ add_integer( CFG_PREFIX "tuner-audio-mode", -1, NULL, TUNER_AUDIO_MODE_TEXT,
+ TUNER_AUDIO_MODE_LONGTEXT, VLC_TRUE );
+ change_integer_list( i_tuner_audio_modes_list,
+ psz_tuner_audio_modes_list_text, 0 );
+
set_section( N_( "Controls" ),
N_( "v4l2 driver controls, if supported by your v4l2 driver." ) );
add_bool( CFG_PREFIX "controls-reset", VLC_FALSE, NULL, CTRL_RESET_TEXT,
set_callbacks( DemuxOpen, DemuxClose );
add_submodule();
+ add_shortcut( "v4l2c" );
set_description( _("Video4Linux2 Compressed A/V") );
set_capability( "access2", 0 );
/* use these when open as access_demux fails; VLC will use another demux */
int i_alsa_chunk_size;
#endif
+ /* Tuner */
+ int i_cur_tuner;
+ int i_frequency;
+ int i_audio_mode;
+
+ /* Controls */
char *psz_set_ctrls;
};
#endif
if( FindMainDevice( p_this, p_sys, FIND_VIDEO|FIND_AUDIO,
- VLC_TRUE, !strcmp( p_demux->psz_access, "v4l2" ) ) != VLC_SUCCESS )
+ VLC_TRUE, !strncmp( p_demux->psz_access, "v4l2", 4 ) ) != VLC_SUCCESS )
{
DemuxClose( p_this );
return VLC_EGENERIC;
p_sys->i_pts = var_CreateGetInteger( p_obj, "v4l2-caching" );
+ p_sys->i_cur_tuner = var_CreateGetInteger( p_obj, "v4l2-tuner" );
+ p_sys->i_frequency = var_CreateGetInteger( p_obj, "v4l2-tuner-frequency" );
+ p_sys->i_audio_mode = var_CreateGetInteger( p_obj, "v4l2-tuner-audio-mode" );
+
p_sys->psz_set_ctrls = var_CreateGetString( p_obj, "v4l2-set-ctrls" );
p_sys->psz_device = p_sys->psz_vdev = p_sys->psz_adev = NULL;
p_sys->i_pts = strtol( psz_parser + strlen( "caching=" ),
&psz_parser, 0 );
}
+ else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
+ {
+ p_sys->i_cur_tuner = strtol( psz_parser + strlen( "tuner=" ),
+ &psz_parser, 0 );
+ }
+ else if( !strncmp( psz_parser, "tuner-frequency=", strlen( "tuner-frequency=" ) ) )
+ {
+ p_sys->i_frequency = strtol( psz_parser
+ + strlen( "tuner-frequency=" ),
+ &psz_parser, 0 );
+ }
+ else if( !strncmp( psz_parser, "tuner-audio-mode=", strlen( "tuner-audio-mode=" ) ) )
+ {
+ p_sys->i_audio_mode = strtol( psz_parser
+ + strlen( "tuner-audio-mode=" ),
+ &psz_parser, 0 );
+ }
else if( !strncmp( psz_parser, "set-ctrls=", strlen( "set-ctrls=" )) )
{
int i_len;
/* Close */
if( p_sys->i_fd_video >= 0 ) close( p_sys->i_fd_video );
#ifdef HAVE_ALSA
- if( p_sys->p_alsa_pcm )
+ if( p_sys->p_alsa_pcm )
{
snd_pcm_close( p_sys->p_alsa_pcm );
p_sys->i_fd_audio = -1;
ParseMRL( p_sys, p_access->psz_path, (vlc_object_t *) p_access );
if( FindMainDevice( p_this, p_sys, FIND_VIDEO,
- VLC_FALSE, !strcmp( p_access->psz_access, "v4l2" ) ) != VLC_SUCCESS )
+ VLC_FALSE, !strncmp( p_access->psz_access, "v4l2", 4 ) ) != VLC_SUCCESS )
{
AccessClose( p_this );
return VLC_EGENERIC;
goto open_failed;
}
+ /* Tune the tuner */
+ if( p_sys->i_frequency >= 0 )
+ {
+ if( p_sys->i_cur_tuner < 0 || 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( ioctl( 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 || 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( ioctl( 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 standard */
if( p_sys->i_selected_standard_id != V4L2_STD_UNKNOWN )
p_sys->p_tuners[i_index].capability &
V4L2_TUNER_CAP_LOW ?
"Hz" : "kHz" );
+
+ struct v4l2_frequency frequency;
+ memset( &frequency, 0, sizeof( frequency ) );
+ if( ioctl( i_fd, VIDIOC_G_FREQUENCY, &frequency ) < 0 )
+ {
+ msg_Err( p_obj, "cannot get tuner frequency (%m)" );
+ goto open_failed;
+ }
+ msg_Dbg( p_obj, "tuner %i (%s) frequency: %.1f %s",
+ i_index,
+ p_sys->p_tuners[i_index].name,
+ frequency.frequency * 62.5,
+ p_sys->p_tuners[i_index].capability &
+ V4L2_TUNER_CAP_LOW ?
+ "Hz" : "kHz" );
}
}
/* A list of available controls (aka the variable name) will be
* stored as choices in the "allcontrols" variable. We'll thus be able
- * to use those to create an appropriate interface
+ * to use those to create an appropriate interface
* A list of available controls that can be changed mid-stream will
* be stored in the "controls" variable */
var_Create( p_obj, "controls", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
while( *psz_parser == ',' || *psz_parser == ' ' )
psz_parser++;
-
+
psz_delim = strchr( psz_parser, ',' );
if( psz_delim == NULL )
psz_delim = strchr( psz_parser, '}' );