From aa94247770732a40e46ab3d539dd9987062abef4 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 10 Oct 2003 12:47:42 +0000 Subject: Some interface implementations for video4linux/video4linux2 plugins: a Tuner interface, with which one can select inp... Original commit message from CVS: Some interface implementations for video4linux/video4linux2 plugins: * a Tuner interface, with which one can select inputs and stations. Audio work is underway here, but unfinished. * A Xoverlay interface with which one can do simple overlay. Similar to the API of the v4l/Xv XFree86 extension. Widget implementation for GTK-2.0 coming up in the sandbox. * Colorbalance - for adapting colors (brightness, contrast, etc.) - pretty basic and maybe somewhat overdesigned. But it'll do for now. Apart from these interfaces, there's also a loadable library 'xwindowlistener' that listenes to X for the movement of a window and the overlap of other windows. This is partly copied from xawtv (and thus partly GPL :(), but it's needed for the xoverlay interface implementation in the v4l/v4l2 elements. Lastly, some small changes to remove redundant properties from the v4l/v4l2 elements since these can be done much simpler. Comments appreciated! --- configure.ac | 4 + gst-libs/gst/Makefile.am | 22 +- gst-libs/gst/colorbalance/Makefile.am | 15 + gst-libs/gst/colorbalance/colorbalance.c | 103 ++++ gst-libs/gst/colorbalance/colorbalance.h | 73 +++ gst-libs/gst/colorbalance/colorbalancechannel.c | 104 ++++ gst-libs/gst/colorbalance/colorbalancechannel.h | 62 +++ gst-libs/gst/tuner/Makefile.am | 17 + gst-libs/gst/tuner/tuner.c | 190 +++++++ gst-libs/gst/tuner/tuner.h | 96 ++++ gst-libs/gst/tuner/tunerchannel.c | 114 ++++ gst-libs/gst/tuner/tunerchannel.h | 77 +++ gst-libs/gst/tuner/tunernorm.c | 95 ++++ gst-libs/gst/tuner/tunernorm.h | 55 ++ gst-libs/gst/xoverlay/Makefile.am | 11 + gst-libs/gst/xoverlay/xoverlay.c | 74 +++ gst-libs/gst/xoverlay/xoverlay.h | 61 +++ gst-libs/gst/xwindowlistener/Makefile.am | 11 + gst-libs/gst/xwindowlistener/xwindowlistener.c | 656 ++++++++++++++++++++++++ gst-libs/gst/xwindowlistener/xwindowlistener.h | 116 +++++ sys/v4l2/gstv4l2colorbalance.c | 151 ++++++ sys/v4l2/gstv4l2colorbalance.h | 58 +++ sys/v4l2/gstv4l2element-marshal.list | 3 - sys/v4l2/gstv4l2element.c | 432 +++++++--------- sys/v4l2/gstv4l2element.h | 33 +- sys/v4l2/gstv4l2src.c | 17 +- sys/v4l2/gstv4l2tuner.c | 361 +++++++++++++ sys/v4l2/gstv4l2tuner.h | 85 +++ sys/v4l2/gstv4l2xoverlay.c | 128 +++++ sys/v4l2/gstv4l2xoverlay.h | 42 ++ sys/v4l2/v4l2-overlay_calls.c | 17 +- sys/v4l2/v4l2_calls.c | 479 ++++++++--------- sys/v4l2/v4l2_calls.h | 25 +- 33 files changed, 3196 insertions(+), 591 deletions(-) create mode 100644 gst-libs/gst/colorbalance/Makefile.am create mode 100644 gst-libs/gst/colorbalance/colorbalance.c create mode 100644 gst-libs/gst/colorbalance/colorbalance.h create mode 100644 gst-libs/gst/colorbalance/colorbalancechannel.c create mode 100644 gst-libs/gst/colorbalance/colorbalancechannel.h create mode 100644 gst-libs/gst/tuner/Makefile.am create mode 100644 gst-libs/gst/tuner/tuner.c create mode 100644 gst-libs/gst/tuner/tuner.h create mode 100644 gst-libs/gst/tuner/tunerchannel.c create mode 100644 gst-libs/gst/tuner/tunerchannel.h create mode 100644 gst-libs/gst/tuner/tunernorm.c create mode 100644 gst-libs/gst/tuner/tunernorm.h create mode 100644 gst-libs/gst/xoverlay/Makefile.am create mode 100644 gst-libs/gst/xoverlay/xoverlay.c create mode 100644 gst-libs/gst/xoverlay/xoverlay.h create mode 100644 gst-libs/gst/xwindowlistener/Makefile.am create mode 100644 gst-libs/gst/xwindowlistener/xwindowlistener.c create mode 100644 gst-libs/gst/xwindowlistener/xwindowlistener.h create mode 100644 sys/v4l2/gstv4l2colorbalance.c create mode 100644 sys/v4l2/gstv4l2colorbalance.h delete mode 100644 sys/v4l2/gstv4l2element-marshal.list create mode 100644 sys/v4l2/gstv4l2tuner.c create mode 100644 sys/v4l2/gstv4l2tuner.h create mode 100644 sys/v4l2/gstv4l2xoverlay.c create mode 100644 sys/v4l2/gstv4l2xoverlay.h diff --git a/configure.ac b/configure.ac index 5bcb93ac..765bac4c 100644 --- a/configure.ac +++ b/configure.ac @@ -1287,6 +1287,7 @@ ext/xvid/Makefile gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/audio/Makefile +gst-libs/gst/colorbalance/Makefile gst-libs/gst/floatcast/Makefile gst-libs/gst/gconf/Makefile gst-libs/gst/idct/Makefile @@ -1296,7 +1297,10 @@ gst-libs/gst/navigation/Makefile gst-libs/gst/play/Makefile gst-libs/gst/resample/Makefile gst-libs/gst/riff/Makefile +gst-libs/gst/tuner/Makefile gst-libs/gst/video/Makefile +gst-libs/gst/xoverlay/Makefile +gst-libs/gst/xwindowlistener/Makefile gst-libs/ext/Makefile gst-libs/ext/ffmpeg/Makefile gst-libs/ext/mplex/Makefile diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index 04acada7..06f12a07 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -4,10 +4,20 @@ else GCONF_DIR= endif -SUBDIRS = audio idct resample riff floatcast \ - $(GCONF_DIR) media-info mixer \ - navigation play video +if USE_XFREE +X_DIR=xwindowlistener +else +X_DIR= +endif + +SUBDIRS = audio colorbalance floatcast \ + $(GCONF_DIR) idct media-info \ + mixer navigation play \ + resample riff tuner video \ + xoverlay $(X_DIR) -DIST_SUBDIRS = audio idct resample riff floatcast \ - gconf media-info mixer navigation \ - play video +DIST_SUBDIRS = audio colorbalance floatcast \ + gconf idct media-info \ + mixer navigation play \ + resample riff tuner video \ + xoverlay xwindowlistener diff --git a/gst-libs/gst/colorbalance/Makefile.am b/gst-libs/gst/colorbalance/Makefile.am new file mode 100644 index 00000000..cbd94c91 --- /dev/null +++ b/gst-libs/gst/colorbalance/Makefile.am @@ -0,0 +1,15 @@ +libgstinterfacesincludedir = \ + $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/colorbalance + +libgstinterfacesinclude_HEADERS = \ + colorbalance.h \ + colorbalancechannel.h + +lib_LTLIBRARIES = libgstcolorbalance.la + +libgstcolorbalance_la_SOURCES = \ + colorbalance.c \ + colorbalancechannel.c +libgstcolorbalance_la_LIBADD = +libgstcolorbalance_la_CFLAGS = $(GST_CFLAGS) $(GST_OPT_CFLAGS) +libgstcolorbalance_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst-libs/gst/colorbalance/colorbalance.c b/gst-libs/gst/colorbalance/colorbalance.c new file mode 100644 index 00000000..829cf5f6 --- /dev/null +++ b/gst-libs/gst/colorbalance/colorbalance.c @@ -0,0 +1,103 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * colorbalance.c: image color balance interface 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 "colorbalance.h" + +static void gst_color_balance_class_init (GstColorBalanceClass *klass); + +GType +gst_color_balance_get_type (void) +{ + static GType gst_color_balance_type = 0; + + if (!gst_color_balance_type) { + static const GTypeInfo gst_color_balance_info = { + sizeof (GstColorBalanceClass), + (GBaseInitFunc) gst_color_balance_class_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_color_balance_type = g_type_register_static (G_TYPE_INTERFACE, + "GstColorBalance", + &gst_color_balance_info, 0); + g_type_interface_add_prerequisite (gst_color_balance_type, + GST_TYPE_INTERFACE); + } + + return gst_color_balance_type; +} + +static void +gst_color_balance_class_init (GstColorBalanceClass *klass) +{ + /* default virtual functions */ + klass->list_channels = NULL; + klass->set_value = NULL; + klass->get_value = NULL; +} + +const GList * +gst_color_balance_list_channels (GstColorBalance *balance) +{ + GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance); + + if (klass->list_channels) { + return klass->list_channels (balance); + } + + return NULL; +} + +void +gst_color_balance_set_value (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value) +{ + GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance); + + if (klass->set_value) { + klass->set_value (balance, channel, value); + } +} + +gint +gst_color_balance_get_value (GstColorBalance *balance, + GstColorBalanceChannel *channel) +{ + GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance); + + if (klass->get_value) { + return klass->get_value (balance, channel); + } + + return channel->min_value; +} diff --git a/gst-libs/gst/colorbalance/colorbalance.h b/gst-libs/gst/colorbalance/colorbalance.h new file mode 100644 index 00000000..2b9d27d3 --- /dev/null +++ b/gst-libs/gst/colorbalance/colorbalance.h @@ -0,0 +1,73 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * color-balance.h: image color balance 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_COLOR_BALANCE_H__ +#define __GST_COLOR_BALANCE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_COLOR_BALANCE \ + (gst_color_balance_get_type ()) +#define GST_COLOR_BALANCE(obj) \ + (GST_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_COLOR_BALANCE, \ + GstColorBalance)) +#define GST_COLOR_BALANCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_COLOR_BALANCE, \ + GstColorBalanceClass)) +#define GST_IS_COLOR_BALANCE(obj) \ + (GST_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_COLOR_BALANCE)) +#define GST_IS_COLOR_BALANCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_COLOR_BALANCE)) +#define GST_COLOR_BALANCE_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_COLOR_BALANCE, GstColorBalanceClass)) + +typedef struct _GstColorBalance GstColorBalance; + +typedef struct _GstColorBalanceClass { + GTypeInterface klass; + + /* virtual functions */ + const GList * (* list_channels) (GstColorBalance *balance); + + void (* set_value) (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value); + gint (* get_value) (GstColorBalance *balance, + GstColorBalanceChannel *channel); +} GstColorBalanceClass; + +GType gst_color_balance_get_type (void); + +/* virtual class function wrappers */ +const GList * + gst_color_balance_list_channels (GstColorBalance *balance); +void gst_color_balance_set_value (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value); +gint gst_color_balance_get_value (GstColorBalance *balance, + GstColorBalanceChannel *channel); + +G_END_DECLS + +#endif /* __GST_COLOR_BALANCE_H__ */ diff --git a/gst-libs/gst/colorbalance/colorbalancechannel.c b/gst-libs/gst/colorbalance/colorbalancechannel.c new file mode 100644 index 00000000..8241bfe7 --- /dev/null +++ b/gst-libs/gst/colorbalance/colorbalancechannel.c @@ -0,0 +1,104 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * colorbalancechannel.c: colorbalance 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 "colorbalancechannel.h" + +enum { + /* FILL ME */ + SIGNAL_VALUE_CHANGED, + LAST_SIGNAL +}; + +static void gst_color_balance_channel_class_init (GstColorBalanceChannelClass *klass); +static void gst_color_balance_channel_init (GstColorBalanceChannel *balance); +static void gst_color_balance_channel_dispose (GObject *object); + +static GObjectClass *parent_class = NULL; +static guint signals[LAST_SIGNAL] = { 0 }; + +GType +gst_color_balance_channel_get_type (void) +{ + static GType gst_color_balance_channel_type = 0; + + if (!gst_color_balance_channel_type) { + static const GTypeInfo color_balance_channel_info = { + sizeof (GstColorBalanceChannelClass), + NULL, + NULL, + (GClassInitFunc) gst_color_balance_channel_class_init, + NULL, + NULL, + sizeof (GstColorBalanceChannel), + 0, + (GInstanceInitFunc) gst_color_balance_channel_init, + NULL + }; + + gst_color_balance_channel_type = + g_type_register_static (G_TYPE_OBJECT, + "GstColorBalanceChannel", + &color_balance_channel_info, 0); + } + + return gst_color_balance_channel_type; +} + +static void +gst_color_balance_channel_class_init (GstColorBalanceChannelClass *klass) +{ + GObjectClass *object_klass = (GObjectClass *) klass; + + parent_class = g_type_class_ref (G_TYPE_OBJECT); + + signals[SIGNAL_VALUE_CHANGED] = + g_signal_new ("value_changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstColorBalanceChannelClass, + value_changed), + NULL, NULL, g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + + object_klass->dispose = gst_color_balance_channel_dispose; +} + +static void +gst_color_balance_channel_init (GstColorBalanceChannel *channel) +{ + channel->label = NULL; + channel->min_value = channel->max_value = 0; +} + +static void +gst_color_balance_channel_dispose (GObject *object) +{ + GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (object); + + if (channel->label) + g_free (channel->label); + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-libs/gst/colorbalance/colorbalancechannel.h b/gst-libs/gst/colorbalance/colorbalancechannel.h new file mode 100644 index 00000000..5f738ecb --- /dev/null +++ b/gst-libs/gst/colorbalance/colorbalancechannel.h @@ -0,0 +1,62 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * colorbalancechannel.h: individual channel object + * + * 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_COLOR_BALANCE_CHANNEL_H__ +#define __GST_COLOR_BALANCE_CHANNEL_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_COLOR_BALANCE_CHANNEL \ + (gst_color_balance_channel_get_type ()) +#define GST_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_COLOR_BALANCE_CHANNEL, \ + GstColorBalanceChannel)) +#define GST_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_COLOR_BALANCE_CHANNEL, \ + GstColorBalanceChannelClass)) +#define GST_IS_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_COLOR_BALANCE_CHANNEL)) +#define GST_IS_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_COLOR_BALANCE_CHANNEL)) + +typedef struct _GstColorBalanceChannel { + GObject parent; + + gchar *label; + gint min_value, + max_value; +} GstColorBalanceChannel; + +typedef struct _GstColorBalanceChannelClass { + GObjectClass parent; + + /* signals */ + void (* value_changed) (GstColorBalanceChannel *channel, + gint value); +} GstColorBalanceChannelClass; + +GType gst_color_balance_channel_get_type (void); + +G_END_DECLS + +#endif /* __GST_COLOR_BALANCE_CHANNEL_H__ */ diff --git a/gst-libs/gst/tuner/Makefile.am b/gst-libs/gst/tuner/Makefile.am new file mode 100644 index 00000000..e349eb32 --- /dev/null +++ b/gst-libs/gst/tuner/Makefile.am @@ -0,0 +1,17 @@ +libgstinterfacesincludedir = \ + $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/tuner + +libgstinterfacesinclude_HEADERS = \ + tuner.h \ + tunernorm.h \ + tunerchannel.h + +lib_LTLIBRARIES = libgsttuner.la + +libgsttuner_la_SOURCES = \ + tuner.c \ + tunernorm.c \ + tunerchannel.c +libgsttuner_la_LIBADD = +libgsttuner_la_CFLAGS = $(GST_CFLAGS) $(GST_OPT_CFLAGS) +libgsttuner_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst-libs/gst/tuner/tuner.c b/gst-libs/gst/tuner/tuner.c new file mode 100644 index 00000000..43dda8d0 --- /dev/null +++ b/gst-libs/gst/tuner/tuner.c @@ -0,0 +1,190 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * 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" + +static void gst_tuner_class_init (GstTunerClass *klass); + +GType +gst_tuner_get_type (void) +{ + static GType gst_tuner_type = 0; + + if (!gst_tuner_type) { + static const GTypeInfo gst_tuner_info = { + sizeof (GstTunerClass), + (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); + g_type_interface_add_prerequisite (gst_tuner_type, + GST_TYPE_INTERFACE); + } + + return gst_tuner_type; +} + +static void +gst_tuner_class_init (GstTunerClass *klass) +{ + /* default virtual functions */ + klass->list_channels = NULL; + klass->set_channel = NULL; + klass->get_channel = NULL; + + klass->list_norms = NULL; + klass->set_norm = NULL; + klass->get_norm = NULL; + + klass->set_frequency = NULL; + klass->get_frequency = NULL; + klass->signal_strength = NULL; +} + +const GList * +gst_tuner_list_channels (GstTuner *tuner) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + if (klass->list_channels) { + return klass->list_channels (tuner); + } + + return NULL; +} + +void +gst_tuner_set_channel (GstTuner *tuner, + GstTunerChannel *channel) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + if (klass->set_channel) { + klass->set_channel (tuner, channel); + } +} + +const GstTunerChannel * +gst_tuner_get_channel (GstTuner *tuner) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + if (klass->get_channel) { + return klass->get_channel (tuner); + } + + return NULL; +} + +const GList * +gst_tuner_list_norms (GstTuner *tuner) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + if (klass->list_norms) { + return klass->list_norms (tuner); + } + + return NULL; +} + +void +gst_tuner_set_norm (GstTuner *tuner, + GstTunerNorm *norm) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + if (klass->set_norm) { + klass->set_norm (tuner, norm); + } +} + +const GstTunerNorm * +gst_tuner_get_norm (GstTuner *tuner) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + if (klass->get_norm) { + return klass->get_norm (tuner); + } + + return NULL; +} + +void +gst_tuner_set_frequency (GstTuner *tuner, + GstTunerChannel *channel, + gulong frequency) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY)); + + if (klass->set_frequency) { + klass->set_frequency (tuner, channel, frequency); + } +} + +gulong +gst_tuner_get_frequency (GstTuner *tuner, + GstTunerChannel *channel) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + + if (klass->get_frequency) { + return klass->get_frequency (tuner, channel); + } + + return 0; +} + +gint +gst_tuner_signal_strength (GstTuner *tuner, + GstTunerChannel *channel) +{ + GstTunerClass *klass = GST_TUNER_GET_CLASS (tuner); + + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + + if (klass->signal_strength) { + return klass->signal_strength (tuner, channel); + } + + return 0; +} diff --git a/gst-libs/gst/tuner/tuner.h b/gst-libs/gst/tuner/tuner.h new file mode 100644 index 00000000..1cd51e11 --- /dev/null +++ b/gst-libs/gst/tuner/tuner.h @@ -0,0 +1,96 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * 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 +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TUNER \ + (gst_tuner_get_type ()) +#define GST_TUNER(obj) \ + (GST_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TUNER, GstTuner)) +#define GST_TUNER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TUNER, GstTunerClass)) +#define GST_IS_TUNER(obj) \ + (GST_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TUNER)) +#define GST_IS_TUNER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER)) +#define GST_TUNER_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TUNER, GstTunerClass)) + +typedef struct _GstTuner GstTuner; + +typedef struct _GstTunerClass { + GTypeInterface klass; + + /* virtual functions */ + const GList * (* list_channels) (GstTuner *tuner); + void (* set_channel) (GstTuner *tuner, + GstTunerChannel *channel); + const GstTunerChannel * + (* get_channel) (GstTuner *tuner); + + const GList * (* list_norms) (GstTuner *tuner); + void (* set_norm) (GstTuner *tuner, + GstTunerNorm *norm); + const 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); +} GstTunerClass; + +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); +const GstTunerChannel * + gst_tuner_get_channel (GstTuner *tuner); + +const GList * gst_tuner_list_norms (GstTuner *tuner); +void gst_tuner_set_norm (GstTuner *tuner, + GstTunerNorm *channel); +const 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); + +G_END_DECLS + +#endif /* __GST_TUNER_H__ */ diff --git a/gst-libs/gst/tuner/tunerchannel.c b/gst-libs/gst/tuner/tunerchannel.c new file mode 100644 index 00000000..aa98978e --- /dev/null +++ b/gst-libs/gst/tuner/tunerchannel.c @@ -0,0 +1,114 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * 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" + +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_ref (G_TYPE_OBJECT); + + 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); + 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); + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-libs/gst/tuner/tunerchannel.h b/gst-libs/gst/tuner/tunerchannel.h new file mode 100644 index 00000000..b8031455 --- /dev/null +++ b/gst-libs/gst/tuner/tunerchannel.h @@ -0,0 +1,77 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * 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 + +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 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; + +#define GST_TUNER_CHANNEL_HAS_FLAG(channel, flag) \ + ((channel)->flags & flag) + +typedef struct _GstTunerChannel { + GObject parent; + + gchar *label; + GstTunerChannelFlags flags; + gulong min_frequency, + max_frequency; + gint min_signal, + max_signal; +} GstTunerChannel; + +typedef struct _GstTunerChannelClass { + GObjectClass parent; + + /* signals */ + void (*frequency_changed) (GstTunerChannel *tuner, + gulong frequency); + void (*signal_changed) (GstTunerChannel *tuner, + gint signal); +} GstTunerChannelClass; + +GType gst_tuner_channel_get_type (void); + +G_END_DECLS + +#endif /* __GST_TUNER_CHANNEL_H__ */ diff --git a/gst-libs/gst/tuner/tunernorm.c b/gst-libs/gst/tuner/tunernorm.c new file mode 100644 index 00000000..48d75de2 --- /dev/null +++ b/gst-libs/gst/tuner/tunernorm.c @@ -0,0 +1,95 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * 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" + +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_ref (G_TYPE_OBJECT); + + object_klass->dispose = gst_tuner_norm_dispose; +} + +static void +gst_tuner_norm_init (GstTunerNorm *norm) +{ + norm->label = NULL; + norm->fps = 0.; +} + +static void +gst_tuner_norm_dispose (GObject *object) +{ + GstTunerNorm *norm = GST_TUNER_NORM (object); + + if (norm->label) + g_free (norm->label); + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-libs/gst/tuner/tunernorm.h b/gst-libs/gst/tuner/tunernorm.h new file mode 100644 index 00000000..3e6e801d --- /dev/null +++ b/gst-libs/gst/tuner/tunernorm.h @@ -0,0 +1,55 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * 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 + +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 { + GObject parent; + + gchar *label; + gfloat fps; +} GstTunerNorm; + +typedef struct _GstTunerNormClass { + GObjectClass parent; +} GstTunerNormClass; + +GType gst_tuner_norm_get_type (void); + +G_END_DECLS + +#endif /* __GST_TUNER_NORM_H__ */ diff --git a/gst-libs/gst/xoverlay/Makefile.am b/gst-libs/gst/xoverlay/Makefile.am new file mode 100644 index 00000000..184d505f --- /dev/null +++ b/gst-libs/gst/xoverlay/Makefile.am @@ -0,0 +1,11 @@ +libgstinterfacesincludedir = \ + $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/xoverlay + +libgstinterfacesinclude_HEADERS = xoverlay.h + +lib_LTLIBRARIES = libgstxoverlay.la + +libgstxoverlay_la_SOURCES = xoverlay.c +libgstxoverlay_la_LIBADD = +libgstxoverlay_la_CFLAGS = $(GST_CFLAGS) $(GST_OPT_CFLAGS) +libgstxoverlay_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst-libs/gst/xoverlay/xoverlay.c b/gst-libs/gst/xoverlay/xoverlay.c new file mode 100644 index 00000000..f0b4ebb5 --- /dev/null +++ b/gst-libs/gst/xoverlay/xoverlay.c @@ -0,0 +1,74 @@ +/* GStreamer X-based Overlay + * Copyright (C) 2003 Ronald Bultje + * + * tv-mixer.c: tv-mixer 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 "xoverlay.h" + +static void gst_x_overlay_class_init (GstXOverlayClass *klass); + +GType +gst_x_overlay_get_type (void) +{ + static GType gst_x_overlay_type = 0; + + if (!gst_x_overlay_type) { + static const GTypeInfo gst_x_overlay_info = { + sizeof (GstXOverlayClass), + (GBaseInitFunc) gst_x_overlay_class_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_x_overlay_type = g_type_register_static (G_TYPE_INTERFACE, + "GstXOverlay", + &gst_x_overlay_info, 0); + g_type_interface_add_prerequisite (gst_x_overlay_type, + GST_TYPE_INTERFACE); + } + + return gst_x_overlay_type; +} + +static void +gst_x_overlay_class_init (GstXOverlayClass *klass) +{ + /* default virtual functions */ + klass->set_xwindow_id = NULL; +} + +void +gst_x_overlay_set_xwindow_id (GstXOverlay *overlay, + XID xwindow_id) +{ + GstXOverlayClass *klass = GST_X_OVERLAY_GET_CLASS (overlay); + + if (klass->set_xwindow_id) { + klass->set_xwindow_id (overlay, xwindow_id); + } +} diff --git a/gst-libs/gst/xoverlay/xoverlay.h b/gst-libs/gst/xoverlay/xoverlay.h new file mode 100644 index 00000000..15258765 --- /dev/null +++ b/gst-libs/gst/xoverlay/xoverlay.h @@ -0,0 +1,61 @@ +/* GStreamer X-based Overlay + * Copyright (C) 2003 Ronald Bultje + * + * x-overlay.h: X-based overlay 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_X_OVERLAY_H__ +#define __GST_X_OVERLAY_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_X_OVERLAY \ + (gst_x_overlay_get_type ()) +#define GST_X_OVERLAY(obj) \ + (GST_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_X_OVERLAY, GstXOverlay)) +#define GST_X_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_X_OVERLAY, GstXOverlayClass)) +#define GST_IS_X_OVERLAY(obj) \ + (GST_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_X_OVERLAY)) +#define GST_IS_X_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_X_OVERLAY)) +#define GST_X_OVERLAY_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_X_OVERLAY, GstXOverlayClass)) + +typedef struct _GstXOverlay GstXOverlay; + +typedef struct _GstXOverlayClass { + GTypeInterface klass; + + /* virtual functions */ + void (* set_xwindow_id) (GstXOverlay *overlay, + XID xwindow_id); +} GstXOverlayClass; + +GType gst_x_overlay_get_type (void); + +/* virtual class function wrappers */ +void gst_x_overlay_set_xwindow_id (GstXOverlay *overlay, + XID xwindow_id); + +G_END_DECLS + +#endif /* __GST_X_OVERLAY_H__ */ diff --git a/gst-libs/gst/xwindowlistener/Makefile.am b/gst-libs/gst/xwindowlistener/Makefile.am new file mode 100644 index 00000000..a3a589ba --- /dev/null +++ b/gst-libs/gst/xwindowlistener/Makefile.am @@ -0,0 +1,11 @@ +librarydir = $(libdir)/gstreamer-@GST_MAJORMINOR@ + +library_LTLIBRARIES = libgstxwindowlistener.la + +libgstxwindowlistener_la_SOURCES = xwindowlistener.c + +libraryincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/xwindowlistener +libraryinclude_HEADERS = xwindowlistener.h + +libgstxwindowlistener_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) +libgstxwindowlistener_la_LIBADD = $(GST_LIBS) $(GST_PLUGIN_LIBS) $(X_LIBS) diff --git a/gst-libs/gst/xwindowlistener/xwindowlistener.c b/gst-libs/gst/xwindowlistener/xwindowlistener.c new file mode 100644 index 00000000..0a400a53 --- /dev/null +++ b/gst-libs/gst/xwindowlistener/xwindowlistener.c @@ -0,0 +1,656 @@ +/* G-Streamer X11 Window event/motion listener + * Copyright (C) 2003 Ronald Bultje + * + * xwindowlistener.c: implementation of the object + * + * 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 +#include "xwindowlistener.h" + +#define NUM_CLIPS 1024 + +static void gst_x_window_listener_class_init (GstXWindowListenerClass *klass); +static void gst_x_window_listener_init (GstXWindowListener *xwin); +static void gst_x_window_listener_dispose (GObject *object); + +static void gst_xwin_start (GstXWindowListener *xwin); +static void gst_xwin_stop (GstXWindowListener *xwin); + +static GObjectClass *parent_class = NULL; + +GType +gst_x_window_listener_get_type (void) +{ + static GType x_window_listener_type = 0; + + if (!x_window_listener_type) { + static const GTypeInfo x_window_listener_info = { + sizeof (GstXWindowListenerClass), + NULL, + NULL, + (GClassInitFunc) gst_x_window_listener_class_init, + NULL, + NULL, + sizeof (GstXWindowListener), + 0, + (GInstanceInitFunc) gst_x_window_listener_init, + NULL + }; + + x_window_listener_type = + g_type_register_static (G_TYPE_OBJECT, + "GstXWindowListener", + &x_window_listener_info, 0); + } + + return x_window_listener_type; +} + +static void +gst_x_window_listener_class_init (GstXWindowListenerClass *klass) +{ + GObjectClass *object_klass = (GObjectClass *) klass; + + parent_class = g_type_class_ref (G_TYPE_OBJECT); + + object_klass->dispose = gst_x_window_listener_dispose; +} + +static void +gst_x_window_listener_init (GstXWindowListener *xwin) +{ + xwin->xwindow_id = 0; + xwin->display_name = NULL; + + xwin->map_window_func = NULL; + xwin->set_window_func = NULL; + + xwin->thread = NULL; +} + +static void +gst_x_window_listener_dispose (GObject *object) +{ + GstXWindowListener *xwin = GST_X_WINDOW_LISTENER (object); + + /* stop overlay */ + gst_x_window_listener_set_xid (xwin, 0); + + if (xwin->display_name) { + g_free (xwin->display_name); + } + + if (parent_class->dispose) { + parent_class->dispose (object); + } +} + +GstXWindowListener * +gst_x_window_listener_new (gchar *display, + MapWindowFunc map_window_func, + SetWindowFunc set_window_func, + gpointer private_data) +{ + GstXWindowListener *xwin = + g_object_new (GST_TYPE_X_WINDOW_LISTENER, NULL); + + xwin->display_name = g_strdup (display); + xwin->map_window_func = map_window_func; + xwin->set_window_func = set_window_func; + xwin->private_data = private_data; + + return xwin; +} + +void +gst_x_window_listener_set_xid (GstXWindowListener *xwin, + XID id) +{ + g_return_if_fail (xwin != NULL); + + if (id == xwin->xwindow_id) { + return; + } + + if (xwin->xwindow_id && xwin->thread) { + gst_xwin_stop (xwin); + } + + xwin->xwindow_id = id; + + if (xwin->xwindow_id && + xwin->display_name && + xwin->display_name[0] == ':') { + g_return_if_fail (xwin->map_window_func != NULL); + g_return_if_fail (xwin->set_window_func != NULL); + + gst_xwin_start (xwin); + } +} + +/* + * The following code works as follows: + * - the "client" (the one who uses this object) sets an XID + * - we add a child XWindow to this XID, and follow motion/events + * - after each event, we determine the position, size and clips + * - next, we call the per-instance virtual functions set by the client + * - and we do all this in an endless cycle + * + * Unfortunately, part of this code is inspired by XawTV, so the + * runtime license for this code as a whole will be GPL unless + * someone can rewrite this or ask permission to the original + * author (Gerd Knorr ) to let us re-license + * this piece of code to LGPL. + */ + +#define DEBUG(format, args...) \ + GST_DEBUG ("XWL: " format, ##args) + +static void +gst_xwin_set_overlay (GstXWindowListener *xwin, + gboolean on) +{ + xwin->map_window_func (xwin->private_data, on); + + /* remember me */ + xwin->ov_visible = on; +} + +static gboolean +gst_xwin_refresh (gpointer data) +{ + GstXWindowListener *xwin = GST_X_WINDOW_LISTENER (data); + Window win, tmp; + XSetWindowAttributes xswa; + XWindowAttributes attr; + + g_mutex_lock (xwin->main_lock); + + win = DefaultRootWindow (xwin->main_display); + XGetWindowAttributes (xwin->main_display, win, &attr); + + xwin->ov_refresh_id = 0; + + if (!xwin->ov_move && xwin->ov_map && + xwin->ov_visibility == VisibilityUnobscured) { + g_mutex_unlock (xwin->main_lock); + return FALSE; /* skip */ + } + + if (xwin->ov_map && + xwin->ov_visibility != VisibilityFullyObscured) { + xwin->ov_refresh = TRUE; + } + + xswa.override_redirect = True; + xswa.backing_store = NotUseful; + xswa.save_under = False; + tmp = XCreateWindow (xwin->main_display,win, 0, 0, + attr.width, attr.height, 0, + CopyFromParent, InputOutput, CopyFromParent, + (CWSaveUnder | CWBackingStore| CWOverrideRedirect ), + &xswa); + XMapWindow (xwin->main_display, tmp); + XUnmapWindow (xwin->main_display, tmp); + XDestroyWindow (xwin->main_display, tmp); + xwin->ov_move = FALSE; + + g_mutex_unlock (xwin->main_lock); + + /* once */ + return FALSE; +} + +static int +x11_error_dev_null (Display *display, + XErrorEvent *event) +{ + return 0; +} + +#define ADD_CLIP(_x, _y, _w, _h) \ + do { \ + GstXWindowClip *clip = &xwin->clips[xwin->num_clips++]; \ + clip->x_offset = _x; \ + clip->y_offset = _y; \ + clip->width = _w; \ + clip->height = _h; \ + clip->data = NULL; \ + } while (0); + +static void +gst_xwin_set_clips (GstXWindowListener *xwin) +{ + Window root, rroot, parent, *kids, me; + XWindowAttributes attr; + guint numkids; + gint i; + gint x1, y1, w1, h1; + void *old_handler; + + old_handler = XSetErrorHandler (x11_error_dev_null); + + if (xwin->num_clips != 0) + xwin->ov_conf = TRUE; + xwin->num_clips = 0; + + root = DefaultRootWindow (xwin->display); + XGetWindowAttributes (xwin->display, root, &attr); + + if (xwin->x < 0) + ADD_CLIP (0, 0, -xwin->x, xwin->h); + if (xwin->y < 0) + ADD_CLIP (0, 0, xwin->w, -xwin->y); + if ((xwin->x + xwin->w) > attr.width) + ADD_CLIP (attr.width - xwin->x, 0, xwin->w, xwin->h); + if ((xwin->y + xwin->h) > attr.height) + ADD_CLIP (0, attr.height - xwin->y, xwin->w, xwin->h); + + me = xwin->child; + while (1) { + XQueryTree (xwin->display, me, &rroot, &parent, &kids, &numkids); + if (numkids) + XFree (kids); + if (root == parent) + break; + me = parent; + } + + XQueryTree (xwin->display, root, &rroot, &parent, &kids, &numkids); + for (i = 0; i < numkids; i++) + if (kids[i] == me) + break; + + for (i++; i < numkids; i++) { + XGetWindowAttributes (xwin->display, kids[i], &attr); + if (attr.map_state != IsViewable) + continue; + + x1 = attr.x - xwin->x; + y1 = attr.y - xwin->y; + w1 = attr.width + 2 * attr.border_width; + h1 = attr.height + 2 * attr.border_width; + if (((x1 + w1) < 0) || (x1 > xwin->w) || + ((y1 + h1) < 0) || (y1 > xwin->h)) + continue; + + if (x1 < 0) + x1 = 0; + if (y1 < 0) + y1 = 0; + ADD_CLIP (x1, y1, w1, h1); + } + XFree (kids); + + if (xwin->num_clips != 0) + xwin->ov_conf = TRUE; + + XSetErrorHandler (old_handler); +} + + +static gboolean +gst_xwin_window (GstXWindowListener *xwin) +{ + if (xwin->ov_map && xwin->ov_wmmap && + xwin->ov_visibility != VisibilityFullyObscured) { + /* visible */ + if (xwin->ov_visibility == VisibilityPartiallyObscured) { + /* set clips */ + gst_xwin_set_clips (xwin); + } + + if (xwin->ov_conf) { + xwin->set_window_func (xwin->private_data, + xwin->x, xwin->y, + xwin->w, xwin->h, + xwin->clips, xwin->num_clips); + + if (!xwin->ov_visible) + gst_xwin_set_overlay (xwin, TRUE); + + g_mutex_lock (xwin->main_lock); + + if (xwin->ov_refresh_id) + g_source_remove (xwin->ov_refresh_id); + xwin->ov_refresh_id = + g_timeout_add (200, (GSourceFunc) gst_xwin_refresh, + (gpointer) xwin); + + xwin->ov_conf = FALSE; + + g_mutex_unlock (xwin->main_lock); + } + } else { + /* not visible */ + if (xwin->ov_conf && xwin->ov_visible) { + gst_xwin_set_overlay (xwin, FALSE); + + g_mutex_lock (xwin->main_lock); + + if (xwin->ov_refresh_id) + g_source_remove (xwin->ov_refresh_id); + xwin->ov_refresh_id = + g_timeout_add (200, (GSourceFunc) gst_xwin_refresh, + (gpointer) xwin); + + xwin->ov_conf = FALSE; + + g_mutex_unlock (xwin->main_lock); + } + } + + xwin->ov_conf_id = 0; + + /* once is enough */ + return FALSE; +} + +static void +gst_xwin_configure (GstXWindowListener *xwin) +{ +#if 0 + /* This part is disabled, because the idle task will be done + * in the main thread instead of here. */ + if (!xwin->ov_conf_id) + xwin->ov_conf_id = + g_idle_add ((GSourceFunc) gst_rec_xoverlay_window, + (gpointer) xwin); +#endif + + gst_xwin_window ((gpointer) xwin); +} + +static void +gst_xwin_resize (GstXWindowListener *xwin) +{ + Drawable drawable, parent, *kids, root; + guint numkids; + XWindowAttributes attr; + + XGetWindowAttributes (xwin->display, + xwin->xwindow_id, &attr); + XMoveResizeWindow (xwin->display, xwin->child, + 0, 0, attr.width, attr.height); + + /* set the video window - the first clip is our own window */ + xwin->x = 0; + xwin->y = 0; + xwin->w = attr.width; + xwin->h = attr.height; + + drawable = xwin->child; + while (1) { + XQueryTree (xwin->display, drawable, + &root, &parent, &kids, &numkids); + if (numkids) + XFree(kids); + drawable = parent; + XGetWindowAttributes (xwin->display, drawable, &attr); + xwin->x += attr.x; + xwin->y += attr.y; + if (parent == attr.root) + break; + } + + xwin->ov_conf = TRUE; + xwin->ov_move = TRUE; + + gst_xwin_configure (xwin); +} + +static void +gst_xwin_init_window (GstXWindowListener *xwin) +{ + XWindowAttributes attr; + + /* start values */ + xwin->ov_conf = TRUE; + xwin->ov_map = xwin->ov_wmmap = TRUE; + xwin->ov_move = TRUE; + xwin->ov_refresh = FALSE; + g_mutex_lock (xwin->main_lock); + xwin->ov_conf_id = xwin->ov_refresh_id = 0; + g_mutex_unlock (xwin->main_lock); + xwin->ov_visibility = VisibilityFullyObscured; + + /* start the memory that we'll use */ + xwin->clips = g_malloc (sizeof (GstXWindowClip) * NUM_CLIPS); + xwin->num_clips = 0; + + /* open connection to X server */ + xwin->display = XOpenDisplay (xwin->display_name); + + /* window */ + XGetWindowAttributes (xwin->display, + xwin->xwindow_id, &attr); + xwin->child = XCreateSimpleWindow (xwin->display, + xwin->xwindow_id, 0, 0, + attr.width, attr.height, 0, 0, 0); + + /* listen to certain X events */ + XSelectInput (xwin->display, xwin->xwindow_id, + StructureNotifyMask); + XSelectInput (xwin->display, xwin->child, + VisibilityChangeMask | StructureNotifyMask); + XSelectInput (xwin->display, DefaultRootWindow (xwin->display), + VisibilityChangeMask | StructureNotifyMask | + SubstructureNotifyMask); + + /* show */ + XMapWindow (xwin->display, xwin->child); + + gst_xwin_resize (xwin); +} + +static void +gst_xwin_exit_window (GstXWindowListener *xwin) +{ + /* disable overlay */ + gst_xwin_set_overlay (xwin, FALSE); + + /* delete idle funcs */ + if (xwin->ov_conf_id != 0) + g_source_remove (xwin->ov_conf_id); + + g_mutex_lock (xwin->main_lock); + if (xwin->ov_refresh_id != 0) + g_source_remove (xwin->ov_refresh_id); + g_mutex_unlock (xwin->main_lock); + + /* get away from X and free mem */ + XDestroyWindow (xwin->display, xwin->child); + XCloseDisplay (xwin->display); + g_free (xwin->clips); +} + +static gpointer +gst_xwin_thread (gpointer data) +{ + GstXWindowListener *xwin = GST_X_WINDOW_LISTENER (data); + XEvent event; + + /* Hi, I'm GStreamer. What's your name? */ + gst_xwin_init_window (xwin); + + while (xwin->cycle) { + XNextEvent (xwin->display, &event); + + if (!xwin->cycle) + break; + + if ((event.type == ConfigureNotify && + event.xconfigure.window == xwin->xwindow_id) || + (event.type == MapNotify && + event.xmap.window == xwin->xwindow_id) || + (event.type == UnmapNotify && + event.xunmap.window == xwin->xwindow_id)) { + /* the 'parent' window, i.e. the widget provided by client */ + switch (event.type) { + case MapNotify: + xwin->ov_map = TRUE; + xwin->ov_conf = TRUE; + gst_xwin_configure (xwin); + break; + + case UnmapNotify: + xwin->ov_map = FALSE; + xwin->ov_conf = TRUE; + gst_xwin_configure (xwin); + break; + + case ConfigureNotify: + gst_xwin_resize (xwin); + break; + + default: + /* nothing */ + break; + } + } else if (event.xany.window == xwin->child) { + /* our own private window */ + switch (event.type) { + case Expose: + if (!event.xexpose.count) { + if (xwin->ov_refresh) { + xwin->ov_refresh = FALSE; + } else { + xwin->ov_conf = TRUE; + gst_xwin_configure (xwin); + } + } + break; + + case VisibilityNotify: + xwin->ov_visibility = event.xvisibility.state; + if (xwin->ov_refresh) { + if (event.xvisibility.state != VisibilityFullyObscured) + xwin->ov_refresh = FALSE; + } else { + xwin->ov_conf = TRUE; + gst_xwin_configure (xwin); + } + break; + + default: + /* nothing */ + break; + } + } else { + /* root window */ + switch (event.type) { + case MapNotify: + case UnmapNotify: + /* are we still visible? */ + if (!xwin->ov_refresh) { + XWindowAttributes attr; + gboolean on; + XGetWindowAttributes (xwin->display, + xwin->xwindow_id, &attr); + on = (attr.map_state == IsViewable); + xwin->ov_wmmap = on; + xwin->ov_conf = TRUE; + gst_xwin_configure (xwin); + } + break; + + case ConfigureNotify: + if (!xwin->ov_refresh) { + gst_xwin_resize (xwin); + } + break; + + default: + /* nothing */ + break; + } + } + } + + /* Nice to have met you, see you later */ + gst_xwin_exit_window (xwin); + + g_thread_exit (NULL); + + return NULL; +} + +static void +gst_xwin_start (GstXWindowListener *xwin) +{ + DEBUG ("Starting XWindow listener"); + + xwin->cycle = TRUE; + /* we use this main_display for two things: first of all, + * the window needs to be 'refreshed' to remove artifacts + * after every move. Secondly, we use this to 'unhang' the + * event handler after we've stopped it */ + xwin->main_lock = g_mutex_new (); + xwin->main_display = XOpenDisplay (xwin->display_name); + xwin->thread = g_thread_create (gst_xwin_thread, + (gpointer) xwin, + TRUE, NULL); + + DEBUG ("Started X-overlay"); +} + +static void +gst_xwin_stop (GstXWindowListener *xwin) +{ + DEBUG ("Stopping XWindow listener"); + + xwin->cycle = FALSE; + /* now, the event loop will hang. To prevent this from hanging + * our app, app, we re-do our refresh hack. Oh man, this is + * ugly. But it works. :). */ + g_mutex_lock (xwin->main_lock); + if (xwin->ov_refresh_id) + g_source_remove (xwin->ov_refresh_id); + g_mutex_unlock (xwin->main_lock); + + gst_xwin_refresh ((gpointer) xwin); + g_thread_join (xwin->thread); + XCloseDisplay (xwin->main_display); + g_mutex_free (xwin->main_lock); + + DEBUG ("Stopped X-overlay"); +} + +/* + * End of code inspired by XawTV. + */ + +static gboolean +plugin_init (GModule *module, + GstPlugin *plugin) +{ + gst_plugin_set_longname (plugin, + "X11-based XWindow event/motion listener"); + return TRUE; +} + +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "xwindowlistener", + plugin_init +}; diff --git a/gst-libs/gst/xwindowlistener/xwindowlistener.h b/gst-libs/gst/xwindowlistener/xwindowlistener.h new file mode 100644 index 00000000..834be67c --- /dev/null +++ b/gst-libs/gst/xwindowlistener/xwindowlistener.h @@ -0,0 +1,116 @@ +/* G-Streamer X11 Window event/motion listener + * Copyright (C) 2003 Ronald Bultje + * + * xwindowlistener.h: object definition + * + * 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 __X_WINDOW_LISTENER_H__ +#define __X_WINDOW_LISTENER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_X_WINDOW_LISTENER \ + (gst_x_window_listener_get_type()) +#define GST_X_WINDOW_LISTENER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_X_WINDOW_LISTENER, \ + GstXWindowListener)) +#define GST_X_WINDOW_LISTENER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_X_WINDOW_LISTENER, \ + GstXWindowListenerClass)) +#define GST_IS_X_WINDOW_LISTENER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_X_WINDOW_LISTENER)) +#define GST_IS_X_WINDOW_LISTENER_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_X_WINDOW_LISTENER)) + +typedef struct _GstXWindowListener GstXWindowListener; +typedef struct _GstXWindowListenerClass GstXWindowListenerClass; +typedef struct _GstXWindowClip GstXWindowClip; +typedef void (* MapWindowFunc) (gpointer your_data, + gboolean visible); +typedef void (* SetWindowFunc) (gpointer your_data, + gint x, gint y, + gint w, gint h, + GstXWindowClip *clips, + gint num_clips); + +struct _GstXWindowClip { + gint32 x_offset, + y_offset, + width, + height; + gpointer data; +}; + +struct _GstXWindowListener { + GObject parent; + + /* "per-instance virtual functions" */ + MapWindowFunc map_window_func; + SetWindowFunc set_window_func; + + /* private data with which we call the virtual functions */ + gpointer private_data; + + /* general information of what we're doing */ + gchar *display_name; + XID xwindow_id; + + /* one extra... */ + Display *main_display; + GMutex *main_lock; + + /* oh my g*d, this is going to be so horribly ugly */ + GThread *thread; + gboolean cycle; + + /* the overlay window + own thread */ + Display *display; + Drawable child; + gboolean ov_conf, + ov_map, + ov_visible, + ov_refresh, + ov_move, + ov_wmmap; + gint ov_visibility; + guint ov_conf_id, + ov_refresh_id; + gint x, y, w, h; + GstXWindowClip *clips; + gint num_clips; +}; + +struct _GstXWindowListenerClass { + GObjectClass parent; +}; + +GType gst_x_window_listener_get_type (void); +GstXWindowListener * + gst_x_window_listener_new (gchar *display, + MapWindowFunc map_window_func, + SetWindowFunc set_window_func, + gpointer private_data); +void gst_x_window_listener_set_xid (GstXWindowListener *xwin, + XID id); + +G_END_DECLS + +#endif /* __X_WINDOW_LISTENER_H__ */ diff --git a/sys/v4l2/gstv4l2colorbalance.c b/sys/v4l2/gstv4l2colorbalance.c new file mode 100644 index 00000000..d0c1dcf8 --- /dev/null +++ b/sys/v4l2/gstv4l2colorbalance.c @@ -0,0 +1,151 @@ +/* GStreamer Color Balance interface implementation + * Copyright (C) 2003 Ronald Bultje + * + * gstv4l2colorbalance.c: color balance interface implementation for V4L2 + * + * 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 +#include "gstv4l2colorbalance.h" +#include "gstv4l2element.h" + +static void +gst_v4l2_color_balance_channel_class_init(GstV4l2ColorBalanceChannelClass *klass); +static void +gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel *channel); + +static const GList * +gst_v4l2_color_balance_list_channels (GstColorBalance *balance); +static void +gst_v4l2_color_balance_set_value (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value); +static gint +gst_v4l2_color_balance_get_value (GstColorBalance *balance, + GstColorBalanceChannel *channel); + +static GstColorBalanceChannelClass *parent_class = NULL; + +GType +gst_v4l2_color_balance_channel_get_type (void) +{ + static GType gst_v4l2_color_balance_channel_type = 0; + + if (!gst_v4l2_color_balance_channel_type) { + static const GTypeInfo v4l2_tuner_channel_info = { + sizeof (GstV4l2ColorBalanceChannelClass), + NULL, + NULL, + (GClassInitFunc) gst_v4l2_color_balance_channel_class_init, + NULL, + NULL, + sizeof (GstV4l2ColorBalanceChannel), + 0, + (GInstanceInitFunc) gst_v4l2_color_balance_channel_init, + NULL + }; + + gst_v4l2_color_balance_channel_type = + g_type_register_static (GST_TYPE_COLOR_BALANCE_CHANNEL, + "GstV4l2ColorBalanceChannel", + &v4l2_tuner_channel_info, 0); + } + + return gst_v4l2_color_balance_channel_type; +} + +static void +gst_v4l2_color_balance_channel_class_init (GstV4l2ColorBalanceChannelClass *klass) +{ + parent_class = g_type_class_ref (GST_TYPE_COLOR_BALANCE_CHANNEL); +} + +static void +gst_v4l2_color_balance_channel_init (GstV4l2ColorBalanceChannel *channel) +{ + channel->index = 0; +} + +void +gst_v4l2_color_balance_interface_init (GstColorBalanceClass *klass) +{ + /* default virtual functions */ + klass->list_channels = gst_v4l2_color_balance_list_channels; + klass->set_value = gst_v4l2_color_balance_set_value; + klass->get_value = gst_v4l2_color_balance_get_value; +} + +static gboolean +gst_v4l2_color_balance_contains_channel (GstV4l2Element *v4l2element, + GstV4l2ColorBalanceChannel *v4l2channel) +{ + const GList *item; + + for (item = v4l2element->colors; item != NULL; item = item->next) + if (item->data == v4l2channel) + return TRUE; + + return FALSE; +} + +static const GList * +gst_v4l2_color_balance_list_channels (GstColorBalance *balance) +{ + return GST_V4L2ELEMENT (balance)->colors; +} + +static void +gst_v4l2_color_balance_set_value (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (balance); + GstV4l2ColorBalanceChannel *v4l2channel = + GST_V4L2_COLOR_BALANCE_CHANNEL (channel); + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element)); + g_return_if_fail (gst_v4l2_color_balance_contains_channel (v4l2element, + v4l2channel)); + + gst_v4l2_set_attribute (v4l2element, v4l2channel->index, value); +} + +static gint +gst_v4l2_color_balance_get_value (GstColorBalance *balance, + GstColorBalanceChannel *channel) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (balance); + GstV4l2ColorBalanceChannel *v4l2channel = + GST_V4L2_COLOR_BALANCE_CHANNEL (channel); + gint value; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), 0); + g_return_val_if_fail (gst_v4l2_color_balance_contains_channel (v4l2element, + v4l2channel), + 0); + + if (!gst_v4l2_get_attribute (v4l2element, v4l2channel->index, &value)) + return 0; + + return value; +} diff --git a/sys/v4l2/gstv4l2colorbalance.h b/sys/v4l2/gstv4l2colorbalance.h new file mode 100644 index 00000000..4003203b --- /dev/null +++ b/sys/v4l2/gstv4l2colorbalance.h @@ -0,0 +1,58 @@ +/* G-Streamer generic V4L2 element - Color Balance interface implementation + * Copyright (C) 2003 Ronald Bultje + * + * gstv4l2colorbalance.h: color balance interface implementation for V4L2 + * + * 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_V4L2_COLOR_BALANCE_H__ +#define __GST_V4L2_COLOR_BALANCE_H__ + +#include +#include +#include "v4l2_calls.h" + +G_BEGIN_DECLS + +#define GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL \ + (gst_v4l2_color_balance_channel_get_type ()) +#define GST_V4L2_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \ + GstV4l2ColorBalanceChannel)) +#define GST_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, \ + GstV4l2ColorBalanceChannelClass)) +#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL)) +#define GST_IS_V4L2_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL)) + +typedef struct _GstV4l2ColorBalanceChannel { + GstColorBalanceChannel parent; + + guint32 index; +} GstV4l2ColorBalanceChannel; + +typedef struct _GstV4l2ColorBalanceChannelClass { + GstColorBalanceChannelClass parent; +} GstV4l2ColorBalanceChannelClass; + +GType gst_v4l2_color_balance_channel_get_type (void); + +void gst_v4l2_color_balance_interface_init (GstColorBalanceClass *klass); + +#endif /* __GST_V4L2_COLOR_BALANCE_H__ */ diff --git a/sys/v4l2/gstv4l2element-marshal.list b/sys/v4l2/gstv4l2element-marshal.list deleted file mode 100644 index 43211212..00000000 --- a/sys/v4l2/gstv4l2element-marshal.list +++ /dev/null @@ -1,3 +0,0 @@ -BOOLEAN:INT,INT,INT,INT,POINTER,INT -BOOLEAN:STRING,INT -BOOLEAN:STRING,POINTER diff --git a/sys/v4l2/gstv4l2element.c b/sys/v4l2/gstv4l2element.c index 9ff553ce..35f06290 100644 --- a/sys/v4l2/gstv4l2element.c +++ b/sys/v4l2/gstv4l2element.c @@ -22,12 +22,14 @@ #endif #include "v4l2_calls.h" -#include "gstv4l2element-marshal.h" +#include "gstv4l2tuner.h" +#include "gstv4l2xoverlay.h" +#include "gstv4l2colorbalance.h" /* elementfactory details */ static GstElementDetails gst_v4l2element_details = { "Generic video4linux2 Element", - "None/Video", + "Generic/Video", "LGPL", "Generic plugin for handling common video4linux2 calls", VERSION, @@ -40,52 +42,65 @@ enum { /* FILL ME */ SIGNAL_OPEN, SIGNAL_CLOSE, - SIGNAL_SET_VIDEOWINDOW, - SIGNAL_GET_ATTRIBUTE, - SIGNAL_SET_ATTRIBUTE, LAST_SIGNAL }; enum { ARG_0, - ARG_CHANNEL, - ARG_CHANNEL_NAMES, - ARG_OUTPUT, - ARG_OUTPUT_NAMES, - ARG_NORM, - ARG_NORM_NAMES, - ARG_HAS_TUNER, - ARG_FREQUENCY, - ARG_SIGNAL_STRENGTH, - ARG_HAS_AUDIO, - ARG_ATTRIBUTES, ARG_DEVICE, ARG_DEVICE_NAME, - ARG_DEVICE_HAS_CAPTURE, - ARG_DEVICE_HAS_OVERLAY, - ARG_DEVICE_HAS_PLAYBACK, - ARG_DISPLAY, - ARG_DO_OVERLAY, + ARG_FLAGS }; -static void gst_v4l2element_class_init (GstV4l2ElementClass *klass); -static void gst_v4l2element_init (GstV4l2Element *v4lelement); -static void gst_v4l2element_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void gst_v4l2element_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); -static GstElementStateReturn gst_v4l2element_change_state (GstElement *element); +static void gst_v4l2element_class_init (GstV4l2ElementClass *klass); +static void gst_v4l2element_init (GstV4l2Element *v4lelement); +static void gst_v4l2element_dispose (GObject *object); +static void gst_v4l2element_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gst_v4l2element_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); +static GstElementStateReturn + gst_v4l2element_change_state (GstElement *element); static GstElementClass *parent_class = NULL; static guint gst_v4l2element_signals[LAST_SIGNAL] = { 0 }; +static gboolean +gst_v4l2_iface_supported (GstInterface *iface, + GType iface_type) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (iface); + + g_assert (iface_type == GST_TYPE_TUNER || + iface_type == GST_TYPE_X_OVERLAY || + iface_type == GST_TYPE_COLOR_BALANCE); + + if (v4l2element->video_fd == -1) + return FALSE; + + if (iface_type == GST_TYPE_X_OVERLAY && + !GST_V4L2_IS_OVERLAY(v4l2element)) + return FALSE; + + return TRUE; +} + + +static void +gst_v4l2_interface_init (GstInterfaceClass *klass) +{ + /* default virtual functions */ + klass->supported = gst_v4l2_iface_supported; +} + + GType gst_v4l2element_get_type (void) { @@ -104,13 +119,78 @@ gst_v4l2element_get_type (void) (GInstanceInitFunc) gst_v4l2element_init, NULL }; - v4l2element_type = g_type_register_static(GST_TYPE_ELEMENT, - "GstV4l2Element", &v4l2element_info, 0); + static const GInterfaceInfo v4l2iface_info = { + (GInterfaceInitFunc) gst_v4l2_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo v4l2_tuner_info = { + (GInterfaceInitFunc) gst_v4l2_tuner_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo v4l2_xoverlay_info = { + (GInterfaceInitFunc) gst_v4l2_xoverlay_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo v4l2_colorbalance_info = { + (GInterfaceInitFunc) gst_v4l2_color_balance_interface_init, + NULL, + NULL, + }; + + v4l2element_type = + g_type_register_static(GST_TYPE_ELEMENT, + "GstV4l2Element", &v4l2element_info, 0); + + g_type_add_interface_static (v4l2element_type, + GST_TYPE_INTERFACE, + &v4l2iface_info); + g_type_add_interface_static (v4l2element_type, + GST_TYPE_TUNER, + &v4l2_tuner_info); + g_type_add_interface_static (v4l2element_type, + GST_TYPE_X_OVERLAY, + &v4l2_xoverlay_info); + g_type_add_interface_static (v4l2element_type, + GST_TYPE_COLOR_BALANCE, + &v4l2_colorbalance_info); } + return v4l2element_type; } +#define GST_TYPE_V4L2_DEVICE_FLAGS (gst_v4l2_device_get_type ()) +GType +gst_v4l2_device_get_type (void) +{ + static GType v4l2_device_type = 0; + + if (v4l2_device_type == 0) { + static const GFlagsValue values[] = { + { V4L2_CAP_VIDEO_CAPTURE, "CAPTURE", + "Device can capture" }, + { V4L2_CAP_VIDEO_OUTPUT, "PLAYBACK", + "Device can playback" }, + { V4L2_CAP_VIDEO_OVERLAY, "OVERLAY", + "Device can do overlay" }, + { V4L2_CAP_TUNER, "TUNER", + "Device has a tuner" }, + { V4L2_CAP_AUDIO, "AUDIO", + "Device handles audio" }, + { 0, NULL, NULL } + }; + + v4l2_device_type = + g_flags_register_static ("GstV4l2DeviceTypeFlags", + values); + } + + return v4l2_device_type; +} + static void gst_v4l2element_class_init (GstV4l2ElementClass *klass) @@ -123,96 +203,15 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass) parent_class = g_type_class_ref(GST_TYPE_ELEMENT); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL, - g_param_spec_int("channel","channel","channel", - G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CHANNEL_NAMES, - g_param_spec_pointer("channel_names","channel_names","channel_names", - G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT, - g_param_spec_int("output","output","output", - G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT_NAMES, - g_param_spec_pointer("output_names","output_names","output_names", - G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM, - g_param_spec_int("norm","norm","norm", - G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NORM_NAMES, - g_param_spec_pointer("norm_names","norm_names","norm_names", - G_PARAM_READABLE)); - - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_TUNER, - g_param_spec_boolean("has_tuner","has_tuner","has_tuner", - 0,G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FREQUENCY, - g_param_spec_ulong("frequency","frequency","frequency", - 0,G_MAXULONG,0,G_PARAM_READWRITE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SIGNAL_STRENGTH, - g_param_spec_ulong("signal_strength","signal_strength","signal_strength", - 0,G_MAXULONG,0,G_PARAM_READABLE)); - - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HAS_AUDIO, - g_param_spec_boolean("has_audio","has_audio","has_audio", - 0,G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ATTRIBUTES, - g_param_spec_pointer("attributes","attributes","attributes", - G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE, - g_param_spec_string("device","device","device", - NULL, G_PARAM_READWRITE)); + g_param_spec_string("device", "Device", "Device location", + NULL, G_PARAM_READWRITE)); g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_NAME, - g_param_spec_string("device_name","device_name","device_name", - NULL, G_PARAM_READABLE)); - - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_CAPTURE, - g_param_spec_boolean("can_capture","can_capture","can_capture", - 0,G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_PLAYBACK, - g_param_spec_boolean("can_playback","can_playback","can_playback", - 0,G_PARAM_READABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DEVICE_HAS_OVERLAY, - g_param_spec_boolean("has_overlay","has_overlay","has_overlay", - 0,G_PARAM_READABLE)); - - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DISPLAY, - g_param_spec_string("display","display","display", - NULL, G_PARAM_WRITABLE)); - g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_DO_OVERLAY, - g_param_spec_boolean("do_overlay","do_overlay","do_overlay", - 0,G_PARAM_WRITABLE)); - - /* actions */ - gst_v4l2element_signals[SIGNAL_SET_VIDEOWINDOW] = - g_signal_new ("set_videowindow", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET(GstV4l2ElementClass, set_videowindow), - NULL, NULL, - gstv4l2_cclosure_marshal_BOOLEAN__INT_INT_INT_INT_POINTER_INT, - G_TYPE_BOOLEAN, 6, - G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, - G_TYPE_POINTER, G_TYPE_INT); - klass->set_videowindow = gst_v4l2_set_window; - gst_v4l2element_signals[SIGNAL_GET_ATTRIBUTE] = - g_signal_new ("get_attribute", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET(GstV4l2ElementClass, get_attribute), - NULL, NULL, - gstv4l2_cclosure_marshal_BOOLEAN__STRING_POINTER, - G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_POINTER); - klass->get_attribute = gst_v4l2_get_attribute; - gst_v4l2element_signals[SIGNAL_SET_ATTRIBUTE] = - g_signal_new ("set_attribute", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET(GstV4l2ElementClass, set_attribute), - NULL, NULL, - gstv4l2_cclosure_marshal_BOOLEAN__STRING_INT, - G_TYPE_BOOLEAN, 2, G_TYPE_STRING, G_TYPE_INT); - klass->set_attribute = gst_v4l2_set_attribute; + g_param_spec_string("device_name", "Device name", + "Name of the device", NULL, G_PARAM_READABLE)); + g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FLAGS, + g_param_spec_flags("flags", "Flags", "Device type flags", + GST_TYPE_V4L2_DEVICE_FLAGS, 0, G_PARAM_READABLE)); /* signals */ gst_v4l2element_signals[SIGNAL_OPEN] = @@ -228,6 +227,7 @@ gst_v4l2element_class_init (GstV4l2ElementClass *klass) gobject_class->set_property = gst_v4l2element_set_property; gobject_class->get_property = gst_v4l2element_get_property; + gobject_class->dispose = gst_v4l2element_dispose; gstelement_class->change_state = gst_v4l2element_change_state; } @@ -239,25 +239,38 @@ gst_v4l2element_init (GstV4l2Element *v4l2element) /* some default values */ v4l2element->video_fd = -1; v4l2element->buffer = NULL; - v4l2element->device = NULL; - - v4l2element->norm = -1; - v4l2element->channel = -1; - v4l2element->output = -1; - v4l2element->frequency = 0; - - v4l2element->controls = NULL; - v4l2element->menus = NULL; - v4l2element->control_specs = NULL; - v4l2element->outputs = NULL; - v4l2element->output_names = NULL; - v4l2element->inputs = NULL; - v4l2element->input_names = NULL; + v4l2element->device = g_strdup("/dev/video"); + v4l2element->display = g_strdup(g_getenv("DISPLAY")); + + v4l2element->channels = NULL; v4l2element->norms = NULL; - v4l2element->norm_names = NULL; + v4l2element->colors = NULL; + + v4l2element->overlay = gst_v4l2_xoverlay_new(v4l2element); } +static void +gst_v4l2element_dispose (GObject *object) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT(object); + + if (v4l2element->overlay) { + gst_v4l2_xoverlay_free(v4l2element); + } + + if (v4l2element->display) { + g_free (v4l2element->display); + } + + if (v4l2element->device) { + g_free (v4l2element->device); + } + + if (((GObjectClass *) parent_class)->dispose) + ((GObjectClass *) parent_class)->dispose(object); +} + static void gst_v4l2element_set_property (GObject *object, guint prop_id, @@ -271,34 +284,6 @@ gst_v4l2element_set_property (GObject *object, v4l2element = GST_V4L2ELEMENT(object); switch (prop_id) { - case ARG_CHANNEL: - v4l2element->channel = g_value_get_int(value); - if (GST_V4L2_IS_OPEN(v4l2element) && !GST_V4L2_IS_ACTIVE(v4l2element)) { - if (!gst_v4l2_set_input(v4l2element, g_value_get_int(value))) - return; - } - break; - case ARG_OUTPUT: - v4l2element->output = g_value_get_int(value); - if (GST_V4L2_IS_OPEN(v4l2element) && !GST_V4L2_IS_ACTIVE(v4l2element)) { - if (!gst_v4l2_set_output(v4l2element, g_value_get_int(value))) - return; - } - break; - case ARG_NORM: - v4l2element->norm = g_value_get_int(value); - if (GST_V4L2_IS_OPEN(v4l2element) && !GST_V4L2_IS_ACTIVE(v4l2element)) { - if (!gst_v4l2_set_norm(v4l2element, g_value_get_int(value))) - return; - } - break; - case ARG_FREQUENCY: - v4l2element->frequency = g_value_get_ulong(value); - if (GST_V4L2_IS_OPEN(v4l2element) && !GST_V4L2_IS_ACTIVE(v4l2element)) { - if (!gst_v4l2_set_frequency(v4l2element, g_value_get_ulong(value))) - return; - } - break; case ARG_DEVICE: if (!GST_V4L2_IS_OPEN(v4l2element)) { if (v4l2element->device) @@ -306,16 +291,6 @@ gst_v4l2element_set_property (GObject *object, v4l2element->device = g_strdup(g_value_get_string(value)); } break; - case ARG_DISPLAY: - if (!gst_v4l2_set_display(v4l2element, g_value_get_string(value))) - return; - break; - case ARG_DO_OVERLAY: - if (GST_V4L2_IS_OPEN(v4l2element)) { - if (!gst_v4l2_enable_overlay(v4l2element, g_value_get_boolean(value))) - return; - } - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -330,88 +305,31 @@ gst_v4l2element_get_property (GObject *object, GParamSpec *pspec) { GstV4l2Element *v4l2element; - gint temp_i = 0; - gulong temp_ul = 0; /* it's not null if we got it, but it might not be ours */ g_return_if_fail(GST_IS_V4L2ELEMENT(object)); v4l2element = GST_V4L2ELEMENT(object); switch (prop_id) { - case ARG_CHANNEL: - if (GST_V4L2_IS_OPEN(v4l2element)) - gst_v4l2_get_input(v4l2element, &temp_i); - g_value_set_int(value, temp_i); - break; - case ARG_CHANNEL_NAMES: - g_value_set_pointer(value, v4l2element->input_names); - break; - case ARG_OUTPUT: - if (GST_V4L2_IS_OPEN(v4l2element)) - gst_v4l2_get_output(v4l2element, &temp_i); - g_value_set_int(value, temp_i); - break; - case ARG_OUTPUT_NAMES: - g_value_set_pointer(value, v4l2element->output_names); - break; - case ARG_NORM: - if (GST_V4L2_IS_OPEN(v4l2element)) - gst_v4l2_get_norm(v4l2element, &temp_i); - g_value_set_int(value, temp_i); - break; - case ARG_NORM_NAMES: - g_value_set_pointer(value, v4l2element->norm_names); - break; - case ARG_HAS_TUNER: - if (GST_V4L2_IS_OPEN(v4l2element)) - g_value_set_boolean(value, - gst_v4l2_has_tuner(v4l2element, &temp_i)); - break; - case ARG_FREQUENCY: - if (GST_V4L2_IS_OPEN(v4l2element)) - gst_v4l2_get_frequency(v4l2element, &temp_ul); - g_value_set_ulong(value, temp_ul); - break; - case ARG_SIGNAL_STRENGTH: - if (GST_V4L2_IS_OPEN(v4l2element)) - gst_v4l2_signal_strength(v4l2element, &temp_ul); - g_value_set_ulong(value, temp_ul); - break; - case ARG_HAS_AUDIO: - if (GST_V4L2_IS_OPEN(v4l2element)) - temp_i = gst_v4l2_has_audio(v4l2element); - g_value_set_boolean(value, temp_i>0?TRUE:FALSE); - break; - case ARG_ATTRIBUTES: - g_value_set_pointer(value, v4l2element->control_specs); - break; case ARG_DEVICE: g_value_set_string(value, v4l2element->device); break; - case ARG_DEVICE_NAME: + case ARG_DEVICE_NAME: { + gchar *new = NULL; if (GST_V4L2_IS_OPEN(v4l2element)) - g_value_set_string(value, v4l2element->vcap.card); - break; - case ARG_DEVICE_HAS_CAPTURE: - if (GST_V4L2_IS_OPEN(v4l2element) && - v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE && - v4l2element->vcap.capabilities & V4L2_CAP_STREAMING) - temp_i = 1; - g_value_set_boolean(value, temp_i>0?TRUE:FALSE); - break; - case ARG_DEVICE_HAS_OVERLAY: - if (GST_V4L2_IS_OPEN(v4l2element) && - v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY) - temp_i = 1; - g_value_set_boolean(value, temp_i>0?TRUE:FALSE); + new = v4l2element->vcap.card; + g_value_set_string(value, new); break; - case ARG_DEVICE_HAS_PLAYBACK: - if (GST_V4L2_IS_OPEN(v4l2element) && - v4l2element->vcap.capabilities & V4L2_CAP_VIDEO_OUTPUT && - v4l2element->vcap.capabilities & V4L2_CAP_STREAMING) - temp_i = 1; - g_value_set_boolean(value, temp_i>0?TRUE:FALSE); + } + case ARG_FLAGS: { + guint flags = 0; + if (GST_V4L2_IS_OPEN(v4l2element)) { + flags |= v4l2element->vcap.capabilities & + 30007; + } + g_value_set_flags(value, flags); break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -433,29 +351,21 @@ gst_v4l2element_change_state (GstElement *element) */ switch (GST_STATE_TRANSITION(element)) { case GST_STATE_NULL_TO_READY: + gst_v4l2_set_display(v4l2element); + if (!gst_v4l2_open(v4l2element)) return GST_STATE_FAILURE; + gst_v4l2_xoverlay_open(v4l2element); + /* emit a signal! whoopie! */ g_signal_emit(G_OBJECT(v4l2element), gst_v4l2element_signals[SIGNAL_OPEN], 0, v4l2element->device); - - /* now, sync options */ - if (v4l2element->norm >= 0) - if (!gst_v4l2_set_norm(v4l2element, v4l2element->norm)) - return GST_STATE_FAILURE; - if (v4l2element->channel >= 0) - if (!gst_v4l2_set_input(v4l2element, v4l2element->channel)) - return GST_STATE_FAILURE; - if (v4l2element->output >= 0) - if (!gst_v4l2_set_output(v4l2element, v4l2element->output)) - return GST_STATE_FAILURE; - if (v4l2element->frequency > 0) - if (!gst_v4l2_set_frequency(v4l2element, v4l2element->frequency)) - return GST_STATE_FAILURE; break; case GST_STATE_READY_TO_NULL: + gst_v4l2_xoverlay_close(v4l2element); + if (!gst_v4l2_close(v4l2element)) return GST_STATE_FAILURE; @@ -478,6 +388,10 @@ gst_v4l2element_factory_init (GstPlugin *plugin) { GstElementFactory *factory; + /* we can run without... But not yet. ;). */ + if (!gst_library_load ("xwindowlistener")) + return FALSE; + /* create an elementfactory for the v4l2element */ factory = gst_element_factory_new("v4l2element", GST_TYPE_V4L2ELEMENT, &gst_v4l2element_details); diff --git a/sys/v4l2/gstv4l2element.h b/sys/v4l2/gstv4l2element.h index 6d86d4a9..f6e19e7e 100644 --- a/sys/v4l2/gstv4l2element.h +++ b/sys/v4l2/gstv4l2element.h @@ -21,6 +21,7 @@ #define __GST_V4L2ELEMENT_H__ #include +#include /* Because of some really cool feature in video4linux1, also known as * 'not including sys/types.h and sys/time.h', we had to include it @@ -71,17 +72,16 @@ struct _GstV4l2Element { struct v4l2_capability vcap; /* the toys available to us */ - GList /*v4l2_input*/ *inputs, *input_names; - GList /*v4l2_output*/ *outputs, *output_names; - GList /*v4l2_enumstd*/ *norms, *norm_names; - GList /*v4l2_queryctrl*/ *controls, *control_specs; - GList /*GList:v4l2_querymenu*/ *menus; + GList *channels; + GList *norms; + GList *colors; + + /* X-overlay */ + GstXWindowListener *overlay; + XID xwindow_id; /* caching values */ - gint channel; - gint output; - gint norm; - gulong frequency; + gchar *display; }; struct _GstV4l2ElementClass { @@ -92,21 +92,6 @@ struct _GstV4l2ElementClass { const gchar *device); void (*close) (GstElement *element, const gchar *device); - - /* actions */ - gboolean (*set_videowindow) (GstElement *element, - gint x_offset, - gint y_offset, - gint height, - gint width, - struct v4l2_clip *clips, - gint num_clips); - gboolean (*get_attribute) (GstElement *element, - const gchar *attr_name, - int *value); - gboolean (*set_attribute) (GstElement *element, - const gchar *attr_name, - const int value); }; diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 7a0094bd..67b683e7 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -24,6 +24,7 @@ #include #include #include "v4l2src_calls.h" +#include "gstv4l2tuner.h" /* elementfactory details */ static GstElementDetails gst_v4l2src_details = { @@ -247,9 +248,8 @@ gst_v4l2src_close (GstElement *element, static gfloat gst_v4l2src_get_fps (GstV4l2Src *v4l2src) { - gint norm; - struct v4l2_standard *std; - gfloat fps; + v4l2_std_id norm; + const GList *item; if (!v4l2src->use_fixed_fps && v4l2src->clock != NULL && @@ -267,11 +267,14 @@ gst_v4l2src_get_fps (GstV4l2Src *v4l2src) if (!gst_v4l2_get_norm(GST_V4L2ELEMENT(v4l2src), &norm)) return 0.; + for (item = GST_V4L2ELEMENT(v4l2src)->norms; + item != NULL; item = item->next) { + GstV4l2TunerNorm *v4l2norm = item->data; + if (v4l2norm->index == norm) + return GST_TUNER_NORM(v4l2norm)->fps; + } - std = ((struct v4l2_standard *) g_list_nth_data(GST_V4L2ELEMENT(v4l2src)->norms, norm)); - fps = (1. * std->frameperiod.denominator) / std->frameperiod.numerator; - - return fps; + return 0.; } diff --git a/sys/v4l2/gstv4l2tuner.c b/sys/v4l2/gstv4l2tuner.c new file mode 100644 index 00000000..9cde6daa --- /dev/null +++ b/sys/v4l2/gstv4l2tuner.c @@ -0,0 +1,361 @@ +/* GStreamer Tuner interface implementation + * Copyright (C) 2003 Ronald Bultje + * + * gstv4l2tuner.c: tuner interface implementation for V4L2 + * + * 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 +#include + +#include "gstv4l2tuner.h" +#include "gstv4l2element.h" +#include "v4l2_calls.h" + +static void gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass *klass); +static void gst_v4l2_tuner_channel_init (GstV4l2TunerChannel *channel); + +static void gst_v4l2_tuner_norm_class_init (GstV4l2TunerNormClass *klass); +static void gst_v4l2_tuner_norm_init (GstV4l2TunerNorm *norm); + +static const GList * + gst_v4l2_tuner_list_channels (GstTuner *mixer); +static void gst_v4l2_tuner_set_channel (GstTuner *mixer, + GstTunerChannel *channel); +static const GstTunerChannel * + gst_v4l2_tuner_get_channel (GstTuner *mixer); + +static const GList * + gst_v4l2_tuner_list_norms (GstTuner *mixer); +static void gst_v4l2_tuner_set_norm (GstTuner *mixer, + GstTunerNorm *norm); +static const GstTunerNorm * + gst_v4l2_tuner_get_norm (GstTuner *mixer); + +static void gst_v4l2_tuner_set_frequency (GstTuner *mixer, + GstTunerChannel *channel, + gulong frequency); +static gulong gst_v4l2_tuner_get_frequency (GstTuner *mixer, + GstTunerChannel *channel); +static gint gst_v4l2_tuner_signal_strength (GstTuner *mixer, + GstTunerChannel *channel); + +static GstTunerNormClass *norm_parent_class = NULL; +static GstTunerChannelClass *channel_parent_class = NULL; + +GType +gst_v4l2_tuner_channel_get_type (void) +{ + static GType gst_v4l2_tuner_channel_type = 0; + + if (!gst_v4l2_tuner_channel_type) { + static const GTypeInfo v4l2_tuner_channel_info = { + sizeof (GstV4l2TunerChannelClass), + NULL, + NULL, + (GClassInitFunc) gst_v4l2_tuner_channel_class_init, + NULL, + NULL, + sizeof (GstV4l2TunerChannel), + 0, + (GInstanceInitFunc) gst_v4l2_tuner_channel_init, + NULL + }; + + gst_v4l2_tuner_channel_type = + g_type_register_static (GST_TYPE_TUNER_CHANNEL, + "GstV4l2TunerChannel", + &v4l2_tuner_channel_info, 0); + } + + return gst_v4l2_tuner_channel_type; +} + +static void +gst_v4l2_tuner_channel_class_init (GstV4l2TunerChannelClass *klass) +{ + channel_parent_class = g_type_class_ref (GST_TYPE_TUNER_CHANNEL); +} + +static void +gst_v4l2_tuner_channel_init (GstV4l2TunerChannel *channel) +{ + channel->index = 0; + channel->tuner = 0; + channel->audio = 0; +} + +GType +gst_v4l2_tuner_norm_get_type (void) +{ + static GType gst_v4l2_tuner_norm_type = 0; + + if (!gst_v4l2_tuner_norm_type) { + static const GTypeInfo v4l2_tuner_norm_info = { + sizeof (GstV4l2TunerNormClass), + NULL, + NULL, + (GClassInitFunc) gst_v4l2_tuner_norm_class_init, + NULL, + NULL, + sizeof (GstV4l2TunerNorm), + 0, + (GInstanceInitFunc) gst_v4l2_tuner_norm_init, + NULL + }; + + gst_v4l2_tuner_norm_type = + g_type_register_static (GST_TYPE_TUNER_NORM, + "GstV4l2TunerNorm", + &v4l2_tuner_norm_info, 0); + } + + return gst_v4l2_tuner_norm_type; +} + +static void +gst_v4l2_tuner_norm_class_init (GstV4l2TunerNormClass *klass) +{ + norm_parent_class = g_type_class_ref (GST_TYPE_TUNER_NORM); +} + +static void +gst_v4l2_tuner_norm_init (GstV4l2TunerNorm *norm) +{ + norm->index = 0; +} + +void +gst_v4l2_tuner_interface_init (GstTunerClass *klass) +{ + /* default virtual functions */ + klass->list_channels = gst_v4l2_tuner_list_channels; + klass->set_channel = gst_v4l2_tuner_set_channel; + klass->get_channel = gst_v4l2_tuner_get_channel; + + klass->list_norms = gst_v4l2_tuner_list_norms; + klass->set_norm = gst_v4l2_tuner_set_norm; + klass->get_norm = gst_v4l2_tuner_get_norm; + + klass->set_frequency = gst_v4l2_tuner_set_frequency; + klass->get_frequency = gst_v4l2_tuner_get_frequency; + klass->signal_strength = gst_v4l2_tuner_signal_strength; +} + +static gboolean +gst_v4l2_tuner_is_sink (GstV4l2Element *v4l2element) +{ + const GList *pads = gst_element_get_pad_list (GST_ELEMENT (v4l2element)); + GstPadDirection dir = GST_PAD_UNKNOWN; + + /* get direction */ + if (pads && g_list_length ((GList *) pads) == 1) + dir = GST_PAD_DIRECTION (GST_PAD (pads->data)); + + return (dir == GST_PAD_SINK); +} + +static gboolean +gst_v4l2_tuner_contains_channel (GstV4l2Element *v4l2element, + GstV4l2TunerChannel *v4l2channel) +{ + const GList *item; + + for (item = v4l2element->channels; item != NULL; item = item->next) + if (item->data == v4l2channel) + return TRUE; + + return FALSE; +} + +static const GList * +gst_v4l2_tuner_list_channels (GstTuner *mixer) +{ + /* ... or output, if we're a sink... */ + return GST_V4L2ELEMENT (mixer)->channels; +} + +static void +gst_v4l2_tuner_set_channel (GstTuner *mixer, + GstTunerChannel *channel) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer); + GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel); + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element)); + g_return_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, v4l2channel)); + + /* ... or output, if we're a sink... */ + if (gst_v4l2_tuner_is_sink (v4l2element)) + gst_v4l2_set_output (v4l2element, v4l2channel->index); + else + gst_v4l2_set_input (v4l2element, v4l2channel->index); +} + +static const GstTunerChannel * +gst_v4l2_tuner_get_channel (GstTuner *mixer) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer); + GList *item; + gint channel; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), NULL); + + /* ... or output, if we're a sink... */ + if (gst_v4l2_tuner_is_sink (v4l2element)) + gst_v4l2_get_output (v4l2element, &channel); + else + gst_v4l2_get_input (v4l2element, &channel); + + for (item = v4l2element->channels; item != NULL; item = item->next) { + if (channel == GST_V4L2_TUNER_CHANNEL (item->data)->index) + return (const GstTunerChannel *) item->data; + } + + return NULL; +} + +static gboolean +gst_v4l2_tuner_contains_norm (GstV4l2Element *v4l2element, + GstV4l2TunerNorm *v4l2norm) +{ + const GList *item; + + for (item = v4l2element->norms; item != NULL; item = item->next) + if (item->data == v4l2norm) + return TRUE; + + return FALSE; +} + +static const GList * +gst_v4l2_tuner_list_norms (GstTuner *mixer) +{ + return GST_V4L2ELEMENT (mixer)->norms; +} + +static void +gst_v4l2_tuner_set_norm (GstTuner *mixer, + GstTunerNorm *norm) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer); + GstV4l2TunerNorm *v4l2norm = GST_V4L2_TUNER_NORM (norm); + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element)); + g_return_if_fail (gst_v4l2_tuner_contains_norm (v4l2element, v4l2norm)); + + gst_v4l2_set_norm (v4l2element, v4l2norm->index); +} + +static const GstTunerNorm * +gst_v4l2_tuner_get_norm (GstTuner *mixer) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer); + GList *item; + v4l2_std_id norm; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), NULL); + + gst_v4l2_get_norm (v4l2element, &norm); + + for (item = v4l2element->norms; item != NULL; item = item->next) { + if (norm == GST_V4L2_TUNER_NORM (item->data)->index) + return (const GstTunerNorm *) item->data; + } + + return NULL; +} + +static void +gst_v4l2_tuner_set_frequency (GstTuner *mixer, + GstTunerChannel *channel, + gulong frequency) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer); + GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel); + gint chan; + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L2_IS_OPEN (v4l2element)); + g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY)); + g_return_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, v4l2channel)); + + gst_v4l2_get_input (v4l2element, &chan); + if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index && + GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) { + gst_v4l2_set_frequency (v4l2element, v4l2channel->tuner, frequency); + } +} + +static gulong +gst_v4l2_tuner_get_frequency (GstTuner *mixer, + GstTunerChannel *channel) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer); + GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel); + gint chan; + gulong frequency = 0; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), 0); + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, + v4l2channel), 0); + + gst_v4l2_get_input (v4l2element, &chan); + if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index && + GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) { + gst_v4l2_get_frequency (v4l2element, v4l2channel->tuner, &frequency); + } + + return frequency; +} + +static gint +gst_v4l2_tuner_signal_strength (GstTuner *mixer, + GstTunerChannel *channel) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (mixer); + GstV4l2TunerChannel *v4l2channel = GST_V4L2_TUNER_CHANNEL (channel); + gint chan; + gulong signal = 0; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L2_IS_OPEN (v4l2element), 0); + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + g_return_val_if_fail (gst_v4l2_tuner_contains_channel (v4l2element, + v4l2channel), 0); + + gst_v4l2_get_input (v4l2element, &chan); + if (chan == GST_V4L2_TUNER_CHANNEL (channel)->index && + GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) { + gst_v4l2_signal_strength (v4l2element, v4l2channel->tuner, &signal); + } + + return signal; +} diff --git a/sys/v4l2/gstv4l2tuner.h b/sys/v4l2/gstv4l2tuner.h new file mode 100644 index 00000000..a768ea2f --- /dev/null +++ b/sys/v4l2/gstv4l2tuner.h @@ -0,0 +1,85 @@ +/* G-Streamer generic V4L2 element - Tuner interface implementation + * Copyright (C) 2003 Ronald Bultje + * + * gstv4l2tuner.h: tuner interface implementation for V4L2 + * + * 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_V4L2_TUNER_H__ +#define __GST_V4L2_TUNER_H__ + +#include +#include + +#include "gstv4l2element.h" + +G_BEGIN_DECLS + +#define GST_TYPE_V4L2_TUNER_CHANNEL \ + (gst_v4l2_tuner_channel_get_type ()) +#define GST_V4L2_TUNER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_CHANNEL, \ + GstV4l2TunerChannel)) +#define GST_V4L2_TUNER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_CHANNEL, \ + GstV4l2TunerChannelClass)) +#define GST_IS_V4L2_TUNER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_CHANNEL)) +#define GST_IS_V4L2_TUNER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L2_TUNER_CHANNEL)) + +typedef struct _GstV4l2TunerChannel { + GstTunerChannel parent; + + guint32 index; + guint32 tuner; + guint32 audio; +} GstV4l2TunerChannel; + +typedef struct _GstV4l2TunerChannelClass { + GstTunerChannelClass parent; +} GstV4l2TunerChannelClass; + +#define GST_TYPE_V4L2_TUNER_NORM \ + (gst_v4l2_tuner_norm_get_type ()) +#define GST_V4L2_TUNER_NORM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_TUNER_NORM, \ + GstV4l2TunerNorm)) +#define GST_V4L2_TUNER_NORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L2_TUNER_NORM, \ + GstV4l2TunerNormClass)) +#define GST_IS_V4L2_TUNER_NORM(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_TUNER_NORM)) +#define GST_IS_V4L2_TUNER_NORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L2_TUNER_NORM)) + +typedef struct _GstV4l2TunerNorm { + GstTunerNorm parent; + + v4l2_std_id index; +} GstV4l2TunerNorm; + +typedef struct _GstV4l2TunerNormClass { + GstTunerNormClass parent; +} GstV4l2TunerNormClass; + +GType gst_v4l2_tuner_channel_get_type (void); +GType gst_v4l2_tuner_norm_get_type (void); + +void gst_v4l2_tuner_interface_init (GstTunerClass *klass); + +#endif /* __GST_V4L2_TUNER_H__ */ diff --git a/sys/v4l2/gstv4l2xoverlay.c b/sys/v4l2/gstv4l2xoverlay.c new file mode 100644 index 00000000..10c5f77b --- /dev/null +++ b/sys/v4l2/gstv4l2xoverlay.c @@ -0,0 +1,128 @@ +/* GStreamer X-based overlay interface implementation + * Copyright (C) 2003 Ronald Bultje + * + * gstv4l2xoverlay.c: X-based overlay interface implementation for V4L2 + * + * 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 +#include +#include + +#include "gstv4l2xoverlay.h" +#include "gstv4l2element.h" +#include "v4l2_calls.h" + +static void gst_v4l2_xoverlay_set_xwindow_id (GstXOverlay *overlay, + XID xwindow_id); + +void +gst_v4l2_xoverlay_interface_init (GstXOverlayClass *klass) +{ + /* default virtual functions */ + klass->set_xwindow_id = gst_v4l2_xoverlay_set_xwindow_id; +} + +GstXWindowListener * +gst_v4l2_xoverlay_new (GstV4l2Element *v4l2element) +{ + GstXWindowListener *xwin = + gst_x_window_listener_new (NULL, + (MapWindowFunc) gst_v4l2_enable_overlay, + (SetWindowFunc) gst_v4l2_set_window, + (gpointer) v4l2element); + + v4l2element->overlay = xwin; + v4l2element->xwindow_id = 0; + + return xwin; +} + +void +gst_v4l2_xoverlay_free (GstV4l2Element *v4l2element) +{ + gst_v4l2_xoverlay_close (v4l2element); + g_object_unref (G_OBJECT (v4l2element->overlay)); + v4l2element->overlay = NULL; +} + +void +gst_v4l2_xoverlay_open (GstV4l2Element *v4l2element) +{ + GstXWindowListener *xwin = v4l2element->overlay; + + if (xwin) { + xwin->display_name = g_strdup (v4l2element->display); + + if (v4l2element->xwindow_id != 0 && + xwin->display_name && + xwin->display_name[0] == ':') { + gst_x_window_listener_set_xid (xwin, v4l2element->xwindow_id); + } + } +} + +void +gst_v4l2_xoverlay_close (GstV4l2Element *v4l2element) +{ + GstXWindowListener *xwin = v4l2element->overlay; + + if (xwin != NULL) { + if (v4l2element->xwindow_id != 0 && + xwin->display_name && + xwin->display_name[0] == ':') { + gst_x_window_listener_set_xid (xwin, 0); + } + + g_free (xwin->display_name); + xwin->display_name = NULL; + } +} + +static void +gst_v4l2_xoverlay_set_xwindow_id (GstXOverlay *overlay, + XID xwindow_id) +{ + GstV4l2Element *v4l2element = GST_V4L2ELEMENT (overlay); + GstXWindowListener *xwin = v4l2element->overlay; + + if (v4l2element->xwindow_id == xwindow_id) { + return; + } + + if (gst_element_get_state (GST_ELEMENT (v4l2element)) != GST_STATE_NULL && + v4l2element->xwindow_id != 0 && + xwin != NULL && + xwin->display_name && + xwin->display_name[0] == ':') { + gst_x_window_listener_set_xid (xwin, 0); + } + + v4l2element->xwindow_id = xwindow_id; + + if (gst_element_get_state (GST_ELEMENT (v4l2element)) != GST_STATE_NULL && + v4l2element->xwindow_id != 0 && + xwin != NULL && + xwin->display_name && + xwin->display_name[0] == ':') { + gst_x_window_listener_set_xid (xwin, v4l2element->xwindow_id); + } +} diff --git a/sys/v4l2/gstv4l2xoverlay.h b/sys/v4l2/gstv4l2xoverlay.h new file mode 100644 index 00000000..cfcdfd35 --- /dev/null +++ b/sys/v4l2/gstv4l2xoverlay.h @@ -0,0 +1,42 @@ +/* G-Streamer generic V4L2 element - X overlay interface implementation + * Copyright (C) 2003 Ronald Bultje + * + * gstv4l2xoverlay.h: tv mixer interface implementation for V4L2 + * + * 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_V4L2_X_OVERLAY_H__ +#define __GST_V4L2_X_OVERLAY_H__ + +#include +#include + +#include "gstv4l2element.h" + +G_BEGIN_DECLS + +void gst_v4l2_xoverlay_interface_init (GstXOverlayClass *klass); + +GstXWindowListener * + gst_v4l2_xoverlay_new (GstV4l2Element *v4l2element); +void gst_v4l2_xoverlay_free (GstV4l2Element *v4l2element); + +/* signal handlers */ +void gst_v4l2_xoverlay_open (GstV4l2Element *v4l2element); +void gst_v4l2_xoverlay_close (GstV4l2Element *v4l2element); + +#endif /* __GST_V4L2_X_OVERLAY_H__ */ diff --git a/sys/v4l2/v4l2-overlay_calls.c b/sys/v4l2/v4l2-overlay_calls.c index d6b35366..2de74269 100644 --- a/sys/v4l2/v4l2-overlay_calls.c +++ b/sys/v4l2/v4l2-overlay_calls.c @@ -43,28 +43,33 @@ ******************************************************/ gboolean -gst_v4l2_set_display (GstV4l2Element *v4l2element, - const gchar *display) +gst_v4l2_set_display (GstV4l2Element *v4l2element) { gchar *buff; - DEBUG("trying to set overlay to '%s'", display); + if (v4l2element->display) + g_free(v4l2element->display); + v4l2element->display = g_strdup(g_getenv("DISPLAY")); + + DEBUG("trying to set overlay to '%s'", v4l2element->display); /* start v4l-conf */ buff = g_strdup_printf("v4l-conf -q -c %s -d %s", - v4l2element->device?v4l2element->device:"/dev/video", display); + v4l2element->device, v4l2element->display); switch (system(buff)) { case -1: gst_element_error(GST_ELEMENT(v4l2element), - "Could not start v4l-conf: %s", g_strerror(errno)); + "Could not start v4l-conf: %s", + g_strerror(errno)); g_free(buff); return FALSE; case 0: break; default: gst_element_error(GST_ELEMENT(v4l2element), - "v4l-conf failed to run correctly: %s", g_strerror(errno)); + "v4l-conf failed to run correctly: %s", + g_strerror(errno)); g_free(buff); return FALSE; } diff --git a/sys/v4l2/v4l2_calls.c b/sys/v4l2/v4l2_calls.c index 2ec66510..70c088cf 100644 --- a/sys/v4l2/v4l2_calls.c +++ b/sys/v4l2/v4l2_calls.c @@ -30,6 +30,9 @@ #include #include #include "v4l2_calls.h" +#include "gstv4l2tuner.h" +#include "gstv4l2xoverlay.h" +#include "gstv4l2colorbalance.h" #define DEBUG(format, args...) \ GST_DEBUG_OBJECT (\ @@ -70,55 +73,126 @@ static gboolean gst_v4l2_fill_lists (GstV4l2Element *v4l2element) { gint n; + const GList *pads = + gst_element_get_pad_list (GST_ELEMENT (v4l2element)); + GstPadDirection dir = GST_PAD_UNKNOWN; DEBUG("getting enumerations"); GST_V4L2_CHECK_OPEN(v4l2element); + /* sinks have outputs, all others have inputs */ + if (pads && g_list_length ((GList *) pads) == 1) + dir = GST_PAD_DIRECTION (GST_PAD (pads->data)); + + if (dir == GST_PAD_SINK) { /* and now, the inputs */ - for (n=0;;n++) { - struct v4l2_input input, *inpptr; - input.index = n; - if (ioctl(v4l2element->video_fd, VIDIOC_ENUMINPUT, &input) < 0) { - if (errno == EINVAL) - break; /* end of enumeration */ - else { - gst_element_error(GST_ELEMENT(v4l2element), - "Failed to get no. %d in input enumeration for %s: %s", - n, v4l2element->device, g_strerror(errno)); - return FALSE; + for (n=0;;n++) { + struct v4l2_input input; + GstV4l2TunerChannel *v4l2channel; + GstTunerChannel *channel; + + input.index = n; + if (ioctl(v4l2element->video_fd, VIDIOC_ENUMINPUT, + &input) < 0) { + if (errno == EINVAL) + break; /* end of enumeration */ + else { + gst_element_error(GST_ELEMENT(v4l2element), + "Failed to get no. %d in input enumeration for %s: %s", + n, v4l2element->device, + g_strerror(errno)); + return FALSE; + } } - } - inpptr = g_malloc(sizeof(input)); - memcpy(inpptr, &input, sizeof(input)); - v4l2element->inputs = g_list_append(v4l2element->inputs, inpptr); - - v4l2element->input_names = g_list_append(v4l2element->input_names, inpptr->name); - } - /* outputs */ - for (n=0;;n++) { - struct v4l2_output output, *outptr; - output.index = n; - if (ioctl(v4l2element->video_fd, VIDIOC_ENUMOUTPUT, &output) < 0) { - if (errno == EINVAL) - break; /* end of enumeration */ - else { - gst_element_error(GST_ELEMENT(v4l2element), - "Failed to get no. %d in output enumeration for %s: %s", - n, v4l2element->device, g_strerror(errno)); - return FALSE; + v4l2channel = + g_object_new(GST_TYPE_V4L2_TUNER_CHANNEL, NULL); + channel = GST_TUNER_CHANNEL(v4l2channel); + channel->label = g_strdup(input.name); + channel->flags = GST_TUNER_CHANNEL_INPUT; + v4l2channel->index = n; + if (input.type == V4L2_INPUT_TYPE_TUNER) { + struct v4l2_tuner vtun; + + v4l2channel->tuner = input.tuner; + channel->flags |= GST_TUNER_CHANNEL_FREQUENCY; + + vtun.index = input.tuner; + if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER, + &vtun) < 0) { + gst_element_error(GST_ELEMENT(v4l2element), + "Failed to get tuner %d settings on %s: %s", + input.tuner, + v4l2element->device, + g_strerror(errno)); + g_object_unref(G_OBJECT(channel)); + return FALSE; + } + channel->min_frequency = vtun.rangelow; + channel->max_frequency = vtun.rangehigh; + channel->min_signal = 0; + channel->max_signal = 0xffff; + } + if (input.audioset) { + /* we take the first. We don't care for + * the others for now */ + while (!(input.audioset & + (1<audio))) + v4l2channel->audio++; + channel->flags |= GST_TUNER_CHANNEL_AUDIO; } + + v4l2element->channels = + g_list_append(v4l2element->channels, + (gpointer) channel); } - outptr = g_malloc(sizeof(output)); - memcpy(outptr, &output, sizeof(output)); - v4l2element->outputs = g_list_append(v4l2element->outputs, outptr); + } else { + /* outputs */ + for (n=0;;n++) { + struct v4l2_output output; + GstV4l2TunerChannel *v4l2channel; + GstTunerChannel *channel; + + output.index = n; + if (ioctl(v4l2element->video_fd, VIDIOC_ENUMOUTPUT, + &output) < 0) { + if (errno == EINVAL) + break; /* end of enumeration */ + else { + gst_element_error(GST_ELEMENT(v4l2element), + "Failed to get no. %d in output enumeration for %s: %s", + n, v4l2element->device, + g_strerror(errno)); + return FALSE; + } + } + + v4l2channel = g_object_new(GST_TYPE_V4L2_TUNER_CHANNEL, NULL); + channel = GST_TUNER_CHANNEL(v4l2channel); + channel->label = g_strdup(output.name); + channel->flags = GST_TUNER_CHANNEL_OUTPUT; + v4l2channel->index = n; + if (output.audioset) { + /* we take the first. We don't care for + * the others for now */ + while (!(output.audioset & + (1<audio))) + v4l2channel->audio++; + channel->flags |= GST_TUNER_CHANNEL_AUDIO; + } - v4l2element->output_names = g_list_append(v4l2element->output_names, outptr->name); + v4l2element->channels = + g_list_append(v4l2element->channels, + (gpointer) channel); + } } /* norms... */ for (n=0;;n++) { - struct v4l2_standard standard, *stdptr; + struct v4l2_standard standard; + GstV4l2TunerNorm *v4l2norm; + GstTunerNorm *norm; + standard.index = n; if (ioctl(v4l2element->video_fd, VIDIOC_ENUMSTD, &standard) < 0) { if (errno == EINVAL) @@ -130,21 +204,28 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element) return FALSE; } } - stdptr = g_malloc(sizeof(standard)); - memcpy(stdptr, &standard, sizeof(standard)); - v4l2element->norms = g_list_append(v4l2element->norms, stdptr); - v4l2element->norm_names = g_list_append(v4l2element->norm_names, stdptr->name); + v4l2norm = g_object_new(GST_TYPE_V4L2_TUNER_NORM, NULL); + norm = GST_TUNER_NORM (v4l2norm); + norm->label = g_strdup(standard.name); + norm->fps = (gfloat) standard.frameperiod.denominator / + standard.frameperiod.numerator; + v4l2norm->index = standard.id; + + v4l2element->norms = g_list_append(v4l2element->norms, + (gpointer) norm); } /* and lastly, controls+menus (if appropriate) */ for (n=V4L2_CID_BASE;;n++) { - struct v4l2_queryctrl control, *ctrlptr; - GList *menus = NULL; - GParamSpec *spec = NULL; + struct v4l2_queryctrl control; + GstV4l2ColorBalanceChannel *v4l2channel; + GstColorBalanceChannel *channel; + /* hacky... */ if (n == V4L2_CID_LASTP1) n = V4L2_CID_PRIVATE_BASE; + control.id = n; if (ioctl(v4l2element->video_fd, VIDIOC_QUERYCTRL, &control) < 0) { if (errno == EINVAL) { @@ -161,9 +242,39 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element) } if (control.flags & V4L2_CTRL_FLAG_DISABLED) continue; - ctrlptr = g_malloc(sizeof(control)); - memcpy(ctrlptr, &control, sizeof(control)); - v4l2element->controls = g_list_append(v4l2element->controls, ctrlptr); + + switch (n) { + case V4L2_CID_BRIGHTNESS: + case V4L2_CID_CONTRAST: + case V4L2_CID_SATURATION: + case V4L2_CID_HUE: + case V4L2_CID_BLACK_LEVEL: + case V4L2_CID_AUTO_WHITE_BALANCE: + case V4L2_CID_DO_WHITE_BALANCE: + case V4L2_CID_RED_BALANCE: + case V4L2_CID_BLUE_BALANCE: + case V4L2_CID_GAMMA: + case V4L2_CID_EXPOSURE: + case V4L2_CID_AUTOGAIN: + case V4L2_CID_GAIN: + /* we only handle these for now */ + break; + default: + DEBUG("ControlID %s (%d) unhandled, FIXME", + control.name, n); + control.id++; + break; + } + if (n != control.id) + continue; + + v4l2channel = g_object_new(GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, + NULL); + channel = GST_COLOR_BALANCE_CHANNEL(v4l2channel); + channel->label = g_strdup(control.name); + v4l2channel->index = n; + +#if 0 if (control.type == V4L2_CTRL_TYPE_MENU) { struct v4l2_querymenu menu, *mptr; int i; @@ -186,30 +297,25 @@ gst_v4l2_fill_lists (GstV4l2Element *v4l2element) } } v4l2element->menus = g_list_append(v4l2element->menus, menus); +#endif switch (control.type) { case V4L2_CTRL_TYPE_INTEGER: - spec = g_param_spec_int(ctrlptr->name, ctrlptr->name, - ctrlptr->name, ctrlptr->minimum, ctrlptr->maximum, - ctrlptr->default_value, G_PARAM_READWRITE); + channel->min_value = control.minimum; + channel->max_value = control.maximum; break; case V4L2_CTRL_TYPE_BOOLEAN: - spec = g_param_spec_boolean(ctrlptr->name, ctrlptr->name, - ctrlptr->name, ctrlptr->default_value, - G_PARAM_READWRITE); + channel->min_value = FALSE; + channel->max_value = TRUE; break; - case V4L2_CTRL_TYPE_MENU: - /* hacky... we abuse pointer for 'no value' */ - spec = g_param_spec_pointer(ctrlptr->name, ctrlptr->name, - ctrlptr->name, G_PARAM_WRITABLE); - break; - case V4L2_CTRL_TYPE_BUTTON: - /* help?!? */ - spec = NULL; + default: + channel->min_value = + channel->max_value = 0; break; } - v4l2element->control_specs = g_list_append(v4l2element->control_specs, spec); + v4l2element->colors = g_list_append(v4l2element->colors, + (gpointer) channel); } return TRUE; @@ -221,48 +327,17 @@ gst_v4l2_empty_lists (GstV4l2Element *v4l2element) { DEBUG("deleting enumerations"); - /* empty lists */ - while (g_list_length(v4l2element->inputs) > 0) { - gpointer data = g_list_nth_data(v4l2element->inputs, 0); - v4l2element->inputs = g_list_remove(v4l2element->inputs, data); - g_free(data); - } - g_list_free(v4l2element->input_names); - v4l2element->input_names = NULL; - while (g_list_length(v4l2element->outputs) > 0) { - gpointer data = g_list_nth_data(v4l2element->outputs, 0); - v4l2element->outputs = g_list_remove(v4l2element->outputs, data); - g_free(data); - } - g_list_free(v4l2element->output_names); - v4l2element->output_names = NULL; - while (g_list_length(v4l2element->norms) > 0) { - gpointer data = g_list_nth_data(v4l2element->norms, 0); - v4l2element->norms = g_list_remove(v4l2element->norms, data); - g_free(data); - } - g_list_free(v4l2element->norm_names); - v4l2element->norm_names = NULL; - while (g_list_length(v4l2element->controls) > 0) { - gpointer data = g_list_nth_data(v4l2element->controls, 0); - v4l2element->controls = g_list_remove(v4l2element->controls, data); - g_free(data); - } - v4l2element->menus = g_list_remove_all(v4l2element->menus, NULL); - while (g_list_length(v4l2element->menus) > 0) { - GList *items = (GList *) g_list_nth_data(v4l2element->menus, 0); - v4l2element->inputs = g_list_remove(v4l2element->inputs, items); - while (g_list_length(items) > 0) { - gpointer data = g_list_nth_data(v4l2element->menus, 0); - items = g_list_remove(items, data); - g_free(data); - } - } - while (g_list_length(v4l2element->control_specs) > 0) { - gpointer data = g_list_nth_data(v4l2element->control_specs, 0); - v4l2element->control_specs = g_list_remove(v4l2element->control_specs, data); - g_param_spec_unref(G_PARAM_SPEC(data)); - } + g_list_foreach (v4l2element->channels, (GFunc) g_object_unref, NULL); + g_list_free (v4l2element->channels); + v4l2element->channels = NULL; + + g_list_foreach (v4l2element->norms, (GFunc) g_object_unref, NULL); + g_list_free (v4l2element->norms); + v4l2element->norms = NULL; + + g_list_foreach (v4l2element->colors, (GFunc) g_object_unref, NULL); + g_list_free (v4l2element->colors); + v4l2element->colors = NULL; } @@ -351,34 +426,19 @@ gst_v4l2_close (GstV4l2Element *v4l2element) gboolean gst_v4l2_get_norm (GstV4l2Element *v4l2element, - gint *norm) + v4l2_std_id *norm) { - v4l2_std_id std_id; - gint n; - DEBUG("getting norm"); GST_V4L2_CHECK_OPEN(v4l2element); - if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, &std_id) < 0) { + if (ioctl(v4l2element->video_fd, VIDIOC_G_STD, norm) < 0) { gst_element_error(GST_ELEMENT(v4l2element), "Failed to get the current norm for device %s: %s", v4l2element->device, g_strerror(errno)); return FALSE; } - /* try to find out what norm number this actually is */ - for (n=0;nnorms);n++) { - struct v4l2_standard *stdptr = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, n); - if (stdptr->id == std_id) { - *norm = n; - return TRUE; - } - } - - gst_element_error(GST_ELEMENT(v4l2element), - "Failed to find norm '%llu' in our list of available norms for device %s", - std_id, v4l2element->device); - return FALSE; + return TRUE; } @@ -390,27 +450,16 @@ gst_v4l2_get_norm (GstV4l2Element *v4l2element, gboolean gst_v4l2_set_norm (GstV4l2Element *v4l2element, - gint norm) + v4l2_std_id norm) { - struct v4l2_standard *standard; - - DEBUG("trying to set norm to %d", norm); + DEBUG("trying to set norm to %llx", norm); GST_V4L2_CHECK_OPEN(v4l2element); GST_V4L2_CHECK_NOT_ACTIVE(v4l2element); - if (norm < 0 || norm >= g_list_length(v4l2element->norms)) { - gst_element_error(GST_ELEMENT(v4l2element), - "Invalid norm number %d (%d-%d)", - norm, 0, g_list_length(v4l2element->norms)); - return FALSE; - } - - standard = (struct v4l2_standard *) g_list_nth_data(v4l2element->norms, norm); - - if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &standard->id) < 0) { + if (ioctl(v4l2element->video_fd, VIDIOC_S_STD, &norm) < 0) { gst_element_error(GST_ELEMENT(v4l2element), - "Failed to set norm '%s' (%llu) for device %s: %s", - standard->name, standard->id, v4l2element->device, g_strerror(errno)); + "Failed to set norm 0x%llx for device %s: %s", + norm, v4l2element->device, g_strerror(errno)); return FALSE; } @@ -460,13 +509,6 @@ gst_v4l2_set_input (GstV4l2Element *v4l2element, GST_V4L2_CHECK_OPEN(v4l2element); GST_V4L2_CHECK_NOT_ACTIVE(v4l2element); - if (input < 0 || input >= g_list_length(v4l2element->inputs)) { - gst_element_error(GST_ELEMENT(v4l2element), - "Invalid input number %d (%d-%d)", - input, 0, g_list_length(v4l2element->inputs)); - return FALSE; - } - if (ioctl(v4l2element->video_fd, VIDIOC_S_INPUT, &input) < 0) { gst_element_error(GST_ELEMENT(v4l2element), "Failed to set input %d on device %s: %s", @@ -520,13 +562,6 @@ gst_v4l2_set_output (GstV4l2Element *v4l2element, GST_V4L2_CHECK_OPEN(v4l2element); GST_V4L2_CHECK_NOT_ACTIVE(v4l2element); - if (output < 0 || output >= g_list_length(v4l2element->outputs)) { - gst_element_error(GST_ELEMENT(v4l2element), - "Invalid output number %d (%d-%d)", - output, 0, g_list_length(v4l2element->outputs)); - return FALSE; - } - if (ioctl(v4l2element->video_fd, VIDIOC_S_OUTPUT, &output) < 0) { gst_element_error(GST_ELEMENT(v4l2element), "Failed to set output %d on device %s: %s", @@ -538,36 +573,6 @@ gst_v4l2_set_output (GstV4l2Element *v4l2element, } -/****************************************************** - * gst_v4l2_has_tuner(): - * Check whether the device has a tuner - * return value: TRUE if it has a tuner, else FALSE - ******************************************************/ - -gint -gst_v4l2_has_tuner (GstV4l2Element *v4l2element, - gint *tuner_num) -{ - gint input_num; - struct v4l2_input *input; - - DEBUG("detecting whether device has a tuner"); - GST_V4L2_CHECK_OPEN(v4l2element); - - if (!gst_v4l2_get_input(v4l2element, &input_num)) - return FALSE; - - input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num); - - if (input->type == V4L2_INPUT_TYPE_TUNER && - v4l2element->vcap.capabilities & V4L2_CAP_TUNER) { - *tuner_num = input->tuner; - return TRUE; - } - return FALSE; -} - - /****************************************************** * gst_v4l2_get_frequency(): * get the current frequency @@ -576,6 +581,7 @@ gst_v4l2_has_tuner (GstV4l2Element *v4l2element, gboolean gst_v4l2_get_frequency (GstV4l2Element *v4l2element, + gint tunernum, gulong *frequency) { struct v4l2_frequency freq; @@ -583,11 +589,7 @@ gst_v4l2_get_frequency (GstV4l2Element *v4l2element, DEBUG("getting current tuner frequency"); GST_V4L2_CHECK_OPEN(v4l2element); - if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner)) - return FALSE; - - freq.type = 0; - + freq.tuner = tunernum; if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) { gst_element_error(GST_ELEMENT(v4l2element), "Failed to get current tuner frequency for device %s: %s", @@ -609,6 +611,7 @@ gst_v4l2_get_frequency (GstV4l2Element *v4l2element, gboolean gst_v4l2_set_frequency (GstV4l2Element *v4l2element, + gint tunernum, gulong frequency) { struct v4l2_frequency freq; @@ -617,13 +620,12 @@ gst_v4l2_set_frequency (GstV4l2Element *v4l2element, GST_V4L2_CHECK_OPEN(v4l2element); GST_V4L2_CHECK_NOT_ACTIVE(v4l2element); - if (!gst_v4l2_has_tuner(v4l2element, &freq.tuner)) - return FALSE; - + freq.tuner = tunernum; + /* fill in type - ignore error */ + ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq); freq.frequency = frequency; - freq.type = 0; - if (ioctl(v4l2element->video_fd, VIDIOC_G_FREQUENCY, &freq) < 0) { + if (ioctl(v4l2element->video_fd, VIDIOC_S_FREQUENCY, &freq) < 0) { gst_element_error(GST_ELEMENT(v4l2element), "Failed to set tuner frequency to %lu for device %s: %s", frequency, v4l2element->device, g_strerror(errno)); @@ -642,6 +644,7 @@ gst_v4l2_set_frequency (GstV4l2Element *v4l2element, gboolean gst_v4l2_signal_strength (GstV4l2Element *v4l2element, + gint tunernum, gulong *signal_strength) { struct v4l2_tuner tuner; @@ -649,6 +652,7 @@ gst_v4l2_signal_strength (GstV4l2Element *v4l2element, DEBUG("trying to get signal strength"); GST_V4L2_CHECK_OPEN(v4l2element); + tuner.index = tunernum; if (ioctl(v4l2element->video_fd, VIDIOC_G_TUNER, &tuner) < 0) { gst_element_error(GST_ELEMENT(v4l2element), "Failed to get signal strength for device %s: %s", @@ -662,51 +666,6 @@ gst_v4l2_signal_strength (GstV4l2Element *v4l2element, } -/****************************************************** - * gst_v4l2_has_audio(): - * Check whether the device has audio capabilities - * return value: TRUE if it has a tuner, else FALSE - ******************************************************/ - -gboolean -gst_v4l2_has_audio (GstV4l2Element *v4l2element) -{ - gint input_num; - struct v4l2_input *input; - - DEBUG("detecting whether device has audio"); - GST_V4L2_CHECK_OPEN(v4l2element); - - if (!gst_v4l2_get_input(v4l2element, &input_num)) - return FALSE; - - input = (struct v4l2_input *) g_list_nth_data(v4l2element->inputs, input_num); - - return (input->audioset != 0); -} - - -/****************************************************** - * gst_v4l2_control_name_to_num(): - * convert name to num (-1 if nothing) - ******************************************************/ - -static gint -gst_v4l2_control_name_to_num (GstV4l2Element *v4l2element, - const gchar *name) -{ - GList *item; - - for (item = v4l2element->controls; item != NULL; item = item->next) { - struct v4l2_queryctrl *ctrl = item->data; - if (!strcmp(ctrl->name, name)) - return ctrl->id; - } - - return -1; -} - - /****************************************************** * gst_v4l2_get_attribute(): * try to get the value of one specific attribute @@ -714,35 +673,22 @@ gst_v4l2_control_name_to_num (GstV4l2Element *v4l2element, ******************************************************/ gboolean -gst_v4l2_get_attribute (GstElement *element, - const gchar *name, - int *value) +gst_v4l2_get_attribute (GstV4l2Element *v4l2element, + int attribute_num, + int *value) { struct v4l2_control control; - GstV4l2Element *v4l2element; - gint attribute_num = -1; - g_return_val_if_fail(element != NULL && name != NULL && value != NULL, FALSE); - g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE); - v4l2element = GST_V4L2ELEMENT(element); - - DEBUG("getting value of attribute %d", attribute_num); GST_V4L2_CHECK_OPEN(v4l2element); - attribute_num = gst_v4l2_control_name_to_num(v4l2element, name); - - if (attribute_num < 0) { - gst_element_error(GST_ELEMENT(v4l2element), - "Invalid control %s", name); - return FALSE; - } + DEBUG("getting value of attribute %d", attribute_num); control.id = attribute_num; if (ioctl(v4l2element->video_fd, VIDIOC_G_CTRL, &control) < 0) { gst_element_error(GST_ELEMENT(v4l2element), - "Failed to get value for control %s (%d) on device %s: %s", - name, attribute_num, v4l2element->device, g_strerror(errno)); + "Failed to get value for control %d on device %s: %s", + attribute_num, v4l2element->device, g_strerror(errno)); return FALSE; } @@ -759,36 +705,23 @@ gst_v4l2_get_attribute (GstElement *element, ******************************************************/ gboolean -gst_v4l2_set_attribute (GstElement *element, - const gchar *name, - const int value) +gst_v4l2_set_attribute (GstV4l2Element *v4l2element, + int attribute_num, + const int value) { struct v4l2_control control; - GstV4l2Element *v4l2element; - gint attribute_num = -1; - - g_return_val_if_fail(element != NULL && name != NULL, FALSE); - g_return_val_if_fail(GST_IS_V4L2ELEMENT(element), FALSE); - v4l2element = GST_V4L2ELEMENT(element); - DEBUG("setting value of attribute %d to %d", attribute_num, value); GST_V4L2_CHECK_OPEN(v4l2element); - attribute_num = gst_v4l2_control_name_to_num(v4l2element, name); - - if (attribute_num < 0) { - gst_element_error(GST_ELEMENT(v4l2element), - "Invalid control %s", name); - return FALSE; - } + DEBUG("setting value of attribute %d to %d", attribute_num, value); control.id = attribute_num; control.value = value; if (ioctl(v4l2element->video_fd, VIDIOC_S_CTRL, &control) < 0) { gst_element_error(GST_ELEMENT(v4l2element), - "Failed to set value %d for control %s (%d) on device %s: %s", - value, name, attribute_num, v4l2element->device, g_strerror(errno)); + "Failed to set value %d for control %d on device %s: %s", + value, attribute_num, v4l2element->device, g_strerror(errno)); return FALSE; } diff --git a/sys/v4l2/v4l2_calls.h b/sys/v4l2/v4l2_calls.h index e03c7abe..a999af8e 100644 --- a/sys/v4l2/v4l2_calls.h +++ b/sys/v4l2/v4l2_calls.h @@ -86,9 +86,9 @@ gboolean gst_v4l2_close (GstV4l2Element *v4l2element); /* norm/input/output */ gboolean gst_v4l2_get_norm (GstV4l2Element *v4l2element, - gint *norm); + v4l2_std_id *norm); gboolean gst_v4l2_set_norm (GstV4l2Element *v4l2element, - gint norm); + v4l2_std_id norm); gboolean gst_v4l2_get_input (GstV4l2Element *v4l2element, gint *input); gboolean gst_v4l2_set_input (GstV4l2Element *v4l2element, @@ -99,27 +99,26 @@ gboolean gst_v4l2_set_output (GstV4l2Element *v4l2element, gint output); /* frequency control */ -gboolean gst_v4l2_has_tuner (GstV4l2Element *v4l2element, - gint *tuner_num); gboolean gst_v4l2_get_frequency (GstV4l2Element *v4l2element, + gint tunernum, gulong *frequency); gboolean gst_v4l2_set_frequency (GstV4l2Element *v4l2element, - gulong frequency); + gint tunernum, + gulong frequency); gboolean gst_v4l2_signal_strength (GstV4l2Element *v4l2element, - gulong *signal_strength); + gint tunernum, + gulong *signal); /* attribute control */ -gboolean gst_v4l2_has_audio (GstV4l2Element *v4l2element); -gboolean gst_v4l2_get_attribute (GstElement *element, - const char *attribute, +gboolean gst_v4l2_get_attribute (GstV4l2Element *v4l2element, + int attribute, int *value); -gboolean gst_v4l2_set_attribute (GstElement *element, - const char *attribute, +gboolean gst_v4l2_set_attribute (GstV4l2Element *v4l2element, + int attribute, const int value); /* overlay */ -gboolean gst_v4l2_set_display (GstV4l2Element *v4l2element, - const gchar *display); +gboolean gst_v4l2_set_display (GstV4l2Element *v4l2element); gboolean gst_v4l2_set_window (GstElement *element, gint x, gint y, gint w, gint h, -- cgit v1.2.1