Update everything for the removal of the interface library and mixer/tuner interfaces

This commit is contained in:
Sebastian Dröge 2012-04-13 13:04:12 +02:00
parent 71fc25849e
commit d99eb6d2cb
28 changed files with 1209 additions and 1297 deletions

View file

@ -79,7 +79,6 @@ EXTRA_HFILES = \
$(top_srcdir)/ext/taglib/gstid3v2mux.h \
$(top_srcdir)/ext/pulse/pulsesink.h \
$(top_srcdir)/ext/pulse/pulsesrc.h \
$(top_srcdir)/ext/pulse/pulsemixer.h \
$(top_srcdir)/ext/speex/gstspeexenc.h \
$(top_srcdir)/ext/speex/gstspeexdec.h \
$(top_srcdir)/ext/wavpack/gstwavpackdec.h \

View file

@ -2,9 +2,6 @@ plugin_LTLIBRARIES = libgstpulse.la
libgstpulse_la_SOURCES = \
plugin.c \
pulsemixer.c \
pulsemixerctrl.c \
pulsemixertrack.c \
pulseprobe.c \
pulsesink.c \
pulsesrc.c \
@ -12,15 +9,12 @@ libgstpulse_la_SOURCES = \
libgstpulse_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(PULSE_CFLAGS)
libgstpulse_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_API_VERSION) \
-lgstinterfaces-$(GST_API_VERSION) -lgstpbutils-$(GST_API_VERSION) \
-lgstpbutils-$(GST_API_VERSION) \
$(GST_BASE_LIBS) $(GST_LIBS) $(PULSE_LIBS)
libgstpulse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstpulse_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = \
pulsemixerctrl.h \
pulsemixer.h \
pulsemixertrack.h \
pulseprobe.h \
pulsesink.h \
pulsesrc.h \

View file

@ -27,7 +27,6 @@
#include "pulsesink.h"
#include "pulsesrc.h"
#include "pulsemixer.h"
GST_DEBUG_CATEGORY (pulse_debug);
@ -49,10 +48,6 @@ plugin_init (GstPlugin * plugin)
GST_TYPE_PULSESRC))
return FALSE;
if (!gst_element_register (plugin, "pulsemixer", GST_RANK_NONE,
GST_TYPE_PULSEMIXER))
return FALSE;
GST_DEBUG_CATEGORY_INIT (pulse_debug, "pulse", 0, "PulseAudio elements");
return TRUE;
}

View file

@ -1,232 +0,0 @@
/*
* GStreamer pulseaudio plugin
*
* Copyright (c) 2004-2008 Lennart Poettering
*
* gst-pulse 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.
*
* gst-pulse 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 gst-pulse; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
/**
* SECTION:element-pulsemixer
* @see_also: pulsesrc, pulsesink
*
* This element lets you adjust sound input and output levels for the
* PulseAudio sound server. It supports the GstMixer interface, which can be
* used to obtain a list of available mixer tracks. Set the mixer element to
* READY state before using the GstMixer interface on it.
*
* <refsect2>
* <title>Example pipelines</title>
* <para>
* pulsemixer can't be used in a sensible way in gst-launch.
* </para>
* </refsect2>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <stdio.h>
#include "pulsemixer.h"
enum
{
PROP_SERVER = 1,
PROP_DEVICE,
PROP_DEVICE_NAME
};
GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
#define GST_CAT_DEFAULT pulse_debug
static void gst_pulsemixer_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_pulsemixer_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_pulsemixer_finalize (GObject * object);
static GstStateChangeReturn gst_pulsemixer_change_state (GstElement * element,
GstStateChange transition);
GST_IMPLEMENT_PULSEMIXER_CTRL_METHODS (GstPulseMixer, gst_pulsemixer);
#define gst_pulsemixer_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstPulseMixer, gst_pulsemixer, GST_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (GST_TYPE_MIXER,
gst_pulsemixer_mixer_interface_init));
static void
gst_pulsemixer_class_init (GstPulseMixerClass * g_class)
{
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
GObjectClass *gobject_class = G_OBJECT_CLASS (g_class);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_pulsemixer_change_state);
gobject_class->finalize = gst_pulsemixer_finalize;
gobject_class->get_property = gst_pulsemixer_get_property;
gobject_class->set_property = gst_pulsemixer_set_property;
g_object_class_install_property (gobject_class,
PROP_SERVER,
g_param_spec_string ("server", "Server",
"The PulseAudio server to connect to", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_DEVICE,
g_param_spec_string ("device", "Device",
"The PulseAudio sink or source to control", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_DEVICE_NAME,
g_param_spec_string ("device-name", "Device name",
"Human-readable name of the sound device", NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (g_class),
"PulseAudio Mixer",
"Generic/Audio",
"Control sound input and output levels for PulseAudio",
"Lennart Poettering");
}
static void
gst_pulsemixer_init (GstPulseMixer * this)
{
this->mixer = NULL;
this->server = NULL;
this->device = NULL;
this->probe =
gst_pulseprobe_new (G_OBJECT (this), G_OBJECT_GET_CLASS (this),
PROP_DEVICE, this->device, TRUE, TRUE);
}
static void
gst_pulsemixer_finalize (GObject * object)
{
GstPulseMixer *this = GST_PULSEMIXER (object);
g_free (this->server);
g_free (this->device);
if (this->mixer) {
gst_pulsemixer_ctrl_free (this->mixer);
this->mixer = NULL;
}
if (this->probe) {
gst_pulseprobe_free (this->probe);
this->probe = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gst_pulsemixer_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstPulseMixer *this = GST_PULSEMIXER (object);
switch (prop_id) {
case PROP_SERVER:
g_free (this->server);
this->server = g_value_dup_string (value);
if (this->probe)
gst_pulseprobe_set_server (this->probe, this->server);
break;
case PROP_DEVICE:
g_free (this->device);
this->device = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_pulsemixer_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
GstPulseMixer *this = GST_PULSEMIXER (object);
switch (prop_id) {
case PROP_SERVER:
g_value_set_string (value, this->server);
break;
case PROP_DEVICE:
g_value_set_string (value, this->device);
break;
case PROP_DEVICE_NAME:
if (this->mixer) {
char *t = g_strdup_printf ("%s: %s",
this->mixer->type == GST_PULSEMIXER_SINK ? "Playback" : "Capture",
this->mixer->description);
g_value_take_string (value, t);
} else
g_value_set_string (value, NULL);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GstStateChangeReturn
gst_pulsemixer_change_state (GstElement * element, GstStateChange transition)
{
GstPulseMixer *this = GST_PULSEMIXER (element);
GstStateChangeReturn res;
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
if (!this->mixer)
this->mixer =
gst_pulsemixer_ctrl_new (G_OBJECT (this), this->server,
this->device, GST_PULSEMIXER_UNKNOWN);
break;
default:
;
}
res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_READY_TO_NULL:
if (this->mixer) {
gst_pulsemixer_ctrl_free (this->mixer);
this->mixer = NULL;
}
break;
default:
;
}
return res;
}

View file

@ -1,68 +0,0 @@
/*
* GStreamer pulseaudio plugin
*
* Copyright (c) 2004-2008 Lennart Poettering
*
* gst-pulse 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.
*
* gst-pulse 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 gst-pulse; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#ifndef __GST_PULSEMIXER_H__
#define __GST_PULSEMIXER_H__
#include <gst/gst.h>
#include <pulse/pulseaudio.h>
#include <pulse/thread-mainloop.h>
#include "pulsemixerctrl.h"
#include "pulseprobe.h"
G_BEGIN_DECLS
#define GST_TYPE_PULSEMIXER \
(gst_pulsemixer_get_type())
#define GST_PULSEMIXER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PULSEMIXER,GstPulseMixer))
#define GST_PULSEMIXER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PULSEMIXER,GstPulseMixerClass))
#define GST_IS_PULSEMIXER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PULSEMIXER))
#define GST_IS_PULSEMIXER_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PULSEMIXER))
typedef struct _GstPulseMixer GstPulseMixer;
typedef struct _GstPulseMixerClass GstPulseMixerClass;
struct _GstPulseMixer
{
GstElement parent;
gchar *server, *device;
GstPulseMixerCtrl *mixer;
GstPulseProbe *probe;
};
struct _GstPulseMixerClass
{
GstElementClass parent_class;
};
GType gst_pulsemixer_get_type (void);
G_END_DECLS
#endif /* __GST_PULSEMIXER_H__ */

View file

@ -1,640 +0,0 @@
/*-*- Mode: C; c-basic-offset: 2 -*-*/
/*
* GStreamer pulseaudio plugin
*
* Copyright (c) 2004-2008 Lennart Poettering
*
* gst-pulse 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.
*
* gst-pulse 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 gst-pulse; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include "pulsemixerctrl.h"
#include "pulsemixertrack.h"
#include "pulseutil.h"
GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
#define GST_CAT_DEFAULT pulse_debug
static void
gst_pulsemixer_ctrl_context_state_cb (pa_context * context, void *userdata)
{
GstPulseMixerCtrl *c = GST_PULSEMIXER_CTRL (userdata);
/* Called from the background thread! */
switch (pa_context_get_state (context)) {
case PA_CONTEXT_READY:
case PA_CONTEXT_TERMINATED:
case PA_CONTEXT_FAILED:
pa_threaded_mainloop_signal (c->mainloop, 0);
break;
case PA_CONTEXT_UNCONNECTED:
case PA_CONTEXT_CONNECTING:
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
}
}
static void
gst_pulsemixer_ctrl_sink_info_cb (pa_context * context, const pa_sink_info * i,
int eol, void *userdata)
{
GstPulseMixerCtrl *c = userdata;
gboolean vol_chg = FALSE;
gboolean old_mute;
/* Called from the background thread! */
if (c->outstandig_queries > 0)
c->outstandig_queries--;
if (c->ignore_queries > 0 || c->time_event) {
if (c->ignore_queries > 0)
c->ignore_queries--;
return;
}
if (!i && eol < 0) {
c->operation_success = FALSE;
pa_threaded_mainloop_signal (c->mainloop, 0);
return;
}
if (eol)
return;
g_free (c->name);
g_free (c->description);
c->name = g_strdup (i->name);
c->description = g_strdup (i->description);
c->index = i->index;
c->channel_map = i->channel_map;
vol_chg = !pa_cvolume_equal (&c->volume, &i->volume);
c->volume = i->volume;
old_mute = c->muted;
c->muted = !!i->mute;
c->type = GST_PULSEMIXER_SINK;
if (c->track) {
GstMixerTrackFlags flags = c->track->flags;
flags =
(flags & ~GST_MIXER_TRACK_MUTE) | (c->muted ? GST_MIXER_TRACK_MUTE : 0);
c->track->flags = flags;
}
c->operation_success = TRUE;
pa_threaded_mainloop_signal (c->mainloop, 0);
if (vol_chg && c->track) {
gint volumes[PA_CHANNELS_MAX];
gint i;
for (i = 0; i < c->volume.channels; i++)
volumes[i] = (gint) (c->volume.values[i]);
GST_LOG_OBJECT (c->object, "Sending volume change notification");
gst_mixer_volume_changed (GST_MIXER (c->object), c->track, volumes);
}
if ((c->muted != old_mute) && c->track) {
GST_LOG_OBJECT (c->object, "Sending mute toggled notification");
gst_mixer_mute_toggled (GST_MIXER (c->object), c->track, c->muted);
}
}
static void
gst_pulsemixer_ctrl_source_info_cb (pa_context * context,
const pa_source_info * i, int eol, void *userdata)
{
GstPulseMixerCtrl *c = userdata;
gboolean vol_chg = FALSE;
gboolean old_mute;
/* Called from the background thread! */
if (c->outstandig_queries > 0)
c->outstandig_queries--;
if (c->ignore_queries > 0 || c->time_event) {
if (c->ignore_queries > 0)
c->ignore_queries--;
return;
}
if (!i && eol < 0) {
c->operation_success = FALSE;
pa_threaded_mainloop_signal (c->mainloop, 0);
return;
}
if (eol)
return;
g_free (c->name);
g_free (c->description);
c->name = g_strdup (i->name);
c->description = g_strdup (i->description);
c->index = i->index;
c->channel_map = i->channel_map;
vol_chg = !pa_cvolume_equal (&c->volume, &i->volume);
c->volume = i->volume;
old_mute = c->muted;
c->muted = !!i->mute;
c->type = GST_PULSEMIXER_SOURCE;
if (c->track) {
GstMixerTrackFlags flags = c->track->flags;
flags =
(flags & ~GST_MIXER_TRACK_MUTE) | (c->muted ? GST_MIXER_TRACK_MUTE : 0);
c->track->flags = flags;
}
c->operation_success = TRUE;
pa_threaded_mainloop_signal (c->mainloop, 0);
if (vol_chg && c->track) {
gint volumes[PA_CHANNELS_MAX];
gint i;
for (i = 0; i < c->volume.channels; i++)
volumes[i] = (gint) (c->volume.values[i]);
GST_LOG_OBJECT (c->object, "Sending volume change notification");
gst_mixer_volume_changed (GST_MIXER (c->object), c->track, volumes);
}
if ((c->muted != old_mute) && c->track) {
GST_LOG_OBJECT (c->object, "Sending mute toggled notification");
gst_mixer_mute_toggled (GST_MIXER (c->object), c->track, c->muted);
}
}
static void
gst_pulsemixer_ctrl_subscribe_cb (pa_context * context,
pa_subscription_event_type_t t, uint32_t idx, void *userdata)
{
GstPulseMixerCtrl *c = GST_PULSEMIXER_CTRL (userdata);
pa_operation *o = NULL;
/* Called from the background thread! */
if (c->index != idx)
return;
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_CHANGE)
return;
if (c->type == GST_PULSEMIXER_SINK)
o = pa_context_get_sink_info_by_index (c->context, c->index,
gst_pulsemixer_ctrl_sink_info_cb, c);
else
o = pa_context_get_source_info_by_index (c->context, c->index,
gst_pulsemixer_ctrl_source_info_cb, c);
if (!o) {
GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s",
pa_strerror (pa_context_errno (c->context)));
return;
}
pa_operation_unref (o);
c->outstandig_queries++;
}
static void
gst_pulsemixer_ctrl_success_cb (pa_context * context, int success,
void *userdata)
{
GstPulseMixerCtrl *c = (GstPulseMixerCtrl *) userdata;
c->operation_success = !!success;
pa_threaded_mainloop_signal (c->mainloop, 0);
}
#define CHECK_DEAD_GOTO(c, label) \
G_STMT_START { \
if (!(c)->context || \
!PA_CONTEXT_IS_GOOD(pa_context_get_state((c)->context))) { \
GST_WARNING_OBJECT ((c)->object, "Not connected: %s", \
(c)->context ? pa_strerror(pa_context_errno((c)->context)) : "NULL"); \
goto label; \
} \
} G_STMT_END
static gboolean
gst_pulsemixer_ctrl_open (GstPulseMixerCtrl * c)
{
int e;
gchar *name;
pa_operation *o = NULL;
g_assert (c);
GST_DEBUG_OBJECT (c->object, "ctrl open");
c->mainloop = pa_threaded_mainloop_new ();
if (!c->mainloop)
return FALSE;
e = pa_threaded_mainloop_start (c->mainloop);
if (e < 0)
return FALSE;
name = gst_pulse_client_name ();
pa_threaded_mainloop_lock (c->mainloop);
if (!(c->context =
pa_context_new (pa_threaded_mainloop_get_api (c->mainloop), name))) {
GST_WARNING_OBJECT (c->object, "Failed to create context");
goto unlock_and_fail;
}
pa_context_set_state_callback (c->context,
gst_pulsemixer_ctrl_context_state_cb, c);
pa_context_set_subscribe_callback (c->context,
gst_pulsemixer_ctrl_subscribe_cb, c);
if (pa_context_connect (c->context, c->server, 0, NULL) < 0) {
GST_WARNING_OBJECT (c->object, "Failed to connect context: %s",
pa_strerror (pa_context_errno (c->context)));
goto unlock_and_fail;
}
/* Wait until the context is ready */
while (pa_context_get_state (c->context) != PA_CONTEXT_READY) {
CHECK_DEAD_GOTO (c, unlock_and_fail);
pa_threaded_mainloop_wait (c->mainloop);
}
/* Subscribe to events */
if (!(o =
pa_context_subscribe (c->context,
PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE,
gst_pulsemixer_ctrl_success_cb, c))) {
GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s",
pa_strerror (pa_context_errno (c->context)));
goto unlock_and_fail;
}
c->operation_success = FALSE;
while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
CHECK_DEAD_GOTO (c, unlock_and_fail);
pa_threaded_mainloop_wait (c->mainloop);
}
if (!c->operation_success) {
GST_WARNING_OBJECT (c->object, "Failed to subscribe to events: %s",
pa_strerror (pa_context_errno (c->context)));
goto unlock_and_fail;
}
pa_operation_unref (o);
o = NULL;
/* Get sink info */
if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SINK) {
GST_WARNING_OBJECT (c->object, "Get info for '%s'", c->device);
if (!(o =
pa_context_get_sink_info_by_name (c->context, c->device,
gst_pulsemixer_ctrl_sink_info_cb, c))) {
GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s",
pa_strerror (pa_context_errno (c->context)));
goto unlock_and_fail;
}
c->operation_success = FALSE;
while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
CHECK_DEAD_GOTO (c, unlock_and_fail);
pa_threaded_mainloop_wait (c->mainloop);
}
pa_operation_unref (o);
o = NULL;
if (!c->operation_success && (c->type == GST_PULSEMIXER_SINK
|| pa_context_errno (c->context) != PA_ERR_NOENTITY)) {
GST_WARNING_OBJECT (c->object, "Failed to get sink info: %s",
pa_strerror (pa_context_errno (c->context)));
goto unlock_and_fail;
}
}
if (c->type == GST_PULSEMIXER_UNKNOWN || c->type == GST_PULSEMIXER_SOURCE) {
if (!(o =
pa_context_get_source_info_by_name (c->context, c->device,
gst_pulsemixer_ctrl_source_info_cb, c))) {
GST_WARNING_OBJECT (c->object, "Failed to get source info: %s",
pa_strerror (pa_context_errno (c->context)));
goto unlock_and_fail;
}
c->operation_success = FALSE;
while (pa_operation_get_state (o) != PA_OPERATION_DONE) {
CHECK_DEAD_GOTO (c, unlock_and_fail);
pa_threaded_mainloop_wait (c->mainloop);
}
pa_operation_unref (o);
o = NULL;
if (!c->operation_success) {
GST_WARNING_OBJECT (c->object, "Failed to get source info: %s",
pa_strerror (pa_context_errno (c->context)));
goto unlock_and_fail;
}
}
g_assert (c->type != GST_PULSEMIXER_UNKNOWN);
c->track = gst_pulsemixer_track_new (c);
c->tracklist = g_list_append (c->tracklist, c->track);
pa_threaded_mainloop_unlock (c->mainloop);
g_free (name);
return TRUE;
unlock_and_fail:
if (o)
pa_operation_unref (o);
if (c->mainloop)
pa_threaded_mainloop_unlock (c->mainloop);
g_free (name);
return FALSE;
}
static void
gst_pulsemixer_ctrl_close (GstPulseMixerCtrl * c)
{
g_assert (c);
GST_DEBUG_OBJECT (c->object, "ctrl close");
if (c->mainloop)
pa_threaded_mainloop_stop (c->mainloop);
if (c->context) {
pa_context_disconnect (c->context);
pa_context_unref (c->context);
c->context = NULL;
}
if (c->mainloop) {
pa_threaded_mainloop_free (c->mainloop);
c->mainloop = NULL;
c->time_event = NULL;
}
if (c->tracklist) {
g_list_free (c->tracklist);
c->tracklist = NULL;
}
if (c->track) {
GST_PULSEMIXER_TRACK (c->track)->control = NULL;
g_object_unref (c->track);
c->track = NULL;
}
}
GstPulseMixerCtrl *
gst_pulsemixer_ctrl_new (GObject * object, const gchar * server,
const gchar * device, GstPulseMixerType type)
{
GstPulseMixerCtrl *c = NULL;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE_TYPE ((object),
GST_TYPE_MIXER), c);
GST_DEBUG_OBJECT (object, "new mixer ctrl for %s", device);
c = g_new (GstPulseMixerCtrl, 1);
c->object = g_object_ref (object);
c->tracklist = NULL;
c->server = g_strdup (server);
c->device = g_strdup (device);
c->mainloop = NULL;
c->context = NULL;
c->track = NULL;
c->ignore_queries = c->outstandig_queries = 0;
pa_cvolume_mute (&c->volume, PA_CHANNELS_MAX);
pa_channel_map_init (&c->channel_map);
c->muted = FALSE;
c->index = PA_INVALID_INDEX;
c->type = type;
c->name = NULL;
c->description = NULL;
c->time_event = NULL;
c->update_volume = c->update_mute = FALSE;
if (!(gst_pulsemixer_ctrl_open (c))) {
gst_pulsemixer_ctrl_free (c);
return NULL;
}
return c;
}
void
gst_pulsemixer_ctrl_free (GstPulseMixerCtrl * c)
{
g_assert (c);
gst_pulsemixer_ctrl_close (c);
g_free (c->server);
g_free (c->device);
g_free (c->name);
g_free (c->description);
g_object_unref (c->object);
g_free (c);
}
const GList *
gst_pulsemixer_ctrl_list_tracks (GstPulseMixerCtrl * c)
{
g_assert (c);
return c->tracklist;
}
static void
gst_pulsemixer_ctrl_timeout_event (pa_mainloop_api * a, pa_time_event * e,
const struct timeval *tv, void *userdata)
{
pa_operation *o;
GstPulseMixerCtrl *c = GST_PULSEMIXER_CTRL (userdata);
if (c->update_volume) {
if (c->type == GST_PULSEMIXER_SINK)
o = pa_context_set_sink_volume_by_index (c->context, c->index, &c->volume,
NULL, NULL);
else
o = pa_context_set_source_volume_by_index (c->context, c->index,
&c->volume, NULL, NULL);
if (!o)
GST_WARNING_OBJECT (c->object, "Failed to set device volume: %s",
pa_strerror (pa_context_errno (c->context)));
else
pa_operation_unref (o);
c->update_volume = FALSE;
}
if (c->update_mute) {
if (c->type == GST_PULSEMIXER_SINK)
o = pa_context_set_sink_mute_by_index (c->context, c->index, c->muted,
NULL, NULL);
else
o = pa_context_set_source_mute_by_index (c->context, c->index, c->muted,
NULL, NULL);
if (!o)
GST_WARNING_OBJECT (c->object, "Failed to set device mute: %s",
pa_strerror (pa_context_errno (c->context)));
else
pa_operation_unref (o);
c->update_mute = FALSE;
}
/* Make sure that all outstanding queries are being ignored */
c->ignore_queries = c->outstandig_queries;
g_assert (e == c->time_event);
a->time_free (e);
c->time_event = NULL;
}
#define UPDATE_DELAY 50000
static void
restart_time_event (GstPulseMixerCtrl * c)
{
struct timeval tv;
pa_mainloop_api *api;
g_assert (c);
if (c->time_event)
return;
/* Updating the volume too often will cause a lot of traffic
* when accessing a networked server. Therefore we make sure
* to update the volume only once every 50ms */
api = pa_threaded_mainloop_get_api (c->mainloop);
c->time_event =
api->time_new (api, pa_timeval_add (pa_gettimeofday (&tv), UPDATE_DELAY),
gst_pulsemixer_ctrl_timeout_event, c);
}
void
gst_pulsemixer_ctrl_set_volume (GstPulseMixerCtrl * c, GstMixerTrack * track,
gint * volumes)
{
pa_cvolume v;
int i;
g_assert (c);
g_assert (track == c->track);
pa_threaded_mainloop_lock (c->mainloop);
for (i = 0; i < c->channel_map.channels; i++)
v.values[i] = (pa_volume_t) volumes[i];
v.channels = c->channel_map.channels;
c->volume = v;
c->update_volume = TRUE;
restart_time_event (c);
pa_threaded_mainloop_unlock (c->mainloop);
}
void
gst_pulsemixer_ctrl_get_volume (GstPulseMixerCtrl * c, GstMixerTrack * track,
gint * volumes)
{
int i;
g_assert (c);
g_assert (track == c->track);
pa_threaded_mainloop_lock (c->mainloop);
for (i = 0; i < c->channel_map.channels; i++)
volumes[i] = c->volume.values[i];
pa_threaded_mainloop_unlock (c->mainloop);
}
void
gst_pulsemixer_ctrl_set_record (GstPulseMixerCtrl * c, GstMixerTrack * track,
gboolean record)
{
g_assert (c);
g_assert (track == c->track);
}
void
gst_pulsemixer_ctrl_set_mute (GstPulseMixerCtrl * c, GstMixerTrack * track,
gboolean mute)
{
g_assert (c);
g_assert (track == c->track);
pa_threaded_mainloop_lock (c->mainloop);
c->muted = mute;
c->update_mute = TRUE;
if (c->track) {
GstMixerTrackFlags flags = c->track->flags;
flags =
(flags & ~GST_MIXER_TRACK_MUTE) | (c->muted ? GST_MIXER_TRACK_MUTE : 0);
c->track->flags = flags;
}
restart_time_event (c);
pa_threaded_mainloop_unlock (c->mainloop);
}
GstMixerFlags
gst_pulsemixer_ctrl_get_mixer_flags (GstPulseMixerCtrl * mixer)
{
return GST_MIXER_FLAG_AUTO_NOTIFICATIONS;
}

View file

@ -1,179 +0,0 @@
/*-*- Mode: C; c-basic-offset: 2 -*-*/
/*
* GStreamer pulseaudio plugin
*
* Copyright (c) 2004-2008 Lennart Poettering
*
* gst-pulse 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.
*
* gst-pulse 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 gst-pulse; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#ifndef __GST_PULSEMIXERCTRL_H__
#define __GST_PULSEMIXERCTRL_H__
#include <gst/gst.h>
#include <gst/audio/mixer.h>
#include <pulse/pulseaudio.h>
#include <pulse/thread-mainloop.h>
G_BEGIN_DECLS
#define GST_PULSEMIXER_CTRL(obj) ((GstPulseMixerCtrl*)(obj))
typedef struct _GstPulseMixerCtrl GstPulseMixerCtrl;
typedef enum
{
GST_PULSEMIXER_UNKNOWN,
GST_PULSEMIXER_SINK,
GST_PULSEMIXER_SOURCE
} GstPulseMixerType;
struct _GstPulseMixerCtrl
{
GObject *object;
GList *tracklist;
gchar *server, *device;
pa_threaded_mainloop *mainloop;
pa_context *context;
gchar *name, *description;
pa_channel_map channel_map;
pa_cvolume volume;
gboolean muted:1;
gboolean update_volume:1;
gboolean update_mute:1;
gboolean operation_success:1;
guint32 index;
GstPulseMixerType type;
GstMixerTrack *track;
pa_time_event *time_event;
int outstandig_queries;
int ignore_queries;
};
GstPulseMixerCtrl *gst_pulsemixer_ctrl_new (GObject *object, const gchar * server,
const gchar * device, GstPulseMixerType type);
void gst_pulsemixer_ctrl_free (GstPulseMixerCtrl * mixer);
const GList *gst_pulsemixer_ctrl_list_tracks (GstPulseMixerCtrl * mixer);
void gst_pulsemixer_ctrl_set_volume (GstPulseMixerCtrl * mixer,
GstMixerTrack * track, gint * volumes);
void gst_pulsemixer_ctrl_get_volume (GstPulseMixerCtrl * mixer,
GstMixerTrack * track, gint * volumes);
void gst_pulsemixer_ctrl_set_mute (GstPulseMixerCtrl * mixer,
GstMixerTrack * track, gboolean mute);
void gst_pulsemixer_ctrl_set_record (GstPulseMixerCtrl * mixer,
GstMixerTrack * track, gboolean record);
GstMixerFlags gst_pulsemixer_ctrl_get_mixer_flags (GstPulseMixerCtrl * mixer);
#define GST_IMPLEMENT_PULSEMIXER_CTRL_METHODS(Type, interface_as_function) \
static const GList* \
interface_as_function ## _list_tracks (GstMixer * mixer) \
{ \
Type *this = (Type*) mixer; \
\
g_return_val_if_fail (this != NULL, NULL); \
g_return_val_if_fail (this->mixer != NULL, NULL); \
\
return gst_pulsemixer_ctrl_list_tracks (this->mixer); \
} \
static void \
interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track, \
gint * volumes) \
{ \
Type *this = (Type*) mixer; \
\
g_return_if_fail (this != NULL); \
g_return_if_fail (this->mixer != NULL); \
\
gst_pulsemixer_ctrl_set_volume (this->mixer, track, volumes); \
} \
static void \
interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track, \
gint * volumes) \
{ \
Type *this = (Type*) mixer; \
\
g_return_if_fail (this != NULL); \
g_return_if_fail (this->mixer != NULL); \
\
gst_pulsemixer_ctrl_get_volume (this->mixer, track, volumes); \
} \
static void \
interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track, \
gboolean record) \
{ \
Type *this = (Type*) mixer; \
\
g_return_if_fail (this != NULL); \
g_return_if_fail (this->mixer != NULL); \
\
gst_pulsemixer_ctrl_set_record (this->mixer, track, record); \
} \
static void \
interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track, \
gboolean mute) \
{ \
Type *this = (Type*) mixer; \
\
g_return_if_fail (this != NULL); \
g_return_if_fail (this->mixer != NULL); \
\
gst_pulsemixer_ctrl_set_mute (this->mixer, track, mute); \
} \
static GstMixerFlags \
interface_as_function ## _get_mixer_flags (GstMixer * mixer) \
{ \
Type *this = (Type*) mixer; \
\
g_return_val_if_fail (this != NULL, GST_MIXER_FLAG_NONE); \
g_return_val_if_fail (this->mixer != NULL, GST_MIXER_FLAG_NONE); \
\
return gst_pulsemixer_ctrl_get_mixer_flags (this->mixer); \
} \
static GstMixerType \
interface_as_function ## _get_mixer_type (GstMixer * mixer) \
{ \
return GST_MIXER_HARDWARE; \
} \
static void \
interface_as_function ## _mixer_interface_init (GstMixerInterface * iface) \
{ \
iface->list_tracks = interface_as_function ## _list_tracks; \
iface->set_volume = interface_as_function ## _set_volume; \
iface->get_volume = interface_as_function ## _get_volume; \
iface->set_mute = interface_as_function ## _set_mute; \
iface->set_record = interface_as_function ## _set_record; \
iface->get_mixer_flags = interface_as_function ## _get_mixer_flags; \
iface->get_mixer_type = interface_as_function ## _get_mixer_type; \
}
G_END_DECLS
#endif

View file

@ -1,67 +0,0 @@
/*
* GStreamer pulseaudio plugin
*
* Copyright (c) 2004-2008 Lennart Poettering
*
* gst-pulse 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.
*
* gst-pulse 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 gst-pulse; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include "pulsemixertrack.h"
GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
#define GST_CAT_DEFAULT pulse_debug
G_DEFINE_TYPE (GstPulseMixerTrack, gst_pulsemixer_track, GST_TYPE_MIXER_TRACK);
static void
gst_pulsemixer_track_class_init (GstPulseMixerTrackClass * klass)
{
}
static void
gst_pulsemixer_track_init (GstPulseMixerTrack * track)
{
track->control = NULL;
}
GstMixerTrack *
gst_pulsemixer_track_new (GstPulseMixerCtrl * control)
{
GstPulseMixerTrack *pulsetrack;
GstMixerTrack *track;
pulsetrack = g_object_new (GST_TYPE_PULSEMIXER_TRACK, NULL);
pulsetrack->control = control;
track = GST_MIXER_TRACK (pulsetrack);
track->label = g_strdup ("Master");
track->num_channels = control->channel_map.channels;
track->flags =
(control->type ==
GST_PULSEMIXER_SINK ? GST_MIXER_TRACK_OUTPUT | GST_MIXER_TRACK_MASTER :
GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_RECORD) | (control->muted ?
GST_MIXER_TRACK_MUTE : 0);
track->min_volume = PA_VOLUME_MUTED;
track->max_volume = PA_VOLUME_NORM;
return track;
}

View file

@ -1,60 +0,0 @@
/*
* GStreamer pulseaudio plugin
*
* Copyright (c) 2004-2008 Lennart Poettering
*
* gst-pulse 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.
*
* gst-pulse 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 gst-pulse; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
#ifndef __GST_PULSEMIXERTRACK_H__
#define __GST_PULSEMIXERTRACK_H__
#include <gst/gst.h>
#include "pulsemixerctrl.h"
G_BEGIN_DECLS
#define GST_TYPE_PULSEMIXER_TRACK \
(gst_pulsemixer_track_get_type())
#define GST_PULSEMIXER_TRACK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_PULSEMIXER_TRACK, GstPulseMixerTrack))
#define GST_PULSEMIXER_TRACK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_PULSEMIXER_TRACK, GstPulseMixerTrackClass))
#define GST_IS_PULSEMIXER_TRACK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_PULSEMIXER_TRACK))
#define GST_IS_PULSEMIXER_TRACK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_PULSEMIXER_TRACK))
typedef struct _GstPulseMixerTrack
{
GstMixerTrack parent;
GstPulseMixerCtrl *control;
} GstPulseMixerTrack;
typedef struct _GstPulseMixerTrackClass
{
GstMixerTrackClass parent;
} GstPulseMixerTrackClass;
GType gst_pulsemixer_track_get_type (void);
GstMixerTrack *gst_pulsemixer_track_new (GstPulseMixerCtrl * control);
G_END_DECLS
#endif

View file

@ -23,7 +23,7 @@
/**
* SECTION:element-pulsesink
* @see_also: pulsesrc, pulsemixer
* @see_also: pulsesrc
*
* This element outputs audio to a
* <ulink href="http://www.pulseaudio.org">PulseAudio sound server</ulink>.

View file

@ -21,7 +21,7 @@
/**
* SECTION:element-pulsesrc
* @see_also: pulsesink, pulsemixer
* @see_also: pulsesink
*
* This element captures audio from a
* <ulink href="http://www.pulseaudio.org">PulseAudio sound server</ulink>.
@ -47,7 +47,6 @@
#include "pulsesrc.h"
#include "pulseutil.h"
#include "pulsemixerctrl.h"
GST_DEBUG_CATEGORY_EXTERN (pulse_debug);
#define GST_CAT_DEFAULT pulse_debug
@ -127,11 +126,8 @@ static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("src",
);
GST_IMPLEMENT_PULSEMIXER_CTRL_METHODS (GstPulseSrc, gst_pulsesrc);
#define gst_pulsesrc_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstPulseSrc, gst_pulsesrc, GST_TYPE_AUDIO_SRC,
G_IMPLEMENT_INTERFACE (GST_TYPE_MIXER, gst_pulsesrc_mixer_interface_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL));
static void
@ -287,8 +283,6 @@ gst_pulsesrc_init (GstPulseSrc * pulsesrc)
pulsesrc->notify = 0;
pulsesrc->mixer = NULL;
pulsesrc->properties = NULL;
pulsesrc->proplist = NULL;
@ -348,11 +342,6 @@ gst_pulsesrc_finalize (GObject * object)
if (pulsesrc->proplist)
pa_proplist_free (pulsesrc->proplist);
if (pulsesrc->mixer) {
gst_pulsemixer_ctrl_free (pulsesrc->mixer);
pulsesrc->mixer = NULL;
}
if (pulsesrc->probe) {
gst_pulseprobe_free (pulsesrc->probe);
pulsesrc->probe = NULL;
@ -1616,11 +1605,6 @@ gst_pulsesrc_change_state (GstElement * element, GstStateChange transition)
this->mainloop = NULL;
goto mainloop_start_failed;
}
if (!this->mixer)
this->mixer =
gst_pulsemixer_ctrl_new (G_OBJECT (this), this->server,
this->device, GST_PULSEMIXER_SOURCE);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
/* uncork and start recording */
@ -1645,11 +1629,6 @@ gst_pulsesrc_change_state (GstElement * element, GstStateChange transition)
gst_pulsesrc_pause (this);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
if (this->mixer) {
gst_pulsemixer_ctrl_free (this->mixer);
this->mixer = NULL;
}
if (this->mainloop)
pa_threaded_mainloop_stop (this->mainloop);

View file

@ -30,7 +30,6 @@
#include <pulse/pulseaudio.h>
#include <pulse/thread-mainloop.h>
#include "pulsemixerctrl.h"
#include "pulseprobe.h"
G_BEGIN_DECLS
@ -69,7 +68,6 @@ struct _GstPulseSrc
size_t read_buffer_length;
gchar *device_description;
GstPulseMixerCtrl *mixer;
GstPulseProbe *probe;
gdouble volume;

View file

@ -5,7 +5,6 @@ libgstrtsp_la_SOURCES = gstrtsp.c gstrtspsrc.c \
libgstrtsp_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
libgstrtsp_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) \
-lgstinterfaces-@GST_API_VERSION@ \
-lgstrtp-@GST_API_VERSION@ -lgstrtsp-@GST_API_VERSION@ \
-lgstsdp-@GST_API_VERSION@ $(GST_LIBS)
libgstrtsp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)

View file

@ -8,17 +8,42 @@ xv_source =
xv_libs =
endif
# variables used for enum/marshal generation
glib_enum_headers = tuner.h tunernorm.h tunerchannel.h
glib_enum_define = GST_INTERFACES
glib_gen_prefix = gst_interfaces
glib_gen_basename = tuner
built_sources = \
tuner-marshal.c \
tuner-enumtypes.c
built_headers = \
tuner-marshal.h \
tuner-enumtypes.h
EXTRA_DIST = tuner-marshal.list
CLEANFILES = $(built_sources) $(built_headers)
include $(top_srcdir)/common/gst-glib-gen.mak
libgstvideo4linux2_la_SOURCES = gstv4l2.c \
gstv4l2colorbalance.c \
gstv4l2object.c \
gstv4l2bufferpool.c \
gstv4l2sink.c \
gstv4l2src.c \
gstv4l2radio.c \
gstv4l2tuner.c \
gstv4l2vidorient.c \
v4l2_calls.c \
tuner.c \
tunerchannel.c \
tunernorm.c \
$(xv_source)
libgstvideo4linux2_la_SOURCES += gstv4l2sink.c
nodist_libgstvideo4linux2_la_SOURCES = $(built_sources) $(built_headers)
libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) \
@ -34,7 +59,6 @@ libgstvideo4linux2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
$(GST_BASE_LIBS) \
$(GST_PLUGINS_BASE_LIBS) \
-lgstvideo-$(GST_API_VERSION) \
-lgstinterfaces-$(GST_API_VERSION) \
$(GST_LIBS) \
$(xv_libs) \
$(LIBV4L2_LIBS) \
@ -50,4 +74,8 @@ noinst_HEADERS = \
gstv4l2tuner.h \
gstv4l2vidorient.h \
gstv4l2videooverlay.h \
v4l2_calls.h
v4l2_calls.h \
tuner.h \
tunerchannel.h \
tunernorm.h

View file

@ -25,8 +25,8 @@
#define __GST_V4L2_TUNER_H__
#include <gst/gst.h>
#include <gst/interfaces/tuner.h>
#include "tuner.h"
#include "gstv4l2object.h"
G_BEGIN_DECLS

View file

@ -34,7 +34,7 @@
/* for XkbKeycodeToKeysym */
#include <X11/XKBlib.h>
#include <gst/interfaces/navigation.h>
#include <gst/video/navigation.h>
#include "gstv4l2videooverlay.h"
#include "gstv4l2object.h"

View file

@ -26,7 +26,7 @@
#include <X11/X.h>
#include <gst/gst.h>
#include <gst/interfaces/navigation.h>
#include <gst/video/navigation.h>
#include <gst/video/gstvideosink.h> /* for GstVideoRectange */
#include <gst/video/videooverlay.h>

View file

@ -0,0 +1,2 @@
VOID:OBJECT,ULONG
VOID:OBJECT,INT

577
sys/v4l2/tuner.c Normal file
View file

@ -0,0 +1,577 @@
/* GStreamer Tuner
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* tuner.c: tuner design virtual class function wrappers
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tuner.h"
#include "tuner-marshal.h"
#include <string.h>
/**
* SECTION:gsttuner
* @short_description: Interface for elements providing tuner operations
*
* <refsect2>
* <para>
* The GstTuner interface is provided by elements that have the ability to
* tune into multiple input signals, for example TV or radio capture cards.
* </para><para>
* The interpretation of 'tuning into' an input stream depends on the element
* implementing the interface. For v4lsrc, it might imply selection of an
* input source and/or frequency to be configured on a TV card. Another
* GstTuner implementation might be to allow selection of an active input pad
* from multiple input pads.
* </para><para>
* That said, the GstTuner interface functions are biased toward the
* TV capture scenario.
* </para><para>
* The general parameters provided are for configuration are:
* <itemizedlist>
* <listitem>Selection of a current #GstTunerChannel. The current channel
* represents the input source (e.g. Composite, S-Video etc for TV capture).
* </listitem>
* <listitem>The #GstTunerNorm for the channel. The norm chooses the
* interpretation of the incoming signal for the current channel. For example,
* PAL or NTSC, or more specific variants there-of.
* </listitem>
* <listitem>Channel frequency. If the current channel has the ability to tune
* between multiple frequencies (if it has the GST_TUNER_CHANNEL_FREQUENCY flag)
* then the frequency can be changed/retrieved via the
* gst_tuner_set_frequency() and gst_tuner_get_frequency() methods.
* </listitem>
* </itemizedlist>
* </para>
* <para>
* Where applicable, the signal strength can be retrieved and/or monitored
* via a signal.
* </para>
* </refsect2>
*/
/* FIXME 0.11: check if we need to add API for sometimes-supportedness
* (aka making up for GstImplementsInterface removal) */
/* FIXME 0.11: replace signals with messages (+ make API thread-safe) */
enum
{
NORM_CHANGED,
CHANNEL_CHANGED,
FREQUENCY_CHANGED,
SIGNAL_CHANGED,
LAST_SIGNAL
};
static void gst_tuner_class_init (GstTunerInterface * iface);
static guint gst_tuner_signals[LAST_SIGNAL] = { 0 };
GType
gst_tuner_get_type (void)
{
static GType gst_tuner_type = 0;
if (!gst_tuner_type) {
static const GTypeInfo gst_tuner_info = {
sizeof (GstTunerInterface),
(GBaseInitFunc) gst_tuner_class_init,
NULL,
NULL,
NULL,
NULL,
0,
0,
NULL,
};
gst_tuner_type = g_type_register_static (G_TYPE_INTERFACE,
"GstTuner", &gst_tuner_info, 0);
}
return gst_tuner_type;
}
static void
gst_tuner_class_init (GstTunerInterface * iface)
{
static gboolean initialized = FALSE;
if (!initialized) {
/**
* GstTuner::norm-changed:
* @tuner: The element providing the GstTuner interface
* @norm: The new configured norm.
*
* Reports that the current #GstTunerNorm has changed.
*/
gst_tuner_signals[NORM_CHANGED] =
g_signal_new ("norm-changed",
GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstTunerInterface, norm_changed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_TUNER_NORM);
/**
* GstTuner::channel-changed:
* @tuner: The element providing the GstTuner interface
* @channel: The new configured channel.
*
* Reports that the current #GstTunerChannel has changed.
*/
gst_tuner_signals[CHANNEL_CHANGED] =
g_signal_new ("channel-changed",
GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstTunerInterface, channel_changed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
GST_TYPE_TUNER_CHANNEL);
/**
* GstTuner::frequency-changed:
* @tuner: The element providing the GstTuner interface
* @frequency: The new frequency (an unsigned long)
*
* Reports that the current frequency has changed.
*/
gst_tuner_signals[FREQUENCY_CHANGED] =
g_signal_new ("frequency-changed",
GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstTunerInterface, frequency_changed),
NULL, NULL,
gst_interfaces_marshal_VOID__OBJECT_ULONG, G_TYPE_NONE, 2,
GST_TYPE_TUNER_CHANNEL, G_TYPE_ULONG);
/**
* GstTuner::signal-changed:
* @tuner: The element providing the GstTuner interface
* @channel: The current #GstTunerChannel
* @signal: The new signal strength (an integer)
*
* Reports that the signal strength has changed.
*
* See Also: gst_tuner_signal_strength()
*/
gst_tuner_signals[SIGNAL_CHANGED] =
g_signal_new ("signal-changed",
GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstTunerInterface, signal_changed),
NULL, NULL,
gst_interfaces_marshal_VOID__OBJECT_INT, G_TYPE_NONE, 2,
GST_TYPE_TUNER_CHANNEL, G_TYPE_INT);
initialized = TRUE;
}
/* default virtual functions */
iface->list_channels = NULL;
iface->set_channel = NULL;
iface->get_channel = NULL;
iface->list_norms = NULL;
iface->set_norm = NULL;
iface->get_norm = NULL;
iface->set_frequency = NULL;
iface->get_frequency = NULL;
iface->signal_strength = NULL;
}
/**
* gst_tuner_list_channels:
* @tuner: the #GstTuner (a #GstElement) to get the channels from.
*
* Retrieve a #GList of #GstTunerChannels available
* (e.g. 'composite', 's-video', ...) from the given tuner object.
*
* Returns: A list of channels available on this tuner. The list is
* owned by the GstTuner and must not be freed.
*/
const GList *
gst_tuner_list_channels (GstTuner * tuner)
{
GstTunerInterface *iface;
g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->list_channels) {
return iface->list_channels (tuner);
}
return NULL;
}
/**
* gst_tuner_set_channel:
* @tuner: the #GstTuner (a #GstElement) that owns the channel.
* @channel: the channel to tune to.
*
* Tunes the object to the given channel, which should be one of the
* channels returned by gst_tuner_list_channels().
*/
void
gst_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel)
{
GstTunerInterface *iface;
g_return_if_fail (GST_IS_TUNER (tuner));
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->set_channel) {
iface->set_channel (tuner, channel);
}
}
/**
* gst_tuner_get_channel:
* @tuner: the #GstTuner (a #GstElement) to get the current channel from.
*
* Retrieve the current channel from the tuner.
*
* Returns: the current channel of the tuner object.
*/
GstTunerChannel *
gst_tuner_get_channel (GstTuner * tuner)
{
GstTunerInterface *iface;
g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->get_channel) {
return iface->get_channel (tuner);
}
return NULL;
}
/**
* gst_tuner_list_norms:
* @tuner: the #GstTuner (*a #GstElement) to get the list of norms from.
*
* Retrieve a GList of available #GstTunerNorm settings for the currently
* tuned channel on the given tuner object.
*
* Returns: A list of norms available on the current channel for this
* tuner object. The list is owned by the GstTuner and must not
* be freed.
*/
const GList *
gst_tuner_list_norms (GstTuner * tuner)
{
GstTunerInterface *iface;
g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->list_norms) {
return iface->list_norms (tuner);
}
return NULL;
}
/**
* gst_tuner_set_norm:
* @tuner: the #GstTuner (a #GstElement) to set the norm on.
* @norm: the norm to use for the current channel.
*
* Changes the video norm on this tuner to the given norm, which should be
* one of the norms returned by gst_tuner_list_norms().
*/
void
gst_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm)
{
GstTunerInterface *iface;
g_return_if_fail (GST_IS_TUNER (tuner));
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->set_norm) {
iface->set_norm (tuner, norm);
}
}
/**
* gst_tuner_get_norm:
* @tuner: the #GstTuner (a #GstElement) to get the current norm from.
*
* Get the current video norm from the given tuner object for the
* currently selected channel.
*
* Returns: the current norm.
*/
GstTunerNorm *
gst_tuner_get_norm (GstTuner * tuner)
{
GstTunerInterface *iface;
g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->get_norm) {
return iface->get_norm (tuner);
}
return NULL;
}
/**
* gst_tuner_set_frequency:
* @tuner: The #GstTuner (a #GstElement) that owns the given channel.
* @channel: The #GstTunerChannel to set the frequency on.
* @frequency: The frequency to tune in to.
*
* Sets a tuning frequency on the given tuner/channel. Note that this
* requires the given channel to be a "tuning" channel, which can be
* checked using GST_TUNER_CHANNEL_HAS_FLAG (), with the proper flag
* being GST_TUNER_CHANNEL_FREQUENCY.
*
* The frequency is in Hz, with minimum steps indicated by the
* frequency_multiplicator provided in the #GstTunerChannel. The
* valid range is provided in the min_frequency and max_frequency properties
* of the #GstTunerChannel.
*/
void
gst_tuner_set_frequency (GstTuner * tuner,
GstTunerChannel * channel, gulong frequency)
{
GstTunerInterface *iface;
g_return_if_fail (GST_IS_TUNER (tuner));
g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
GST_TUNER_CHANNEL_FREQUENCY));
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->set_frequency) {
iface->set_frequency (tuner, channel, frequency);
}
}
/**
* gst_tuner_get_frequency:
* @tuner: The #GstTuner (a #GstElement) that owns the given channel.
* @channel: The #GstTunerChannel to retrieve the frequency from.
*
* Retrieve the current frequency from the given channel. As for
* gst_tuner_set_frequency(), the #GstTunerChannel must support frequency
* operations, as indicated by the GST_TUNER_CHANNEL_FREQUENCY flag.
*
* Returns: The current frequency, or 0 on error.
*/
gulong
gst_tuner_get_frequency (GstTuner * tuner, GstTunerChannel * channel)
{
GstTunerInterface *iface;
g_return_val_if_fail (GST_IS_TUNER (tuner), 0);
g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0);
g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
GST_TUNER_CHANNEL_FREQUENCY), 0);
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->get_frequency) {
return iface->get_frequency (tuner, channel);
}
return 0;
}
/**
* gst_tuner_signal_strength:
* @tuner: the #GstTuner (a #GstElement) that owns the given channel.
* @channel: the #GstTunerChannel to get the signal strength from.
*
* Get the strength of the signal on this channel. Note that this
* requires the current channel to be a "tuning" channel, i.e. a
* channel on which frequency can be set. This can be checked using
* GST_TUNER_CHANNEL_HAS_FLAG (), and the appropriate flag to check
* for is GST_TUNER_CHANNEL_FREQUENCY.
*
* The valid range of the signal strength is indicated in the
* min_signal and max_signal properties of the #GstTunerChannel.
*
* Returns: Signal strength, or 0 on error.
*/
gint
gst_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel)
{
GstTunerInterface *iface;
g_return_val_if_fail (GST_IS_TUNER (tuner), 0);
g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0);
g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
GST_TUNER_CHANNEL_FREQUENCY), 0);
iface = GST_TUNER_GET_INTERFACE (tuner);
if (iface->signal_strength) {
return iface->signal_strength (tuner, channel);
}
return 0;
}
/**
* gst_tuner_find_norm_by_name:
* @tuner: A #GstTuner instance
* @norm: A string containing the name of a #GstTunerNorm
*
* Look up a #GstTunerNorm by name.
*
* Returns: A #GstTunerNorm, or NULL if no norm with the provided name
* is available.
*/
GstTunerNorm *
gst_tuner_find_norm_by_name (GstTuner * tuner, gchar * norm)
{
GList *walk;
g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
g_return_val_if_fail (norm != NULL, NULL);
walk = (GList *) gst_tuner_list_norms (tuner);
while (walk) {
if (strcmp (GST_TUNER_NORM (walk->data)->label, norm) == 0)
return GST_TUNER_NORM (walk->data);
walk = g_list_next (walk);
}
return NULL;
}
/**
* gst_tuner_find_channel_by_name:
* @tuner: A #GstTuner instance
* @channel: A string containing the name of a #GstTunerChannel
*
* Look up a #GstTunerChannel by name.
*
* Returns: A #GstTunerChannel, or NULL if no channel with the provided name
* is available.
*/
GstTunerChannel *
gst_tuner_find_channel_by_name (GstTuner * tuner, gchar * channel)
{
GList *walk;
g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
g_return_val_if_fail (channel != NULL, NULL);
walk = (GList *) gst_tuner_list_channels (tuner);
while (walk) {
if (strcmp (GST_TUNER_CHANNEL (walk->data)->label, channel) == 0)
return GST_TUNER_CHANNEL (walk->data);
walk = g_list_next (walk);
}
return NULL;
}
/**
* gst_tuner_channel_changed:
* @tuner: A #GstTuner instance
* @channel: A #GstTunerChannel instance
*
* Called by elements implementing the #GstTuner interface when the
* current channel changes. Fires the #GstTuner::channel-changed signal.
*/
void
gst_tuner_channel_changed (GstTuner * tuner, GstTunerChannel * channel)
{
g_return_if_fail (GST_IS_TUNER (tuner));
g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
g_signal_emit (G_OBJECT (tuner),
gst_tuner_signals[CHANNEL_CHANGED], 0, channel);
}
/**
* gst_tuner_norm_changed:
* @tuner: A #GstTuner instance
* @norm: A #GstTunerNorm instance
*
* Called by elements implementing the #GstTuner interface when the
* current norm changes. Fires the #GstTuner::norm-changed signal.
*
*/
void
gst_tuner_norm_changed (GstTuner * tuner, GstTunerNorm * norm)
{
g_return_if_fail (GST_IS_TUNER (tuner));
g_return_if_fail (GST_IS_TUNER_NORM (norm));
g_signal_emit (G_OBJECT (tuner), gst_tuner_signals[NORM_CHANGED], 0, norm);
}
/**
* gst_tuner_frequency_changed:
* @tuner: A #GstTuner instance
* @channel: The current #GstTunerChannel
* @frequency: The new frequency setting
*
* Called by elements implementing the #GstTuner interface when the
* configured frequency changes. Fires the #GstTuner::frequency-changed
* signal on the tuner, and the #GstTunerChannel::frequency-changed signal
* on the channel.
*/
void
gst_tuner_frequency_changed (GstTuner * tuner,
GstTunerChannel * channel, gulong frequency)
{
g_return_if_fail (GST_IS_TUNER (tuner));
g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
g_signal_emit (G_OBJECT (tuner),
gst_tuner_signals[FREQUENCY_CHANGED], 0, channel, frequency);
g_signal_emit_by_name (G_OBJECT (channel), "frequency_changed", frequency);
}
/**
* gst_tuner_signal_changed:
* @tuner: A #GstTuner instance
* @channel: The current #GstTunerChannel
* @signal: The new signal strength
*
* Called by elements implementing the #GstTuner interface when the
* incoming signal strength changes. Fires the #GstTuner::signal-changed
* signal on the tuner and the #GstTunerChannel::signal-changed signal on
* the channel.
*/
void
gst_tuner_signal_changed (GstTuner * tuner,
GstTunerChannel * channel, gint signal)
{
g_return_if_fail (GST_IS_TUNER (tuner));
g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
g_signal_emit (G_OBJECT (tuner),
gst_tuner_signals[SIGNAL_CHANGED], 0, channel, signal);
g_signal_emit_by_name (G_OBJECT (channel), "signal_changed", signal);
}

142
sys/v4l2/tuner.h Normal file
View file

@ -0,0 +1,142 @@
/* GStreamer Tuner
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* tuner.h: tuner interface design
*
* 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.
*/
#ifndef __GST_TUNER_H__
#define __GST_TUNER_H__
#include <gst/gst.h>
#include "tunernorm.h"
#include "tunerchannel.h"
#include "tuner-enumtypes.h"
G_BEGIN_DECLS
#define GST_TYPE_TUNER \
(gst_tuner_get_type ())
#define GST_TUNER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TUNER, GstTuner))
#define GST_IS_TUNER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TUNER))
#define GST_TUNER_GET_INTERFACE(inst) \
(G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TUNER, GstTunerInterface))
typedef struct _GstTuner GstTuner;
typedef struct _GstTunerInterface GstTunerInterface;
/**
* GstTunerInterface:
* @iface: the parent interface
* @list_channels: list available channels
* @set_channel: set to a channel
* @get_channel: return the current channel
* @list_norms: list available norms
* @set_norm: set a norm
* @get_norm: return the current norm
* @set_frequency: set the frequency
* @get_frequency: return the current frequency
* @signal_strength: get the signal strength
* @channel_changed: default handler for channel changed notification
* @norm_changed: default handler for norm changed notification
* @frequency_changed: default handler for frequency changed notification
* @signal_changed: default handler for signal-strength changed notification
*
* Tuner interface.
*/
struct _GstTunerInterface {
GTypeInterface iface;
/* virtual functions */
const GList * (* list_channels) (GstTuner *tuner);
void (* set_channel) (GstTuner *tuner,
GstTunerChannel *channel);
GstTunerChannel *
(* get_channel) (GstTuner *tuner);
const GList * (* list_norms) (GstTuner *tuner);
void (* set_norm) (GstTuner *tuner,
GstTunerNorm *norm);
GstTunerNorm *(* get_norm) (GstTuner *tuner);
void (* set_frequency) (GstTuner *tuner,
GstTunerChannel *channel,
gulong frequency);
gulong (* get_frequency) (GstTuner *tuner,
GstTunerChannel *channel);
gint (* signal_strength) (GstTuner *tuner,
GstTunerChannel *channel);
/* signals */
void (*channel_changed) (GstTuner *tuner,
GstTunerChannel *channel);
void (*norm_changed) (GstTuner *tuner,
GstTunerNorm *norm);
void (*frequency_changed) (GstTuner *tuner,
GstTunerChannel *channel,
gulong frequency);
void (*signal_changed) (GstTuner *tuner,
GstTunerChannel *channel,
gint signal);
};
GType gst_tuner_get_type (void);
/* virtual class function wrappers */
const GList * gst_tuner_list_channels (GstTuner *tuner);
void gst_tuner_set_channel (GstTuner *tuner,
GstTunerChannel *channel);
GstTunerChannel *
gst_tuner_get_channel (GstTuner *tuner);
const GList * gst_tuner_list_norms (GstTuner *tuner);
void gst_tuner_set_norm (GstTuner *tuner,
GstTunerNorm *norm);
GstTunerNorm * gst_tuner_get_norm (GstTuner *tuner);
void gst_tuner_set_frequency (GstTuner *tuner,
GstTunerChannel *channel,
gulong frequency);
gulong gst_tuner_get_frequency (GstTuner *tuner,
GstTunerChannel *channel);
gint gst_tuner_signal_strength (GstTuner *tuner,
GstTunerChannel *channel);
/* helper functions */
GstTunerNorm * gst_tuner_find_norm_by_name (GstTuner *tuner,
gchar *norm);
GstTunerChannel *gst_tuner_find_channel_by_name (GstTuner *tuner,
gchar *channel);
/* trigger signals */
void gst_tuner_channel_changed (GstTuner *tuner,
GstTunerChannel *channel);
void gst_tuner_norm_changed (GstTuner *tuner,
GstTunerNorm *norm);
void gst_tuner_frequency_changed (GstTuner *tuner,
GstTunerChannel *channel,
gulong frequency);
void gst_tuner_signal_changed (GstTuner *tuner,
GstTunerChannel *channel,
gint signal);
G_END_DECLS
#endif /* __GST_TUNER_H__ */

148
sys/v4l2/tunerchannel.c Normal file
View file

@ -0,0 +1,148 @@
/* GStreamer Tuner
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* tunerchannel.c: tuner channel object design
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tunerchannel.h"
/**
* SECTION:gsttunerchannel
* @short_description: A channel from an element implementing the #GstTuner
* interface.
*
* <refsect2>
* <para>The #GstTunerChannel object is provided by an element implementing
* the #GstTuner interface.
* </para>
* <para>
* GstTunerChannel provides a name and flags to determine the type and
* capabilities of the channel. If the GST_TUNER_CHANNEL_FREQUENCY flag is
* set, then the channel also information about the minimum and maximum
* frequency, and range of the reported signal strength.
* </para>
* </refsect2>
*/
enum
{
/* FILL ME */
SIGNAL_FREQUENCY_CHANGED,
SIGNAL_SIGNAL_CHANGED,
LAST_SIGNAL
};
static void gst_tuner_channel_class_init (GstTunerChannelClass * klass);
static void gst_tuner_channel_init (GstTunerChannel * channel);
static void gst_tuner_channel_dispose (GObject * object);
static GObjectClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = { 0 };
GType
gst_tuner_channel_get_type (void)
{
static GType gst_tuner_channel_type = 0;
if (!gst_tuner_channel_type) {
static const GTypeInfo tuner_channel_info = {
sizeof (GstTunerChannelClass),
NULL,
NULL,
(GClassInitFunc) gst_tuner_channel_class_init,
NULL,
NULL,
sizeof (GstTunerChannel),
0,
(GInstanceInitFunc) gst_tuner_channel_init,
NULL
};
gst_tuner_channel_type =
g_type_register_static (G_TYPE_OBJECT,
"GstTunerChannel", &tuner_channel_info, 0);
}
return gst_tuner_channel_type;
}
static void
gst_tuner_channel_class_init (GstTunerChannelClass * klass)
{
GObjectClass *object_klass = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
/**
* GstTunerChannel::frequency-changed:
* @tunerchannel: The #GstTunerChannel
* @frequency: The new frequency (an unsigned long)
*
* Reports that the current frequency has changed.
*/
signals[SIGNAL_FREQUENCY_CHANGED] =
g_signal_new ("frequency-changed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstTunerChannelClass,
frequency_changed),
NULL, NULL, g_cclosure_marshal_VOID__ULONG, G_TYPE_NONE, 1, G_TYPE_ULONG);
/**
* GstTunerChannel::signal-changed:
* @tunerchannel: The #GstTunerChannel
* @signal: The new signal strength (an integer)
*
* Reports that the signal strength has changed.
*
* See Also: gst_tuner_signal_strength()
*/
signals[SIGNAL_SIGNAL_CHANGED] =
g_signal_new ("signal-changed", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstTunerChannelClass,
signal_changed),
NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
object_klass->dispose = gst_tuner_channel_dispose;
}
static void
gst_tuner_channel_init (GstTunerChannel * channel)
{
channel->label = NULL;
channel->flags = 0;
channel->min_frequency = channel->max_frequency = 0;
channel->min_signal = channel->max_signal = 0;
}
static void
gst_tuner_channel_dispose (GObject * object)
{
GstTunerChannel *channel = GST_TUNER_CHANNEL (object);
if (channel->label) {
g_free (channel->label);
channel->label = NULL;
}
if (parent_class->dispose)
parent_class->dispose (object);
}

116
sys/v4l2/tunerchannel.h Normal file
View file

@ -0,0 +1,116 @@
/* GStreamer Tuner
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* tunerchannel.h: tuner channel object design
*
* 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.
*/
#ifndef __GST_TUNER_CHANNEL_H__
#define __GST_TUNER_CHANNEL_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_TUNER_CHANNEL \
(gst_tuner_channel_get_type ())
#define GST_TUNER_CHANNEL(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TUNER_CHANNEL, \
GstTunerChannel))
#define GST_TUNER_CHANNEL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TUNER_CHANNEL, \
GstTunerChannelClass))
#define GST_IS_TUNER_CHANNEL(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TUNER_CHANNEL))
#define GST_IS_TUNER_CHANNEL_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER_CHANNEL))
typedef struct _GstTunerChannel GstTunerChannel;
typedef struct _GstTunerChannelClass GstTunerChannelClass;
/**
* GstTunerChannelFlags:
* @GST_TUNER_CHANNEL_INPUT: The channel is for input
* @GST_TUNER_CHANNEL_OUTPUT: The channel is for output
* @GST_TUNER_CHANNEL_FREQUENCY: The channel has a frequency setting
* and signal strength.
* @GST_TUNER_CHANNEL_AUDIO: The channel carries audio.
*
* An enumeration for flags indicating the available capabilities
* of a #GstTunerChannel.
*/
typedef enum {
GST_TUNER_CHANNEL_INPUT = (1<<0),
GST_TUNER_CHANNEL_OUTPUT = (1<<1),
GST_TUNER_CHANNEL_FREQUENCY = (1<<2),
GST_TUNER_CHANNEL_AUDIO = (1<<3)
} GstTunerChannelFlags;
/**
* GST_TUNER_CHANNEL_HAS_FLAG:
* @channel: A #GstTunerChannel
* @flag: The flag to check for
*
* Macro to check if the given flag is set on a channel
*/
#define GST_TUNER_CHANNEL_HAS_FLAG(channel, flag) \
((channel)->flags & flag)
/**
* GstTunerChannel:
* @label: A string containing a descriptive name for this channel
* @flags: A set of #GstTunerChannelFlags for this channel
* @freq_multiplicator: The step size (in Hz) for the frequency setting.
* @min_frequency: Minimum valid frequency setting (in Hz).
* @max_frequency: Maximum valid frequency setting (in Hz).
* @min_signal: Minimum reported signal strength value.
* @max_signal: Maximum reported signal strength value.
*/
struct _GstTunerChannel {
GObject parent;
/*< public >*/
gchar *label;
GstTunerChannelFlags flags;
gfloat freq_multiplicator;
gulong min_frequency;
gulong max_frequency;
gint min_signal;
gint max_signal;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstTunerChannelClass {
GObjectClass parent;
/*< private >*/
/* signals */
void (*frequency_changed) (GstTunerChannel *channel,
gulong frequency);
void (*signal_changed) (GstTunerChannel *channel,
gint signal);
gpointer _gst_reserved[GST_PADDING];
};
GType gst_tuner_channel_get_type (void);
G_END_DECLS
#endif /* __GST_TUNER_CHANNEL_H__ */

111
sys/v4l2/tunernorm.c Normal file
View file

@ -0,0 +1,111 @@
/* GStreamer Tuner
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* tunernorm.c: tuner norm object design
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tunernorm.h"
/**
* SECTION:gsttunernorm
* @short_description: Encapsulates information about the data format(s)
* for a #GstTunerChannel.
*
* <refsect2>
* <para>The #GstTunerNorm object is created by an element implementing the
* #GstTuner interface and encapsulates the selection of a capture/output format
* for a selected #GstTunerChannel.
* </para>
* </refsect2>
*/
enum
{
/* FILL ME */
LAST_SIGNAL
};
static void gst_tuner_norm_class_init (GstTunerNormClass * klass);
static void gst_tuner_norm_init (GstTunerNorm * norm);
static void gst_tuner_norm_dispose (GObject * object);
static GObjectClass *parent_class = NULL;
/*static guint signals[LAST_SIGNAL] = { 0 };*/
GType
gst_tuner_norm_get_type (void)
{
static GType gst_tuner_norm_type = 0;
if (!gst_tuner_norm_type) {
static const GTypeInfo tuner_norm_info = {
sizeof (GstTunerNormClass),
NULL,
NULL,
(GClassInitFunc) gst_tuner_norm_class_init,
NULL,
NULL,
sizeof (GstTunerNorm),
0,
(GInstanceInitFunc) gst_tuner_norm_init,
NULL
};
gst_tuner_norm_type =
g_type_register_static (G_TYPE_OBJECT,
"GstTunerNorm", &tuner_norm_info, 0);
}
return gst_tuner_norm_type;
}
static void
gst_tuner_norm_class_init (GstTunerNormClass * klass)
{
GObjectClass *object_klass = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
object_klass->dispose = gst_tuner_norm_dispose;
}
static void
gst_tuner_norm_init (GstTunerNorm * norm)
{
norm->label = NULL;
g_value_init (&norm->framerate, GST_TYPE_FRACTION);
}
static void
gst_tuner_norm_dispose (GObject * object)
{
GstTunerNorm *norm = GST_TUNER_NORM (object);
if (norm->label) {
g_free (norm->label);
norm->label = NULL;
}
if (parent_class->dispose)
parent_class->dispose (object);
}

70
sys/v4l2/tunernorm.h Normal file
View file

@ -0,0 +1,70 @@
/* GStreamer Tuner
* Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* tunernorm.h: tuner norm object design
*
* 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.
*/
#ifndef __GST_TUNER_NORM_H__
#define __GST_TUNER_NORM_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_TUNER_NORM \
(gst_tuner_norm_get_type ())
#define GST_TUNER_NORM(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TUNER_NORM, GstTunerNorm))
#define GST_TUNER_NORM_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TUNER_NORM, GstTunerNormClass))
#define GST_IS_TUNER_NORM(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TUNER_NORM))
#define GST_IS_TUNER_NORM_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER_NORM))
typedef struct _GstTunerNorm GstTunerNorm;
typedef struct _GstTunerNormClass GstTunerNormClass;
/**
* GstTunerNorm:
* @label: A string containing a descriptive name for the norm
* @framerate: A GValue containing the framerate associated with this norm,
* if any. (May be unset).
*/
struct _GstTunerNorm {
GObject parent;
/*< public >*/
gchar *label;
GValue framerate;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
struct _GstTunerNormClass {
GObjectClass parent;
gpointer _gst_reserved[GST_PADDING];
};
GType gst_tuner_norm_get_type (void);
G_END_DECLS
#endif /* __GST_TUNER_NORM_H__ */

View file

@ -294,7 +294,7 @@ elements_sunaudio_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) \
$(AM_CFLAGS)
elements_sunaudio_LDADD = \
$(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-@GST_API_VERSION@ \
$(GST_PLUGINS_BASE_LIBS) \
$(LDADD)
elements_udpsrc_CFLAGS = $(AM_CFLAGS) $(GIO_CFLAGS)

View file

@ -1,5 +1,5 @@
noinst_PROGRAMS = pulse
pulse_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS)
pulse_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_API_VERSION) $(GST_BASE_LIBS) $(GST_LIBS)
pulse_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS)

View file

@ -13,8 +13,7 @@ V4L2_TESTS = v4l2src-test
v4l2src_test_SOURCES = v4l2src-test.c
v4l2src_test_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
v4l2src_test_LDADD = $(GST_PLUGINS_BASE_LIBS) \
-lgstvideo-$(GST_API_VERSION) \
-lgstinterfaces-$(GST_API_VERSION) $(GST_LIBS)
-lgstvideo-$(GST_API_VERSION)
else
V4L2_TESTS =
@ -25,7 +24,7 @@ OSS4_TESTS=test-oss4
test_oss4_SOURCES = test-oss4.c
test_oss4_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
test_oss4_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_API_VERSION) $(GST_LIBS)
test_oss4_LDADD = $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS)
test_oss4_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
else
OSS4_TESTS=

View file

@ -24,7 +24,6 @@
#include <getopt.h>
#include <gst/gst.h>
#include <gst/interfaces/tuner.h>
#include <gst/video/colorbalance.h>
#include <gst/video/videoorientation.h>
@ -49,6 +48,7 @@ run_options (char opt)
int res;
switch (opt) {
#if 0
case 'f':
{
GstTuner *tuner = GST_TUNER (source);
@ -143,6 +143,7 @@ run_options (char opt)
gst_tuner_set_channel (tuner, channel);
}
break;
#endif
case 'e':
gst_element_set_state (pipeline, GST_STATE_NULL);
g_main_loop_quit (loop);