mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 18:50:48 +00:00
d9e61954a1
Rename start and stop methods to open and close because that is what they do. After setting the format on the device object, setup the bufferpools. Move this code from the v4l2src_calls.c file, it is shared between source and sink. Make new device start and stop method that merges various bits of common code spread over several files.
579 lines
15 KiB
C
579 lines
15 KiB
C
/* GStreamer v4l2 radio tuner element
|
|
* Copyright (C) 2010, 2011 Alexey Chernov <4ernov@gmail.com>
|
|
*
|
|
* gstv4l2radio.c - V4L2 radio tuner element
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
/**
|
|
* SECTION:element-v4l2radio
|
|
*
|
|
* v4l2radio can be used to control radio device
|
|
* and to tune it to different radiostations.
|
|
*
|
|
* <refsect2>
|
|
* <title>Example launch lines</title>
|
|
* |[
|
|
* gst-launch v4l2radio device=/dev/radio0 frequency=101200000
|
|
* gst-launch alsasrc device=hw:1 ! audioconvert ! audioresample ! alsasink
|
|
* ]|
|
|
* First pipeline tunes the radio device /dev/radio0 to station 101.2 MHz,
|
|
* second pipeline connects digital audio out (hw:1) to default sound card.
|
|
* </refsect2>
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "gst/gst-i18n-plugin.h"
|
|
|
|
#include "gstv4l2tuner.h"
|
|
#include "gstv4l2radio.h"
|
|
#include "v4l2_calls.h"
|
|
|
|
GST_DEBUG_CATEGORY_STATIC (v4l2radio_debug);
|
|
#define GST_CAT_DEFAULT v4l2radio_debug
|
|
|
|
#define DEFAULT_PROP_DEVICE "/dev/radio0"
|
|
#define MIN_FREQUENCY 87500000
|
|
#define DEFAULT_FREQUENCY 100000000
|
|
#define MAX_FREQUENCY 108000000
|
|
|
|
enum
|
|
{
|
|
ARG_0,
|
|
ARG_DEVICE,
|
|
ARG_FREQUENCY
|
|
};
|
|
|
|
static gboolean
|
|
gst_v4l2radio_fill_channel_list (GstV4l2Radio * radio)
|
|
{
|
|
int res;
|
|
struct v4l2_tuner vtun;
|
|
struct v4l2_capability vc;
|
|
GstV4l2TunerChannel *v4l2channel;
|
|
GstTunerChannel *channel;
|
|
|
|
GstElement *e;
|
|
|
|
GstV4l2Object *v4l2object;
|
|
|
|
e = GST_ELEMENT (radio);
|
|
v4l2object = radio->v4l2object;
|
|
|
|
GST_DEBUG_OBJECT (e, "getting audio enumeration");
|
|
GST_V4L2_CHECK_OPEN (v4l2object);
|
|
|
|
GST_DEBUG_OBJECT (e, " audio input");
|
|
|
|
memset (&vc, 0, sizeof (vc));
|
|
|
|
res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &vc);
|
|
if (res < 0)
|
|
goto caps_failed;
|
|
|
|
if (!(vc.capabilities & V4L2_CAP_TUNER))
|
|
goto not_a_tuner;
|
|
|
|
/* getting audio input */
|
|
memset (&vtun, 0, sizeof (vtun));
|
|
vtun.index = 0;
|
|
|
|
res = v4l2_ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun);
|
|
if (res < 0)
|
|
goto tuner_failed;
|
|
|
|
GST_LOG_OBJECT (e, " index: %d", vtun.index);
|
|
GST_LOG_OBJECT (e, " name: '%s'", vtun.name);
|
|
GST_LOG_OBJECT (e, " type: %016x", (guint) vtun.type);
|
|
GST_LOG_OBJECT (e, " caps: %016x", (guint) vtun.capability);
|
|
GST_LOG_OBJECT (e, " rlow: %016x", (guint) vtun.rangelow);
|
|
GST_LOG_OBJECT (e, " rhigh: %016x", (guint) vtun.rangehigh);
|
|
GST_LOG_OBJECT (e, " audmode: %016x", (guint) vtun.audmode);
|
|
|
|
v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
|
|
channel = GST_TUNER_CHANNEL (v4l2channel);
|
|
channel->label = g_strdup ((const gchar *) vtun.name);
|
|
channel->flags = GST_TUNER_CHANNEL_FREQUENCY | GST_TUNER_CHANNEL_AUDIO;
|
|
v4l2channel->index = 0;
|
|
v4l2channel->tuner = 0;
|
|
|
|
channel->freq_multiplicator =
|
|
62.5 * ((vtun.capability & V4L2_TUNER_CAP_LOW) ? 1 : 1000);
|
|
channel->min_frequency = vtun.rangelow * channel->freq_multiplicator;
|
|
channel->max_frequency = vtun.rangehigh * channel->freq_multiplicator;
|
|
channel->min_signal = 0;
|
|
channel->max_signal = 0xffff;
|
|
|
|
v4l2object->channels =
|
|
g_list_prepend (v4l2object->channels, (gpointer) channel);
|
|
|
|
v4l2object->channels = g_list_reverse (v4l2object->channels);
|
|
|
|
GST_DEBUG_OBJECT (e, "done");
|
|
return TRUE;
|
|
|
|
/* ERRORS */
|
|
tuner_failed:
|
|
{
|
|
GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
|
|
(_("Failed to get settings of tuner %d on device '%s'."),
|
|
vtun.index, v4l2object->videodev), GST_ERROR_SYSTEM);
|
|
return FALSE;
|
|
}
|
|
caps_failed:
|
|
{
|
|
GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
|
|
(_("Error getting capabilities for device '%s'."),
|
|
v4l2object->videodev), GST_ERROR_SYSTEM);
|
|
return FALSE;
|
|
}
|
|
not_a_tuner:
|
|
{
|
|
GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
|
|
(_("Device '%s' is not a tuner."),
|
|
v4l2object->videodev), GST_ERROR_SYSTEM);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_get_input (GstV4l2Object * v4l2object, gint * input)
|
|
{
|
|
GST_DEBUG_OBJECT (v4l2object->element, "trying to get radio input");
|
|
|
|
if (!GST_V4L2_IS_OPEN (v4l2object))
|
|
return FALSE;
|
|
|
|
if (!v4l2object->channels)
|
|
goto input_failed;
|
|
|
|
*input = 0;
|
|
|
|
GST_DEBUG_OBJECT (v4l2object->element, "input: %d", 0);
|
|
|
|
return TRUE;
|
|
|
|
/* ERRORS */
|
|
input_failed:
|
|
{
|
|
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
|
|
(_("Failed to get radio input on device '%s'. "),
|
|
v4l2object->videodev), GST_ERROR_SYSTEM);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_set_input (GstV4l2Object * v4l2object, gint input)
|
|
{
|
|
GST_DEBUG_OBJECT (v4l2object->element, "trying to set input to %d", input);
|
|
|
|
if (!GST_V4L2_IS_OPEN (v4l2object))
|
|
return FALSE;
|
|
|
|
if (!v4l2object->channels)
|
|
goto input_failed;
|
|
|
|
return TRUE;
|
|
|
|
/* ERRORS */
|
|
input_failed:
|
|
{
|
|
GST_ELEMENT_WARNING (v4l2object->element, RESOURCE, SETTINGS,
|
|
(_("Failed to set input %d on device %s."),
|
|
input, v4l2object->videodev), GST_ERROR_SYSTEM);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_set_mute_on (GstV4l2Radio * radio, gboolean on)
|
|
{
|
|
gint res;
|
|
struct v4l2_control vctrl;
|
|
|
|
GST_DEBUG_OBJECT (radio, "setting current tuner mute state: %d", on);
|
|
|
|
if (!GST_V4L2_IS_OPEN (radio->v4l2object))
|
|
return FALSE;
|
|
|
|
memset (&vctrl, 0, sizeof (vctrl));
|
|
vctrl.id = V4L2_CID_AUDIO_MUTE;
|
|
vctrl.value = on;
|
|
|
|
GST_DEBUG_OBJECT (radio, "radio fd: %d", radio->v4l2object->video_fd);
|
|
|
|
res = ioctl (radio->v4l2object->video_fd, VIDIOC_S_CTRL, &vctrl);
|
|
GST_DEBUG_OBJECT (radio, "mute state change result: %d", res);
|
|
if (res < 0)
|
|
goto freq_failed;
|
|
|
|
return TRUE;
|
|
|
|
/* ERRORS */
|
|
freq_failed:
|
|
{
|
|
GST_ELEMENT_WARNING (radio, RESOURCE, SETTINGS,
|
|
(_("Failed to change mute state for device '%s'."),
|
|
radio->v4l2object->videodev), GST_ERROR_SYSTEM);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_set_mute (GstV4l2Radio * radio)
|
|
{
|
|
return gst_v4l2radio_set_mute_on (radio, TRUE);
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_set_unmute (GstV4l2Radio * radio)
|
|
{
|
|
return gst_v4l2radio_set_mute_on (radio, FALSE);
|
|
}
|
|
|
|
GST_IMPLEMENT_V4L2_PROBE_METHODS (GstV4l2RadioClass, gst_v4l2radio);
|
|
GST_IMPLEMENT_V4L2_TUNER_METHODS (GstV4l2Radio, gst_v4l2radio);
|
|
|
|
static void gst_v4l2radio_uri_handler_init (gpointer g_iface,
|
|
gpointer iface_data);
|
|
|
|
static void
|
|
gst_v4l2radio_tuner_interface_reinit (GstTunerClass * iface)
|
|
{
|
|
gst_v4l2radio_tuner_interface_init (iface);
|
|
}
|
|
|
|
#define gst_v4l2radio_parent_class parent_class
|
|
G_DEFINE_TYPE_WITH_CODE (GstV4l2Radio, gst_v4l2radio, GST_TYPE_ELEMENT,
|
|
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
|
|
gst_v4l2radio_uri_handler_init);
|
|
G_IMPLEMENT_INTERFACE (GST_TYPE_TUNER,
|
|
gst_v4l2radio_tuner_interface_reinit);
|
|
G_IMPLEMENT_INTERFACE (GST_TYPE_PROPERTY_PROBE,
|
|
gst_v4l2radio_property_probe_interface_init));
|
|
|
|
static void gst_v4l2radio_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec);
|
|
static void gst_v4l2radio_get_property (GObject * object, guint prop_id,
|
|
GValue * value, GParamSpec * pspec);
|
|
static void gst_v4l2radio_finalize (GstV4l2Radio * radio);
|
|
static void gst_v4l2radio_dispose (GObject * object);
|
|
static GstStateChangeReturn gst_v4l2radio_change_state (GstElement * element,
|
|
GstStateChange transition);
|
|
|
|
static void
|
|
gst_v4l2radio_class_init (GstV4l2RadioClass * klass)
|
|
{
|
|
GObjectClass *gobject_class;
|
|
GstElementClass *gstelement_class;
|
|
|
|
gobject_class = (GObjectClass *) klass;
|
|
gstelement_class = (GstElementClass *) klass;
|
|
|
|
gobject_class->dispose = gst_v4l2radio_dispose;
|
|
gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2radio_finalize;
|
|
gobject_class->set_property = gst_v4l2radio_set_property;
|
|
gobject_class->get_property = gst_v4l2radio_get_property;
|
|
|
|
g_object_class_install_property (gobject_class, ARG_DEVICE,
|
|
g_param_spec_string ("device", "Radio device location",
|
|
"Video4Linux2 radio device location",
|
|
DEFAULT_PROP_DEVICE, G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (gobject_class, ARG_FREQUENCY,
|
|
g_param_spec_int ("frequency", "Station frequency",
|
|
"Station frequency in Hz",
|
|
MIN_FREQUENCY, MAX_FREQUENCY, DEFAULT_FREQUENCY, G_PARAM_READWRITE));
|
|
|
|
gstelement_class->change_state =
|
|
GST_DEBUG_FUNCPTR (gst_v4l2radio_change_state);
|
|
|
|
gst_element_class_set_details_simple (gstelement_class,
|
|
"Radio (video4linux2) Tuner",
|
|
"Tuner",
|
|
"Controls a Video4Linux2 radio device",
|
|
"Alexey Chernov <4ernov@gmail.com>");
|
|
|
|
klass->v4l2_class_devices = NULL;
|
|
|
|
GST_DEBUG_CATEGORY_INIT (v4l2radio_debug, "v4l2radio", 0,
|
|
"V4l2 radio element");
|
|
}
|
|
|
|
static void
|
|
gst_v4l2radio_init (GstV4l2Radio * filter)
|
|
{
|
|
filter->v4l2object = gst_v4l2_object_new (GST_ELEMENT (filter),
|
|
V4L2_BUF_TYPE_VIDEO_CAPTURE, DEFAULT_PROP_DEVICE,
|
|
gst_v4l2radio_get_input, gst_v4l2radio_set_input, NULL);
|
|
|
|
filter->v4l2object->frequency = DEFAULT_FREQUENCY;
|
|
g_free (filter->v4l2object->videodev);
|
|
filter->v4l2object->videodev = g_strdup (DEFAULT_PROP_DEVICE);
|
|
}
|
|
|
|
static void
|
|
gst_v4l2radio_dispose (GObject * object)
|
|
{
|
|
GstV4l2Radio *radio = GST_V4L2RADIO (object);
|
|
gst_v4l2_close (radio->v4l2object);
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gst_v4l2radio_finalize (GstV4l2Radio * radio)
|
|
{
|
|
gst_v4l2_object_destroy (radio->v4l2object);
|
|
G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (radio));
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_open (GstV4l2Radio * radio)
|
|
{
|
|
GstV4l2Object *v4l2object;
|
|
|
|
v4l2object = radio->v4l2object;
|
|
if (gst_v4l2_open (v4l2object))
|
|
return gst_v4l2radio_fill_channel_list (radio);
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gst_v4l2radio_set_defaults (GstV4l2Radio * radio)
|
|
{
|
|
GstV4l2Object *v4l2object;
|
|
GstTunerChannel *channel = NULL;
|
|
GstTuner *tuner;
|
|
|
|
v4l2object = radio->v4l2object;
|
|
|
|
if (!GST_IS_TUNER (v4l2object->element))
|
|
return;
|
|
|
|
tuner = GST_TUNER (v4l2object->element);
|
|
|
|
if (v4l2object->channel)
|
|
channel = gst_tuner_find_channel_by_name (tuner, v4l2object->channel);
|
|
if (channel) {
|
|
gst_tuner_set_channel (tuner, channel);
|
|
} else {
|
|
channel =
|
|
GST_TUNER_CHANNEL (gst_tuner_get_channel (GST_TUNER
|
|
(v4l2object->element)));
|
|
if (channel) {
|
|
g_free (v4l2object->channel);
|
|
v4l2object->channel = g_strdup (channel->label);
|
|
gst_tuner_channel_changed (tuner, channel);
|
|
}
|
|
}
|
|
|
|
if (channel
|
|
&& GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) {
|
|
if (v4l2object->frequency != 0) {
|
|
gst_tuner_set_frequency (tuner, channel, v4l2object->frequency);
|
|
} else {
|
|
v4l2object->frequency = gst_tuner_get_frequency (tuner, channel);
|
|
if (v4l2object->frequency == 0) {
|
|
/* guess */
|
|
gst_tuner_set_frequency (tuner, channel, MIN_FREQUENCY);
|
|
} else {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_start (GstV4l2Radio * radio)
|
|
{
|
|
if (!gst_v4l2radio_open (radio))
|
|
return FALSE;
|
|
|
|
gst_v4l2radio_set_defaults (radio);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_stop (GstV4l2Radio * radio)
|
|
{
|
|
if (!gst_v4l2_object_close (radio->v4l2object))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static GstStateChangeReturn
|
|
gst_v4l2radio_change_state (GstElement * element, GstStateChange transition)
|
|
{
|
|
GstV4l2Radio *radio;
|
|
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
|
|
|
radio = GST_V4L2RADIO (element);
|
|
switch (transition) {
|
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
|
/*start radio */
|
|
if (!gst_v4l2radio_start (radio))
|
|
ret = GST_STATE_CHANGE_FAILURE;
|
|
break;
|
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
|
/*unmute radio */
|
|
if (!gst_v4l2radio_set_unmute (radio))
|
|
ret = GST_STATE_CHANGE_FAILURE;
|
|
break;
|
|
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
|
/*mute radio */
|
|
if (!gst_v4l2radio_set_mute (radio))
|
|
ret = GST_STATE_CHANGE_FAILURE;
|
|
break;
|
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
|
/*stop radio */
|
|
if (!gst_v4l2radio_stop (radio))
|
|
ret = GST_STATE_CHANGE_FAILURE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
gst_v4l2radio_set_property (GObject * object, guint prop_id,
|
|
const GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstV4l2Radio *radio = GST_V4L2RADIO (object);
|
|
gint frequency;
|
|
switch (prop_id) {
|
|
case ARG_DEVICE:
|
|
g_free (radio->v4l2object->videodev);
|
|
radio->v4l2object->videodev =
|
|
g_strdup ((gchar *) g_value_get_string (value));
|
|
break;
|
|
case ARG_FREQUENCY:
|
|
frequency = g_value_get_int (value);
|
|
if (frequency >= MIN_FREQUENCY && frequency <= MAX_FREQUENCY) {
|
|
radio->v4l2object->frequency = frequency;
|
|
gst_v4l2_set_frequency (radio->v4l2object, 0,
|
|
radio->v4l2object->frequency);
|
|
}
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_v4l2radio_get_property (GObject * object, guint prop_id,
|
|
GValue * value, GParamSpec * pspec)
|
|
{
|
|
GstV4l2Radio *radio = GST_V4L2RADIO (object);
|
|
|
|
switch (prop_id) {
|
|
case ARG_DEVICE:
|
|
g_value_set_string (value, radio->v4l2object->videodev);
|
|
break;
|
|
case ARG_FREQUENCY:
|
|
if (gst_v4l2_get_frequency (radio->v4l2object,
|
|
0, &(radio->v4l2object->frequency)))
|
|
g_value_set_int (value, radio->v4l2object->frequency);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* GstURIHandler interface */
|
|
static GstURIType
|
|
gst_v4l2radio_uri_get_type (GType type)
|
|
{
|
|
return GST_URI_SRC;
|
|
}
|
|
|
|
static gchar **
|
|
gst_v4l2radio_uri_get_protocols (GType type)
|
|
{
|
|
static gchar *protocols[] = { (char *) "radio", NULL };
|
|
return protocols;
|
|
}
|
|
|
|
static const gchar *
|
|
gst_v4l2radio_uri_get_uri (GstURIHandler * handler)
|
|
{
|
|
GstV4l2Radio *radio = GST_V4L2RADIO (handler);
|
|
|
|
if (radio->v4l2object->videodev != NULL) {
|
|
if (gst_v4l2_get_frequency (radio->v4l2object,
|
|
0, &(radio->v4l2object->frequency))) {
|
|
gchar uri[20];
|
|
gchar freq[6];
|
|
g_ascii_formatd (freq, 6, "%4.1f", radio->v4l2object->frequency / 1e6);
|
|
g_snprintf (uri, sizeof (uri), "radio://%s", freq);
|
|
return g_intern_string (uri);
|
|
}
|
|
}
|
|
|
|
return "radio://";
|
|
}
|
|
|
|
static gboolean
|
|
gst_v4l2radio_uri_set_uri (GstURIHandler * handler, const gchar * uri)
|
|
{
|
|
GstV4l2Radio *radio = GST_V4L2RADIO (handler);
|
|
gdouble dfreq;
|
|
gint ifreq;
|
|
const gchar *freq;
|
|
gchar *end;
|
|
|
|
if (strcmp (uri, "radio://") != 0) {
|
|
freq = uri + 8;
|
|
|
|
dfreq = g_ascii_strtod (freq, &end);
|
|
|
|
if (errno || strlen (end))
|
|
goto uri_failed;
|
|
|
|
ifreq = dfreq * 1e6;
|
|
g_object_set (radio, "frequency", ifreq, NULL);
|
|
|
|
} else
|
|
goto uri_failed;
|
|
|
|
return TRUE;
|
|
|
|
uri_failed:
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gst_v4l2radio_uri_handler_init (gpointer g_iface, gpointer iface_data)
|
|
{
|
|
GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
|
|
|
|
iface->get_type = gst_v4l2radio_uri_get_type;
|
|
iface->get_protocols = gst_v4l2radio_uri_get_protocols;
|
|
iface->get_uri = gst_v4l2radio_uri_get_uri;
|
|
iface->set_uri = gst_v4l2radio_uri_set_uri;
|
|
}
|