Commit 2971d9bd authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

v4l2: add basic support for AM and FM tuners (fixes #6788)

parent 71f0a5f5
...@@ -152,6 +152,7 @@ libv4l2_plugin_la_SOURCES = \ ...@@ -152,6 +152,7 @@ libv4l2_plugin_la_SOURCES = \
v4l2/video.c \ v4l2/video.c \
v4l2/demux.c \ v4l2/demux.c \
v4l2/access.c \ v4l2/access.c \
v4l2/radio.c \
v4l2/controls.c \ v4l2/controls.c \
v4l2/lib.c \ v4l2/lib.c \
v4l2/v4l2.h v4l2/v4l2.h
......
/*****************************************************************************
* radio.c : V4L2 analog radio receiver
*****************************************************************************
* Copyright (C) 2012 Rémi Denis-Courmont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <fcntl.h>
#include <vlc_common.h>
#include <vlc_demux.h>
#include <vlc_fs.h>
#include "v4l2.h"
struct demux_sys_t
{
int fd;
vlc_v4l2_ctrl_t *controls;
};
static int RadioControl (demux_t *demux, int query, va_list args)
{
switch (query)
{
case DEMUX_CAN_PAUSE:
case DEMUX_CAN_SEEK:
case DEMUX_CAN_CONTROL_PACE:
*va_arg (args, bool *) = false;
break;
case DEMUX_GET_PTS_DELAY:
*va_arg (args,int64_t *) = INT64_C(1000)
* var_InheritInteger (demux, "live-caching");
break;
case DEMUX_GET_TIME:
*va_arg (args, int64_t *) = mdate ();
break;
/* TODO implement others */
default:
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
int RadioOpen (vlc_object_t *obj)
{
demux_t *demux = (demux_t *)obj;
/* Parse MRL */
size_t pathlen = strcspn (demux->psz_location, ":;");
char *path = (pathlen != 0) ? strndup (demux->psz_location, pathlen)
: var_InheritString (obj, CFG_PREFIX"radio-dev");
if (unlikely(path == NULL))
return VLC_ENOMEM;
if (demux->psz_location[pathlen] != '\0')
var_LocationParse (obj, demux->psz_location + pathlen + 1, CFG_PREFIX);
/* Open device */
uint32_t caps;
int fd = OpenDevice (obj, path, &caps);
free (path);
if (fd == -1)
return VLC_EGENERIC;
if (!(caps & V4L2_CAP_TUNER))
{
msg_Err (obj, "not a radio tuner device");
goto error;
}
if (SetupTuner (obj, fd, 0))
goto error;
demux_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
goto error;
sys->fd = fd;
sys->controls = ControlsInit (VLC_OBJECT(demux), fd);
demux->p_sys = sys;
demux->pf_demux = NULL;
demux->pf_control = RadioControl;
demux->info.i_update = 0;
demux->info.i_title = 0;
demux->info.i_seekpoint = 0;
return VLC_SUCCESS;
error:
v4l2_close (fd);
return VLC_EGENERIC;
}
void RadioClose (vlc_object_t *obj)
{
demux_t *demux = (demux_t *)obj;
demux_sys_t *sys = demux->p_sys;
ControlsDeinit (obj, sys->controls);
v4l2_close (sys->fd);
free (sys);
}
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
#include "v4l2.h" #include "v4l2.h"
#define DEVICE_TEXT N_( "Device" ) #define VIDEO_DEVICE_TEXT N_( "Video capture device" )
#define DEVICE_LONGTEXT N_("Video device node." ) #define VIDEO_DEVICE_LONGTEXT N_("Video capture device node." )
#define STANDARD_TEXT N_( "Standard" ) #define STANDARD_TEXT N_( "Standard" )
#define STANDARD_LONGTEXT N_( \ #define STANDARD_LONGTEXT N_( \
"Video standard (Default, SECAM, PAL, or NTSC)." ) "Video standard (Default, SECAM, PAL, or NTSC)." )
...@@ -66,6 +66,15 @@ ...@@ -66,6 +66,15 @@
/*#define FPS_TEXT N_( "Frame rate" ) /*#define FPS_TEXT N_( "Frame rate" )
#define FPS_LONGTEXT N_( "Maximum frame rate to use (0 = no limits)." )*/ #define FPS_LONGTEXT N_( "Maximum frame rate to use (0 = no limits)." )*/
#define RADIO_DEVICE_TEXT N_( "Radio device" )
#define RADIO_DEVICE_LONGTEXT N_("Radio tuner device node." )
#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." )
#define CTRL_RESET_TEXT N_( "Reset controls" ) #define CTRL_RESET_TEXT N_( "Reset controls" )
#define CTRL_RESET_LONGTEXT N_( "Reset controls to defaults." ) #define CTRL_RESET_LONGTEXT N_( "Reset controls to defaults." )
#define BRIGHTNESS_TEXT N_( "Brightness" ) #define BRIGHTNESS_TEXT N_( "Brightness" )
...@@ -180,13 +189,6 @@ static const char *const colorfx_user[] = { N_("Unspecified"), N_("None"), ...@@ -180,13 +189,6 @@ static const char *const colorfx_user[] = { N_("Unspecified"), N_("None"),
"To list available controls, increase verbosity (-vvv) " \ "To list available controls, increase verbosity (-vvv) " \
"or use the v4l2-ctl application." ) "or use the v4l2-ctl application." )
#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." )
#define ASPECT_TEXT N_("Picture aspect-ratio n:m") #define ASPECT_TEXT N_("Picture aspect-ratio n:m")
#define ASPECT_LONGTEXT N_("Define input picture aspect-ratio to use. Default is 4:3" ) #define ASPECT_LONGTEXT N_("Define input picture aspect-ratio to use. Default is 4:3" )
...@@ -266,14 +268,14 @@ static const char *const psz_tuner_audio_modes_list_text[] = { ...@@ -266,14 +268,14 @@ static const char *const psz_tuner_audio_modes_list_text[] = {
}; };
vlc_module_begin () vlc_module_begin ()
set_shortname( N_("Video4Linux2") ) set_shortname( N_("V4L") )
set_description( N_("Video4Linux2 input") ) set_description( N_("Video4Linux input") )
set_category( CAT_INPUT ) set_category( CAT_INPUT )
set_subcategory( SUBCAT_INPUT_ACCESS ) set_subcategory( SUBCAT_INPUT_ACCESS )
set_section( N_( "Video input" ), NULL ) set_section( N_( "Video input" ), NULL )
add_loadfile( CFG_PREFIX "dev", "/dev/video0", add_loadfile( CFG_PREFIX "dev", "/dev/video0",
DEVICE_TEXT, DEVICE_LONGTEXT, false ) VIDEO_DEVICE_TEXT, VIDEO_DEVICE_LONGTEXT, false )
change_safe() change_safe()
add_string( CFG_PREFIX "standard", "", add_string( CFG_PREFIX "standard", "",
STANDARD_TEXT, STANDARD_LONGTEXT, false ) STANDARD_TEXT, STANDARD_LONGTEXT, false )
...@@ -306,6 +308,9 @@ vlc_module_begin () ...@@ -306,6 +308,9 @@ vlc_module_begin ()
add_obsolete_bool( CFG_PREFIX "use-libv4l2" ) /* since 2.1.0 */ add_obsolete_bool( CFG_PREFIX "use-libv4l2" ) /* since 2.1.0 */
set_section( N_( "Tuner" ), NULL ) set_section( N_( "Tuner" ), NULL )
add_loadfile( CFG_PREFIX "radio-dev", "/dev/radio0",
RADIO_DEVICE_TEXT, RADIO_DEVICE_LONGTEXT, false )
change_safe()
add_obsolete_integer( CFG_PREFIX "tuner" ) /* since 2.1.0 */ add_obsolete_integer( CFG_PREFIX "tuner" ) /* since 2.1.0 */
add_integer( CFG_PREFIX "tuner-frequency", -1, FREQUENCY_TEXT, add_integer( CFG_PREFIX "tuner-frequency", -1, FREQUENCY_TEXT,
FREQUENCY_LONGTEXT, true ) FREQUENCY_LONGTEXT, true )
...@@ -409,11 +414,17 @@ vlc_module_begin () ...@@ -409,11 +414,17 @@ vlc_module_begin ()
add_submodule () add_submodule ()
add_shortcut( "v4l", "v4l2", "v4l2c" ) add_shortcut( "v4l", "v4l2", "v4l2c" )
set_description( N_("Video4Linux2 Compressed A/V") ) set_description( N_("Video4Linux compressed A/V input") )
set_capability( "access", 0 ) set_capability( "access", 0 )
/* use these when open as access_demux fails; VLC will use another demux */ /* use these when open as access_demux fails; VLC will use another demux */
set_callbacks( AccessOpen, AccessClose ) set_callbacks( AccessOpen, AccessClose )
add_submodule ()
add_shortcut ("radio" /*, "fm", "am" */)
set_description (N_("Video4Linux radio tuner"))
set_capability ("access_demux", 0)
set_callbacks (RadioOpen, RadioClose)
vlc_module_end () vlc_module_end ()
/** /**
......
...@@ -88,6 +88,7 @@ int SetupFormat (vlc_object_t *, int, uint32_t, ...@@ -88,6 +88,7 @@ int SetupFormat (vlc_object_t *, int, uint32_t,
struct v4l2_format *, struct v4l2_streamparm *); struct v4l2_format *, struct v4l2_streamparm *);
#define SetupFormat(o,fd,fcc,fmt,p) \ #define SetupFormat(o,fd,fcc,fmt,p) \
SetupFormat(VLC_OBJECT(o),fd,fcc,fmt,p) SetupFormat(VLC_OBJECT(o),fd,fcc,fmt,p)
int SetupTuner (vlc_object_t *, int fd, uint32_t);
int StartUserPtr (vlc_object_t *, int); int StartUserPtr (vlc_object_t *, int);
struct buffer_t *StartMmap (vlc_object_t *, int, uint32_t *); struct buffer_t *StartMmap (vlc_object_t *, int, uint32_t *);
...@@ -106,6 +107,10 @@ void GetMaxDimensions(vlc_object_t *, int fd, uint32_t fmt, float fps_min, ...@@ -106,6 +107,10 @@ void GetMaxDimensions(vlc_object_t *, int fd, uint32_t fmt, float fps_min,
int AccessOpen(vlc_object_t *); int AccessOpen(vlc_object_t *);
void AccessClose(vlc_object_t *); void AccessClose(vlc_object_t *);
/* radio.c */
int RadioOpen(vlc_object_t *);
void RadioClose(vlc_object_t *);
/* controls.c */ /* controls.c */
vlc_v4l2_ctrl_t *ControlsInit(vlc_object_t *, int fd); vlc_v4l2_ctrl_t *ControlsInit(vlc_object_t *, int fd);
void ControlsDeinit(vlc_object_t *, vlc_v4l2_ctrl_t *); void ControlsDeinit(vlc_object_t *, vlc_v4l2_ctrl_t *);
...@@ -116,7 +116,7 @@ static int SetupAudio (vlc_object_t *obj, int fd, ...@@ -116,7 +116,7 @@ static int SetupAudio (vlc_object_t *obj, int fd,
return 0; return 0;
} }
static int SetupTuner (vlc_object_t *obj, int fd, uint32_t idx) int SetupTuner (vlc_object_t *obj, int fd, uint32_t idx)
{ {
struct v4l2_tuner tuner = { .index = idx }; struct v4l2_tuner tuner = { .index = idx };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment