From fe148502a5dd08fc62825cac6272cb5e980984a6 Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Mon, 21 Feb 2011 10:59:56 +0000 Subject: Move farsight-using sources to src And only build them for empathy-av, since they use farsight. --- libempathy-gtk/Makefile.am | 12 +- libempathy-gtk/empathy-audio-sink.c | 235 ---------------- libempathy-gtk/empathy-audio-sink.h | 67 ----- libempathy-gtk/empathy-audio-src.c | 387 --------------------------- libempathy-gtk/empathy-audio-src.h | 66 ----- libempathy-gtk/empathy-video-src.c | 360 ------------------------- libempathy-gtk/empathy-video-src.h | 86 ------ libempathy-gtk/empathy-video-widget.c | 485 ---------------------------------- libempathy-gtk/empathy-video-widget.h | 72 ----- src/Makefile.am | 9 +- src/empathy-audio-sink.c | 235 ++++++++++++++++ src/empathy-audio-sink.h | 67 +++++ src/empathy-audio-src.c | 387 +++++++++++++++++++++++++++ src/empathy-audio-src.h | 66 +++++ src/empathy-streamed-media-window.c | 8 +- src/empathy-video-src.c | 360 +++++++++++++++++++++++++ src/empathy-video-src.h | 86 ++++++ src/empathy-video-widget.c | 485 ++++++++++++++++++++++++++++++++++ src/empathy-video-widget.h | 72 +++++ 19 files changed, 1772 insertions(+), 1773 deletions(-) delete mode 100644 libempathy-gtk/empathy-audio-sink.c delete mode 100644 libempathy-gtk/empathy-audio-sink.h delete mode 100644 libempathy-gtk/empathy-audio-src.c delete mode 100644 libempathy-gtk/empathy-audio-src.h delete mode 100644 libempathy-gtk/empathy-video-src.c delete mode 100644 libempathy-gtk/empathy-video-src.h delete mode 100644 libempathy-gtk/empathy-video-widget.c delete mode 100644 libempathy-gtk/empathy-video-widget.h create mode 100644 src/empathy-audio-sink.c create mode 100644 src/empathy-audio-sink.h create mode 100644 src/empathy-audio-src.c create mode 100644 src/empathy-audio-src.h create mode 100644 src/empathy-video-src.c create mode 100644 src/empathy-video-src.h create mode 100644 src/empathy-video-widget.c create mode 100644 src/empathy-video-widget.h diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am index ca14833d2..9e2671cd4 100644 --- a/libempathy-gtk/Makefile.am +++ b/libempathy-gtk/Makefile.am @@ -35,8 +35,6 @@ libempathy_gtk_handwritten_source = \ empathy-account-widget-private.h \ empathy-account-widget-sip.c \ empathy-account-widget.c \ - empathy-audio-sink.c \ - empathy-audio-src.c \ empathy-avatar-chooser.c \ empathy-avatar-image.c \ empathy-cell-renderer-activatable.c \ @@ -90,17 +88,13 @@ libempathy_gtk_handwritten_source = \ empathy-theme-irc.c \ empathy-theme-manager.c \ empathy-tls-dialog.c \ - empathy-ui-utils.c \ - empathy-video-src.c \ - empathy-video-widget.c + empathy-ui-utils.c libempathy_gtk_headers = \ empathy-account-chooser.h \ empathy-account-widget-irc.h \ empathy-account-widget-sip.h \ empathy-account-widget.h \ - empathy-audio-sink.h \ - empathy-audio-src.h \ empathy-avatar-chooser.h \ empathy-avatar-image.h \ empathy-cell-renderer-activatable.h \ @@ -155,9 +149,7 @@ libempathy_gtk_headers = \ empathy-theme-irc.h \ empathy-theme-manager.h \ empathy-tls-dialog.h \ - empathy-ui-utils.h \ - empathy-video-src.h \ - empathy-video-widget.h + empathy-ui-utils.h libempathy_gtk_la_SOURCES = \ $(libempathy_gtk_handwritten_source) \ diff --git a/libempathy-gtk/empathy-audio-sink.c b/libempathy-gtk/empathy-audio-sink.c deleted file mode 100644 index 1d2169593..000000000 --- a/libempathy-gtk/empathy-audio-sink.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * empathy-gst-audio-sink.c - Source for EmpathyGstAudioSink - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include - -#include - -#include "empathy-audio-sink.h" - - -G_DEFINE_TYPE(EmpathyGstAudioSink, empathy_audio_sink, GST_TYPE_BIN) - -/* signal enum */ -#if 0 -enum -{ - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = {0}; -#endif - -enum { - PROP_VOLUME = 1, -}; - -/* private structure */ -typedef struct _EmpathyGstAudioSinkPrivate EmpathyGstAudioSinkPrivate; - -struct _EmpathyGstAudioSinkPrivate -{ - gboolean dispose_has_run; - GstElement *sink; - GstElement *volume; - FsElementAddedNotifier *notifier; -}; - -#define EMPATHY_GST_AUDIO_SINK_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SINK, \ - EmpathyGstAudioSinkPrivate)) - -static void -empathy_audio_sink_element_added_cb (FsElementAddedNotifier *notifier, - GstBin *bin, GstElement *element, EmpathyGstAudioSink *self) -{ - EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self); - - if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume")) - { - gdouble volume; - - volume = empathy_audio_sink_get_volume (self); - empathy_audio_sink_set_volume (self, 1.0); - - if (priv->volume != NULL) - g_object_unref (priv->volume); - priv->volume = g_object_ref (element); - - if (volume != 1.0) - empathy_audio_sink_set_volume (self, volume); - } -} - -static void -empathy_audio_sink_init (EmpathyGstAudioSink *obj) -{ - EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (obj); - GstElement *resample; - GstPad *ghost, *sink; - - priv->notifier = fs_element_added_notifier_new (); - g_signal_connect (priv->notifier, "element-added", - G_CALLBACK (empathy_audio_sink_element_added_cb), obj); - - resample = gst_element_factory_make ("audioresample", NULL); - - priv->volume = gst_element_factory_make ("volume", NULL); - g_object_ref (priv->volume); - - priv->sink = gst_element_factory_make ("gconfaudiosink", NULL); - - fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->sink)); - - gst_bin_add_many (GST_BIN (obj), resample, priv->volume, priv->sink, NULL); - gst_element_link_many (resample, priv->volume, priv->sink, NULL); - - sink = gst_element_get_static_pad (resample, "sink"); - - ghost = gst_ghost_pad_new ("sink", sink); - gst_element_add_pad (GST_ELEMENT (obj), ghost); - - gst_object_unref (G_OBJECT (sink)); -} - -static void empathy_audio_sink_dispose (GObject *object); -static void empathy_audio_sink_finalize (GObject *object); - -static void -empathy_audio_sink_set_property (GObject *object, - guint property_id, const GValue *value, GParamSpec *pspec) -{ - switch (property_id) - { - case PROP_VOLUME: - empathy_audio_sink_set_volume (EMPATHY_GST_AUDIO_SINK (object), - g_value_get_double (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -empathy_audio_sink_get_property (GObject *object, - guint property_id, GValue *value, GParamSpec *pspec) -{ - switch (property_id) - { - case PROP_VOLUME: - g_value_set_double (value, - empathy_audio_sink_get_volume (EMPATHY_GST_AUDIO_SINK (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -empathy_audio_sink_class_init (EmpathyGstAudioSinkClass - *empathy_audio_sink_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (empathy_audio_sink_class); - GParamSpec *param_spec; - - g_type_class_add_private (empathy_audio_sink_class, - sizeof (EmpathyGstAudioSinkPrivate)); - - object_class->dispose = empathy_audio_sink_dispose; - object_class->finalize = empathy_audio_sink_finalize; - - object_class->set_property = empathy_audio_sink_set_property; - object_class->get_property = empathy_audio_sink_get_property; - - param_spec = g_param_spec_double ("volume", "Volume", "volume control", - 0.0, 5.0, 1.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_VOLUME, param_spec); -} - -void -empathy_audio_sink_dispose (GObject *object) -{ - EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object); - EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self); - - if (priv->dispose_has_run) - return; - - priv->dispose_has_run = TRUE; - - if (priv->notifier != NULL) - g_object_unref (priv->notifier); - priv->notifier = NULL; - - if (priv->volume != NULL) - g_object_unref (priv->volume); - priv->volume = NULL; - - if (G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose) - G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose (object); -} - -void -empathy_audio_sink_finalize (GObject *object) -{ - //EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object); - //EmpathyGstAudioSinkPrivate *priv = - // EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self); - - /* free any data held directly by the object here */ - - G_OBJECT_CLASS (empathy_audio_sink_parent_class)->finalize (object); -} - -GstElement * -empathy_audio_sink_new (void) -{ - static gboolean registered = FALSE; - - if (!registered) { - if (!gst_element_register (NULL, "empathyaudiosink", - GST_RANK_NONE, EMPATHY_TYPE_GST_AUDIO_SINK)) - return NULL; - registered = TRUE; - } - return gst_element_factory_make ("empathyaudiosink", NULL); -} - -void -empathy_audio_sink_set_volume (EmpathyGstAudioSink *sink, gdouble volume) -{ - EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (sink); - - g_object_set (G_OBJECT (priv->volume), "volume", volume, NULL); -} - -gdouble -empathy_audio_sink_get_volume (EmpathyGstAudioSink *sink) -{ - EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (sink); - gdouble volume; - - g_object_get (G_OBJECT (priv->volume), "volume", &volume, NULL); - - return volume; -} diff --git a/libempathy-gtk/empathy-audio-sink.h b/libempathy-gtk/empathy-audio-sink.h deleted file mode 100644 index 21ebf2b5a..000000000 --- a/libempathy-gtk/empathy-audio-sink.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * empathy-gst-video-sink.h - Header for EmpathyGstAudioSink - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __EMPATHY_GST_AUDIO_SINK_H__ -#define __EMPATHY_GST_AUDIO_SINK_H__ - -#include -#include - -G_BEGIN_DECLS - -typedef struct _EmpathyGstAudioSink EmpathyGstAudioSink; -typedef struct _EmpathyGstAudioSinkClass EmpathyGstAudioSinkClass; - -struct _EmpathyGstAudioSinkClass { - GstBinClass parent_class; -}; - -struct _EmpathyGstAudioSink { - GstBin parent; -}; - -GType empathy_audio_sink_get_type (void); - -/* TYPE MACROS */ -#define EMPATHY_TYPE_GST_AUDIO_SINK \ - (empathy_audio_sink_get_type ()) -#define EMPATHY_GST_AUDIO_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_GST_AUDIO_SINK, \ - EmpathyGstAudioSink)) -#define EMPATHY_GST_AUDIO_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_GST_AUDIO_SINK, \ - EmpathyGstAudioSinkClass)) -#define EMPATHY_IS_GST_AUDIO_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_GST_AUDIO_SINK)) -#define EMPATHY_IS_GST_AUDIO_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_GST_AUDIO_SINK)) -#define EMPATHY_GST_AUDIO_SINK_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_GST_AUDIO_SINK, \ - EmpathyGstAudioSinkClass)) - -GstElement *empathy_audio_sink_new (void); - -void empathy_audio_sink_set_volume (EmpathyGstAudioSink *sink, gdouble volume); - -gdouble empathy_audio_sink_get_volume (EmpathyGstAudioSink *sink); - -G_END_DECLS - -#endif /* #ifndef __EMPATHY_GST_AUDIO_SINK_H__*/ diff --git a/libempathy-gtk/empathy-audio-src.c b/libempathy-gtk/empathy-audio-src.c deleted file mode 100644 index a3416f2ea..000000000 --- a/libempathy-gtk/empathy-audio-src.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * empathy-gst-audio-src.c - Source for EmpathyGstAudioSrc - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include - -#include -#include "empathy-audio-src.h" - -G_DEFINE_TYPE(EmpathyGstAudioSrc, empathy_audio_src, GST_TYPE_BIN) - -/* signal enum */ -enum -{ - PEAK_LEVEL_CHANGED, - RMS_LEVEL_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = {0}; - -enum { - PROP_VOLUME = 1, - PROP_RMS_LEVEL, - PROP_PEAK_LEVEL, -}; - -/* private structure */ -typedef struct _EmpathyGstAudioSrcPrivate EmpathyGstAudioSrcPrivate; - -struct _EmpathyGstAudioSrcPrivate -{ - gboolean dispose_has_run; - GstElement *src; - GstElement *volume; - GstElement *level; - FsElementAddedNotifier *notifier; - - gdouble peak_level; - gdouble rms_level; - - GMutex *lock; - guint idle_id; -}; - -#define EMPATHY_GST_AUDIO_SRC_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SRC, \ - EmpathyGstAudioSrcPrivate)) - -static void -empathy_audio_src_element_added_cb (FsElementAddedNotifier *notifier, - GstBin *bin, GstElement *element, EmpathyGstAudioSrc *self) -{ - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - - if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume")) - { - gdouble volume; - - volume = empathy_audio_src_get_volume (self); - empathy_audio_src_set_volume (self, 1.0); - - if (priv->volume != NULL) - g_object_unref (priv->volume); - priv->volume = g_object_ref (element); - - if (volume != 1.0) - empathy_audio_src_set_volume (self, volume); - } -} - -static void -empathy_audio_src_init (EmpathyGstAudioSrc *obj) -{ - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (obj); - GstPad *ghost, *src; - - priv->peak_level = -G_MAXDOUBLE; - priv->lock = g_mutex_new (); - - priv->notifier = fs_element_added_notifier_new (); - g_signal_connect (priv->notifier, "element-added", - G_CALLBACK (empathy_audio_src_element_added_cb), obj); - - priv->src = gst_element_factory_make ("gconfaudiosrc", NULL); - gst_bin_add (GST_BIN (obj), priv->src); - - fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->src)); - - priv->volume = gst_element_factory_make ("volume", NULL); - g_object_ref (priv->volume); - - gst_bin_add (GST_BIN (obj), priv->volume); - gst_element_link (priv->src, priv->volume); - - priv->level = gst_element_factory_make ("level", NULL); - gst_bin_add (GST_BIN (obj), priv->level); - gst_element_link (priv->volume, priv->level); - - src = gst_element_get_static_pad (priv->level, "src"); - - ghost = gst_ghost_pad_new ("src", src); - gst_element_add_pad (GST_ELEMENT (obj), ghost); - - gst_object_unref (G_OBJECT (src)); -} - -static void empathy_audio_src_dispose (GObject *object); -static void empathy_audio_src_finalize (GObject *object); -static void empathy_audio_src_handle_message (GstBin *bin, - GstMessage *message); - -static gboolean empathy_audio_src_levels_updated (gpointer user_data); - -static void -empathy_audio_src_set_property (GObject *object, - guint property_id, const GValue *value, GParamSpec *pspec) -{ - switch (property_id) - { - case PROP_VOLUME: - empathy_audio_src_set_volume (EMPATHY_GST_AUDIO_SRC (object), - g_value_get_double (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -empathy_audio_src_get_property (GObject *object, - guint property_id, GValue *value, GParamSpec *pspec) -{ - EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object); - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - - switch (property_id) - { - case PROP_VOLUME: - g_value_set_double (value, - empathy_audio_src_get_volume (self)); - break; - case PROP_PEAK_LEVEL: - g_mutex_lock (priv->lock); - g_value_set_double (value, priv->peak_level); - g_mutex_unlock (priv->lock); - break; - case PROP_RMS_LEVEL: - g_mutex_lock (priv->lock); - g_value_set_double (value, priv->rms_level); - g_mutex_unlock (priv->lock); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -empathy_audio_src_class_init (EmpathyGstAudioSrcClass - *empathy_audio_src_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (empathy_audio_src_class); - GstBinClass *gstbin_class = GST_BIN_CLASS (empathy_audio_src_class); - GParamSpec *param_spec; - - g_type_class_add_private (empathy_audio_src_class, - sizeof (EmpathyGstAudioSrcPrivate)); - - object_class->dispose = empathy_audio_src_dispose; - object_class->finalize = empathy_audio_src_finalize; - - object_class->set_property = empathy_audio_src_set_property; - object_class->get_property = empathy_audio_src_get_property; - - gstbin_class->handle_message = - GST_DEBUG_FUNCPTR (empathy_audio_src_handle_message); - - param_spec = g_param_spec_double ("volume", "Volume", "volume contol", - 0.0, 5.0, 1.0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_VOLUME, param_spec); - - param_spec = g_param_spec_double ("peak-level", "peak level", "peak level", - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_VOLUME, param_spec); - - signals[PEAK_LEVEL_CHANGED] = g_signal_new ("peak-level-changed", - G_TYPE_FROM_CLASS (empathy_audio_src_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__DOUBLE, - G_TYPE_NONE, 1, G_TYPE_DOUBLE); - - param_spec = g_param_spec_double ("rms-level", "RMS level", "RMS level", - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_VOLUME, param_spec); - - - signals[RMS_LEVEL_CHANGED] = g_signal_new ("rms-level-changed", - G_TYPE_FROM_CLASS (empathy_audio_src_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__DOUBLE, - G_TYPE_NONE, 1, G_TYPE_DOUBLE); -} - -void -empathy_audio_src_dispose (GObject *object) -{ - EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object); - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - - if (priv->dispose_has_run) - return; - - priv->dispose_has_run = TRUE; - - if (priv->idle_id != 0) - g_source_remove (priv->idle_id); - - priv->idle_id = 0; - - /* release any references held by the object here */ - - if (G_OBJECT_CLASS (empathy_audio_src_parent_class)->dispose) - G_OBJECT_CLASS (empathy_audio_src_parent_class)->dispose (object); -} - -void -empathy_audio_src_finalize (GObject *object) -{ - EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object); - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - - /* free any data held directly by the object here */ - g_mutex_free (priv->lock); - - G_OBJECT_CLASS (empathy_audio_src_parent_class)->finalize (object); -} - -static gboolean -empathy_audio_src_levels_updated (gpointer user_data) -{ - EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (user_data); - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - - g_mutex_lock (priv->lock); - - g_signal_emit (self, signals[PEAK_LEVEL_CHANGED], 0, priv->peak_level); - g_signal_emit (self, signals[RMS_LEVEL_CHANGED], 0, priv->rms_level); - priv->idle_id = 0; - - g_mutex_unlock (priv->lock); - - return FALSE; -} - -static void -empathy_audio_src_handle_message (GstBin *bin, GstMessage *message) -{ - EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (bin); - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); - - if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT && - GST_MESSAGE_SRC (message) == GST_OBJECT (priv->level)) - { - const GstStructure *s; - const gchar *name; - const GValue *list; - guint i, len; - gdouble peak = -G_MAXDOUBLE; - gdouble rms = -G_MAXDOUBLE; - - s = gst_message_get_structure (message); - name = gst_structure_get_name (s); - - if (g_strcmp0 ("level", name) != 0) - goto out; - - list = gst_structure_get_value (s, "peak"); - len = gst_value_list_get_size (list); - - for (i =0 ; i < len; i++) - { - const GValue *value; - gdouble db; - - value = gst_value_list_get_value (list, i); - db = g_value_get_double (value); - peak = MAX (db, peak); - } - - list = gst_structure_get_value (s, "rms"); - len = gst_value_list_get_size (list); - - for (i =0 ; i < len; i++) - { - const GValue *value; - gdouble db; - - value = gst_value_list_get_value (list, i); - db = g_value_get_double (value); - rms = MAX (db, rms); - } - - g_mutex_lock (priv->lock); - - priv->peak_level = peak; - priv->rms_level = rms; - if (priv->idle_id == 0) - priv->idle_id = g_idle_add (empathy_audio_src_levels_updated, self); - - g_mutex_unlock (priv->lock); - } - -out: - GST_BIN_CLASS (empathy_audio_src_parent_class)->handle_message (bin, - message); -} - -GstElement * -empathy_audio_src_new (void) -{ - static gboolean registered = FALSE; - - if (!registered) { - if (!gst_element_register (NULL, "empathyaudiosrc", - GST_RANK_NONE, EMPATHY_TYPE_GST_AUDIO_SRC)) - return NULL; - registered = TRUE; - } - return gst_element_factory_make ("empathyaudiosrc", NULL); -} - -void -empathy_audio_src_set_volume (EmpathyGstAudioSrc *src, gdouble volume) -{ - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); - GParamSpec *pspec; - GParamSpecDouble *pspec_double; - - pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (priv->volume), - "volume"); - - g_assert (pspec != NULL); - - pspec_double = G_PARAM_SPEC_DOUBLE (pspec); - - volume = CLAMP (volume, pspec_double->minimum, pspec_double->maximum); - - g_object_set (G_OBJECT (priv->volume), "volume", volume, NULL); -} - -gdouble -empathy_audio_src_get_volume (EmpathyGstAudioSrc *src) -{ - EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); - gdouble volume; - - g_object_get (G_OBJECT (priv->volume), "volume", &volume, NULL); - - return volume; -} - - diff --git a/libempathy-gtk/empathy-audio-src.h b/libempathy-gtk/empathy-audio-src.h deleted file mode 100644 index 4bca31b61..000000000 --- a/libempathy-gtk/empathy-audio-src.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * empathy-gst-video-src.h - Header for EmpathyGstAudioSrc - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __EMPATHY_GST_AUDIO_SRC_H__ -#define __EMPATHY_GST_AUDIO_SRC_H__ - -#include -#include - -G_BEGIN_DECLS - -typedef struct _EmpathyGstAudioSrc EmpathyGstAudioSrc; -typedef struct _EmpathyGstAudioSrcClass EmpathyGstAudioSrcClass; - -struct _EmpathyGstAudioSrcClass { - GstBinClass parent_class; -}; - -struct _EmpathyGstAudioSrc { - GstBin parent; -}; - -GType empathy_audio_src_get_type (void); - -/* TYPE MACROS */ -#define EMPATHY_TYPE_GST_AUDIO_SRC \ - (empathy_audio_src_get_type ()) -#define EMPATHY_GST_AUDIO_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_GST_AUDIO_SRC, \ - EmpathyGstAudioSrc)) -#define EMPATHY_GST_AUDIO_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_GST_AUDIO_SRC, \ - EmpathyGstAudioSrcClass)) -#define EMPATHY_IS_GST_AUDIO_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_GST_AUDIO_SRC)) -#define EMPATHY_IS_GST_AUDIO_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_GST_AUDIO_SRC)) -#define EMPATHY_GST_AUDIO_SRC_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_GST_AUDIO_SRC, \ - EmpathyGstAudioSrcClass)) - -GstElement *empathy_audio_src_new (void); - -void empathy_audio_src_set_volume (EmpathyGstAudioSrc *src, gdouble volume); -gdouble empathy_audio_src_get_volume (EmpathyGstAudioSrc *src); - -G_END_DECLS - -#endif /* #ifndef __EMPATHY_GST_AUDIO_SRC_H__*/ diff --git a/libempathy-gtk/empathy-video-src.c b/libempathy-gtk/empathy-video-src.c deleted file mode 100644 index 5c865daaa..000000000 --- a/libempathy-gtk/empathy-video-src.c +++ /dev/null @@ -1,360 +0,0 @@ -/* - * empathy-gst-video-src.c - Source for EmpathyGstVideoSrc - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include - -#include - -#include "empathy-video-src.h" - -G_DEFINE_TYPE(EmpathyGstVideoSrc, empathy_video_src, GST_TYPE_BIN) - -/* Keep in sync with EmpathyGstVideoSrcChannel */ -static const gchar *channel_names[NR_EMPATHY_GST_VIDEO_SRC_CHANNELS] = { - "contrast", "brightness", "gamma" }; - -/* signal enum */ -#if 0 -enum -{ - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = {0}; -#endif - -/* private structure */ -typedef struct _EmpathyGstVideoSrcPrivate EmpathyGstVideoSrcPrivate; - -struct _EmpathyGstVideoSrcPrivate -{ - gboolean dispose_has_run; - GstElement *src; - /* Element implementing a ColorBalance interface */ - GstElement *balance; -}; - -#define EMPATHY_GST_VIDEO_SRC_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_VIDEO_SRC, \ - EmpathyGstVideoSrcPrivate)) -/** - * empathy_gst_add_to_bin - create a new gst element, add to bin and link it. - * @bin - bin to add the new element to. - * @src - src element for the new element (may be NULL). - * @name - name of the factory for the new element - * - * Returns: The newly created element ot %NULL on failure - */ -static GstElement * -empathy_gst_add_to_bin (GstBin *bin, - GstElement *src, - const gchar *factoryname) -{ - GstElement *ret; - - if ((ret = gst_element_factory_make (factoryname, NULL)) == NULL) - { - g_message ("Element factory \"%s\" not found.", factoryname); - goto error; - } - - if (!gst_bin_add (bin, ret)) - { - g_warning ("Couldn't add \"%s\" to bin.", factoryname); - goto error; - } - - /* do not link if src == NULL, just exit here */ - if (src == NULL) - return ret; - - if (!gst_element_link (src, ret)) - { - g_warning ("Failed to link \"%s\".", factoryname); - gst_bin_remove (bin, ret); - goto error; - } - - return ret; - -error: - if (ret != NULL) - gst_object_unref (ret); - return NULL; -} - - -static void -empathy_video_src_init (EmpathyGstVideoSrc *obj) -{ - EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (obj); - GstElement *element, *element_back; - GstPad *ghost, *src; - GstCaps *caps; - gchar *str; - - /* allocate caps here, so we can update it by optional elements */ - caps = gst_caps_new_simple ("video/x-raw-yuv", - "width", G_TYPE_INT, 320, - "height", G_TYPE_INT, 240, - NULL); - - /* allocate any data required by the object here */ - if ((element = empathy_gst_add_to_bin (GST_BIN (obj), - NULL, "gconfvideosrc")) == NULL) - g_error ("Couldn't add \"gconfvideosrc\" (gst-plugins-good missing?)"); - - /* we need to save our source to priv->src */ - priv->src = element; - - /* videomaxrate is optional as it's part of gst-plugins-bad. So don't - * fail if it doesn't exist. */ - element_back = element; - if ((element = empathy_gst_add_to_bin (GST_BIN (obj), - element, "videomaxrate")) == NULL) - { - g_message ("Couldn't add \"videomaxrate\" (gst-plugins-bad missing?)"); - element = element_back; - } - else - { - gst_caps_set_simple (caps, - "framerate", GST_TYPE_FRACTION, 15, 1, - NULL); - } - - str = gst_caps_to_string (caps); - g_debug ("Current video src caps are : %s", str); - g_free (str); - - if ((element = empathy_gst_add_to_bin (GST_BIN (obj), - element, "ffmpegcolorspace")) == NULL) - g_error ("Failed to add \"ffmpegcolorspace\" (gst-plugins-base missing?)"); - - if ((element = empathy_gst_add_to_bin (GST_BIN (obj), - element, "videoscale")) == NULL) - g_error ("Failed to add \"videoscale\", (gst-plugins-base missing?)"); - - if ((element = empathy_gst_add_to_bin (GST_BIN (obj), - element, "capsfilter")) == NULL) - g_error ( - "Failed to add \"capsfilter\" (gstreamer core elements missing?)"); - - g_object_set (G_OBJECT (element), "caps", caps, NULL); - - - /* optionally add postproc_tmpnoise to improve the performance of encoders */ - element_back = element; - if ((element = empathy_gst_add_to_bin (GST_BIN (obj), - element, "postproc_tmpnoise")) == NULL) - { - g_message ("Failed to add \"postproc_tmpnoise\" (gst-ffmpeg missing?)"); - element = element_back; - } - - src = gst_element_get_static_pad (element, "src"); - g_assert (src != NULL); - - ghost = gst_ghost_pad_new ("src", src); - if (ghost == NULL) - g_error ("Unable to create ghost pad for the videosrc"); - - if (!gst_element_add_pad (GST_ELEMENT (obj), ghost)) - g_error ("pad with the same name already existed or " - "the pad already had another parent."); - - gst_object_unref (G_OBJECT (src)); -} - -static void empathy_video_src_dispose (GObject *object); -static void empathy_video_src_finalize (GObject *object); - -static void -empathy_video_src_class_init (EmpathyGstVideoSrcClass *empathy_video_src_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (empathy_video_src_class); - - g_type_class_add_private (empathy_video_src_class, - sizeof (EmpathyGstVideoSrcPrivate)); - - object_class->dispose = empathy_video_src_dispose; - object_class->finalize = empathy_video_src_finalize; -} - -void -empathy_video_src_dispose (GObject *object) -{ - EmpathyGstVideoSrc *self = EMPATHY_GST_VIDEO_SRC (object); - EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (self); - - if (priv->dispose_has_run) - return; - - priv->dispose_has_run = TRUE; - - /* release any references held by the object here */ - - if (G_OBJECT_CLASS (empathy_video_src_parent_class)->dispose) - G_OBJECT_CLASS (empathy_video_src_parent_class)->dispose (object); -} - -void -empathy_video_src_finalize (GObject *object) -{ - //EmpathyGstVideoSrc *self = EMPATHY_GST_VIDEO_SRC (object); - //EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (self); - - /* free any data held directly by the object here */ - - G_OBJECT_CLASS (empathy_video_src_parent_class)->finalize (object); -} - -GstElement * -empathy_video_src_new (void) -{ - static gboolean registered = FALSE; - - if (!registered) { - if (!gst_element_register (NULL, "empathyvideosrc", - GST_RANK_NONE, EMPATHY_TYPE_GST_VIDEO_SRC)) - return NULL; - registered = TRUE; - } - return gst_element_factory_make ("empathyvideosrc", NULL); -} - -void -empathy_video_src_set_channel (GstElement *src, - EmpathyGstVideoSrcChannel channel, guint percent) -{ - GstElement *color; - GstColorBalance *balance; - const GList *channels; - GList *l; - - /* Find something supporting GstColorBalance */ - color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE); - - if (color == NULL) - return; - - balance = GST_COLOR_BALANCE (color); - - channels = gst_color_balance_list_channels (balance); - - for (l = (GList *) channels; l != NULL; l = g_list_next (l)) - { - GstColorBalanceChannel *c = GST_COLOR_BALANCE_CHANNEL (l->data); - - if (g_ascii_strcasecmp (c->label, channel_names[channel]) == 0) - { - gst_color_balance_set_value (balance, c, - ((c->max_value - c->min_value) * percent)/100 - + c->min_value); - break; - } - } - - g_object_unref (color); -} - -guint -empathy_video_src_get_channel (GstElement *src, - EmpathyGstVideoSrcChannel channel) -{ - GstElement *color; - GstColorBalance *balance; - const GList *channels; - GList *l; - guint percent = 0; - - /* Find something supporting GstColorBalance */ - color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE); - - if (color == NULL) - return percent; - - balance = GST_COLOR_BALANCE (color); - - channels = gst_color_balance_list_channels (balance); - - for (l = (GList *) channels; l != NULL; l = g_list_next (l)) - { - GstColorBalanceChannel *c = GST_COLOR_BALANCE_CHANNEL (l->data); - - if (g_ascii_strcasecmp (c->label, channel_names[channel]) == 0) - { - percent = - ((gst_color_balance_get_value (balance, c) - - c->min_value) * 100) / - (c->max_value - c->min_value); - - break; - } - } - - g_object_unref (color); - - return percent; -} - - -guint -empathy_video_src_get_supported_channels (GstElement *src) -{ - GstElement *color; - GstColorBalance *balance; - const GList *channels; - GList *l; - guint result = 0; - - /* Find something supporting GstColorBalance */ - color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE); - - if (color == NULL) - goto out; - - balance = GST_COLOR_BALANCE (color); - - channels = gst_color_balance_list_channels (balance); - - for (l = (GList *) channels; l != NULL; l = g_list_next (l)) - { - GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (l->data); - int i; - - for (i = 0; i < NR_EMPATHY_GST_VIDEO_SRC_CHANNELS; i++) - { - if (g_ascii_strcasecmp (channel->label, channel_names[i]) == 0) - { - result |= (1 << i); - break; - } - } - } - - g_object_unref (color); - -out: - return result; -} - diff --git a/libempathy-gtk/empathy-video-src.h b/libempathy-gtk/empathy-video-src.h deleted file mode 100644 index fae5563eb..000000000 --- a/libempathy-gtk/empathy-video-src.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * empathy-gst-video-src.h - Header for EmpathyGstVideoSrc - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __EMPATHY_GST_VIDEO_SRC_H__ -#define __EMPATHY_GST_VIDEO_SRC_H__ - -#include -#include - -G_BEGIN_DECLS - -typedef struct _EmpathyGstVideoSrc EmpathyGstVideoSrc; -typedef struct _EmpathyGstVideoSrcClass EmpathyGstVideoSrcClass; - -typedef enum { - EMPATHY_GST_VIDEO_SRC_CHANNEL_CONTRAST = 0, - EMPATHY_GST_VIDEO_SRC_CHANNEL_BRIGHTNESS = 1, - EMPATHY_GST_VIDEO_SRC_CHANNEL_GAMMA = 2, - NR_EMPATHY_GST_VIDEO_SRC_CHANNELS -} EmpathyGstVideoSrcChannel; - -#define EMPATHY_GST_VIDEO_SRC_SUPPORTS_CONTRAST \ - (1 << EMPATHY_GST_VIDEO_SRC_CHANNEL_CONTRAST) -#define EMPATHY_GST_VIDEO_SRC_SUPPORTS_BRIGHTNESS \ - (1 << EMPATHY_GST_VIDEO_SRC_CHANNEL_BRIGHTNESS) -#define EMPATHY_GST_VIDEO_SRC_SUPPORTS_GAMMA \ - (1 << EMPATHY_GST_VIDEO_SRC_CHANNEL_GAMMA) - -struct _EmpathyGstVideoSrcClass { - GstBinClass parent_class; -}; - -struct _EmpathyGstVideoSrc { - GstBin parent; -}; - -GType empathy_video_src_get_type (void); - -/* TYPE MACROS */ -#define EMPATHY_TYPE_GST_VIDEO_SRC \ - (empathy_video_src_get_type ()) -#define EMPATHY_GST_VIDEO_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_GST_VIDEO_SRC, \ - EmpathyGstVideoSrc)) -#define EMPATHY_GST_VIDEO_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_GST_VIDEO_SRC, \ - EmpathyGstVideoSrcClass)) -#define EMPATHY_IS_GST_VIDEO_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_GST_VIDEO_SRC)) -#define EMPATHY_IS_GST_VIDEO_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_GST_VIDEO_SRC)) -#define EMPATHY_GST_VIDEO_SRC_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_GST_VIDEO_SRC, \ - EmpathyGstVideoSrcClass)) - -GstElement *empathy_video_src_new (void); - -guint -empathy_video_src_get_supported_channels (GstElement *src); - -void empathy_video_src_set_channel (GstElement *src, - EmpathyGstVideoSrcChannel channel, guint percent); - -guint empathy_video_src_get_channel (GstElement *src, - EmpathyGstVideoSrcChannel channel); - -G_END_DECLS - -#endif /* #ifndef __EMPATHY_GST_VIDEO_SRC_H__*/ diff --git a/libempathy-gtk/empathy-video-widget.c b/libempathy-gtk/empathy-video-widget.c deleted file mode 100644 index a3b13fd12..000000000 --- a/libempathy-gtk/empathy-video-widget.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * empathy-gst-gtk-widget.c - Source for EmpathyVideoWidget - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include -#include - -#include -#include -#include - -#include "empathy-video-widget.h" - -G_DEFINE_TYPE(EmpathyVideoWidget, empathy_video_widget, - GTK_TYPE_DRAWING_AREA) - -static void empathy_video_widget_element_added_cb ( - FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, - EmpathyVideoWidget *self); - -static void empathy_video_widget_sync_message_cb ( - GstBus *bus, GstMessage *message, EmpathyVideoWidget *self); - -/* signal enum */ -#if 0 -enum -{ - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = {0}; -#endif - -enum { - PROP_GST_ELEMENT = 1, - PROP_GST_BUS, - PROP_MIN_WIDTH, - PROP_MIN_HEIGHT, - PROP_SYNC, - PROP_ASYNC, -}; - -/* private structure */ -typedef struct _EmpathyVideoWidgetPriv EmpathyVideoWidgetPriv; - -struct _EmpathyVideoWidgetPriv -{ - gboolean dispose_has_run; - GstBus *bus; - GstElement *videosink; - GstPad *sink_pad; - GstElement *overlay; - FsElementAddedNotifier *notifier; - gint min_width; - gint min_height; - gboolean sync; - gboolean async; - - GMutex *lock; -}; - -#define GET_PRIV(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - EMPATHY_TYPE_VIDEO_WIDGET, EmpathyVideoWidgetPriv)) - -static void -empathy_video_widget_init (EmpathyVideoWidget *obj) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (obj); - GdkColor black; - - priv->lock = g_mutex_new (); - - priv->notifier = fs_element_added_notifier_new (); - g_signal_connect (priv->notifier, "element-added", - G_CALLBACK (empathy_video_widget_element_added_cb), - obj); - - if (gdk_color_parse ("Black", &black)) - gtk_widget_modify_bg (GTK_WIDGET (obj), GTK_STATE_NORMAL, - &black); - - gtk_widget_set_double_buffered (GTK_WIDGET (obj), FALSE); -} - -static void -empathy_video_widget_realized (GtkWidget *widget, gpointer user_data) -{ - /* requesting the XID forces the GdkWindow to be native in GTK+ 2.18 - * onwards, requesting the native window in a thread causes a BadWindowID, - * so we need to request it now. We could call gdk_window_ensure_native(), - * but that would mean we require GTK+ 2.18, so instead we call this */ - GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (widget))); -} - -static void -empathy_video_widget_constructed (GObject *object) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (object); - GstElement *colorspace, *videoscale, *sink; - GstPad *pad; - - g_signal_connect (object, "realize", - G_CALLBACK (empathy_video_widget_realized), NULL); - - priv->videosink = gst_bin_new (NULL); - - gst_object_ref (priv->videosink); - gst_object_sink (priv->videosink); - - priv->sink_pad = gst_element_get_static_pad (priv->videosink, "sink"); - - sink = gst_element_factory_make ("gconfvideosink", NULL); - g_assert (sink != NULL); - - videoscale = gst_element_factory_make ("videoscale", NULL); - g_assert (videoscale != NULL); - - g_object_set (videoscale, "qos", FALSE, NULL); - - colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL); - g_assert (colorspace != NULL); - - g_object_set (colorspace, "qos", FALSE, NULL); - - gst_bin_add_many (GST_BIN (priv->videosink), colorspace, videoscale, - sink, NULL); - - if (!gst_element_link (colorspace, videoscale)) - g_error ("Failed to link ffmpegcolorspace and videoscale"); - - if (!gst_element_link (videoscale, sink)) - g_error ("Failed to link videoscale and gconfvideosink"); - - pad = gst_element_get_static_pad (colorspace, "sink"); - g_assert (pad != NULL); - - priv->sink_pad = gst_ghost_pad_new ("sink", pad); - if (!gst_element_add_pad (priv->videosink, priv->sink_pad)) - g_error ("Couldn't add sink ghostpad to the bin"); - - gst_object_unref (pad); - - fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->videosink)); - gst_bus_enable_sync_message_emission (priv->bus); - - g_signal_connect (priv->bus, "sync-message", - G_CALLBACK (empathy_video_widget_sync_message_cb), object); - - gtk_widget_set_size_request (GTK_WIDGET (object), priv->min_width, - priv->min_height); -} - -static void empathy_video_widget_dispose (GObject *object); -static void empathy_video_widget_finalize (GObject *object); - -static gboolean empathy_video_widget_expose_event (GtkWidget *widget, - GdkEventExpose *event); -static void -empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self); - -static void -empathy_video_widget_set_property (GObject *object, - guint property_id, const GValue *value, GParamSpec *pspec) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (object); - - switch (property_id) - { - case PROP_GST_BUS: - priv->bus = g_value_dup_object (value); - break; - case PROP_MIN_WIDTH: - priv->min_width = g_value_get_int (value); - break; - case PROP_MIN_HEIGHT: - priv->min_height = g_value_get_int (value); - break; - case PROP_SYNC: - priv->sync = g_value_get_boolean (value); - empathy_video_widget_element_set_sink_properties ( - EMPATHY_VIDEO_WIDGET (object)); - break; - case PROP_ASYNC: - priv->async = g_value_get_boolean (value); - empathy_video_widget_element_set_sink_properties ( - EMPATHY_VIDEO_WIDGET (object)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -empathy_video_widget_get_property (GObject *object, - guint property_id, GValue *value, GParamSpec *pspec) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (object); - - switch (property_id) - { - case PROP_GST_ELEMENT: - g_value_set_object (value, priv->videosink); - break; - case PROP_GST_BUS: - g_value_set_object (value, priv->bus); - break; - case PROP_MIN_WIDTH: - g_value_set_int (value, priv->min_width); - break; - case PROP_MIN_HEIGHT: - g_value_set_int (value, priv->min_height); - break; - case PROP_SYNC: - g_value_set_boolean (value, priv->sync); - break; - case PROP_ASYNC: - g_value_set_boolean (value, priv->async); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - - -static void -empathy_video_widget_class_init ( - EmpathyVideoWidgetClass *empathy_video_widget_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (empathy_video_widget_class); - GtkWidgetClass *widget_class = - GTK_WIDGET_CLASS (empathy_video_widget_class); - GParamSpec *param_spec; - - g_type_class_add_private (empathy_video_widget_class, - sizeof (EmpathyVideoWidgetPriv)); - - object_class->dispose = empathy_video_widget_dispose; - object_class->finalize = empathy_video_widget_finalize; - object_class->constructed = empathy_video_widget_constructed; - - object_class->set_property = empathy_video_widget_set_property; - object_class->get_property = empathy_video_widget_get_property; - - widget_class->expose_event = empathy_video_widget_expose_event; - - param_spec = g_param_spec_object ("gst-element", - "gst-element", "The underlaying gstreamer element", - GST_TYPE_ELEMENT, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_GST_ELEMENT, param_spec); - - param_spec = g_param_spec_object ("gst-bus", - "gst-bus", - "The toplevel bus from the pipeline in which this bin will be added", - GST_TYPE_BUS, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_GST_BUS, param_spec); - - param_spec = g_param_spec_int ("min-width", - "min-width", - "Minimal width of the widget", - 0, G_MAXINT, EMPATHY_VIDEO_WIDGET_DEFAULT_WIDTH, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_MIN_WIDTH, param_spec); - - param_spec = g_param_spec_int ("min-height", - "min-height", - "Minimal height of the widget", - 0, G_MAXINT, EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_MIN_HEIGHT, param_spec); - - param_spec = g_param_spec_boolean ("sync", - "sync", - "Whether the underlying sink should be sync or not", - TRUE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_SYNC, param_spec); - - param_spec = g_param_spec_boolean ("async", - "async", - "Whether the underlying sink should be async or not", - TRUE, - G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_ASYNC, param_spec); -} - -void -empathy_video_widget_dispose (GObject *object) -{ - EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object); - EmpathyVideoWidgetPriv *priv = GET_PRIV (self); - - if (priv->dispose_has_run) - return; - - priv->dispose_has_run = TRUE; - - g_signal_handlers_disconnect_by_func (priv->bus, - empathy_video_widget_sync_message_cb, object); - - if (priv->bus != NULL) - g_object_unref (priv->bus); - - priv->bus = NULL; - - if (priv->videosink != NULL) - g_object_unref (priv->videosink); - - priv->videosink = NULL; - - - /* release any references held by the object here */ - - if (G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose) - G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose (object); -} - -void -empathy_video_widget_finalize (GObject *object) -{ - EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object); - EmpathyVideoWidgetPriv *priv = GET_PRIV (self); - - /* free any data held directly by the object here */ - g_mutex_free (priv->lock); - - G_OBJECT_CLASS (empathy_video_widget_parent_class)->finalize (object); -} - - -static void -empathy_video_widget_element_set_sink_properties_unlocked ( - EmpathyVideoWidget *self) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (self); - - if (priv->overlay == NULL) - return; - - if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay), - "force-aspect-ratio")) - g_object_set (G_OBJECT (priv->overlay), "force-aspect-ratio", TRUE, NULL); - - if (g_object_class_find_property ( - G_OBJECT_GET_CLASS (priv->overlay), "sync")) - g_object_set (G_OBJECT (priv->overlay), "sync", priv->sync, NULL); - - if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay), - "async")) - g_object_set (G_OBJECT (priv->overlay), "async", priv->async, NULL); -} - -static void -empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (self); - - g_mutex_lock (priv->lock); - empathy_video_widget_element_set_sink_properties_unlocked (self); - g_mutex_unlock (priv->lock); -} - -static void -empathy_video_widget_element_added_cb (FsElementAddedNotifier *notifier, - GstBin *bin, GstElement *element, EmpathyVideoWidget *self) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (self); - - /* We assume the overlay is the sink */ - g_mutex_lock (priv->lock); - if (priv->overlay == NULL && GST_IS_X_OVERLAY (element)) - { - priv->overlay = element; - g_object_add_weak_pointer (G_OBJECT (element), - (gpointer) &priv->overlay); - empathy_video_widget_element_set_sink_properties_unlocked (self); - gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay)); - } - g_mutex_unlock (priv->lock); -} - -static void -empathy_video_widget_sync_message_cb (GstBus *bus, GstMessage *message, - EmpathyVideoWidget *self) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (self); - const GstStructure *s; - - if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) - return; - - if (GST_MESSAGE_SRC (message) != (GstObject *) priv->overlay) - return; - - s = gst_message_get_structure (message); - - if (gst_structure_has_name (s, "prepare-xwindow-id")) - { - g_assert (gtk_widget_get_realized (GTK_WIDGET (self))); - gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay), - GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (self)))); - } -} - -static gboolean -empathy_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event) -{ - EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (widget); - EmpathyVideoWidgetPriv *priv = GET_PRIV (self); - GtkAllocation allocation; - - if (event != NULL && event->count > 0) - return TRUE; - - if (priv->overlay == NULL) - { - gtk_widget_get_allocation (widget, &allocation); - gdk_window_clear_area (gtk_widget_get_window (widget), 0, 0, - allocation.width, allocation.height); - return TRUE; - } - - gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay), - GDK_WINDOW_XID (gtk_widget_get_window (widget))); - - gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay)); - - return TRUE; -} - -GtkWidget * -empathy_video_widget_new_with_size (GstBus *bus, gint width, gint height) -{ - g_return_val_if_fail (bus != NULL, NULL); - - return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET, - "gst-bus", bus, - "min-width", width, - "min-height", height, - NULL)); -} - -GtkWidget * -empathy_video_widget_new (GstBus *bus) -{ - g_return_val_if_fail (bus != NULL, NULL); - - return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET, - "gst-bus", bus, - NULL)); -} - -GstPad * -empathy_video_widget_get_sink (EmpathyVideoWidget *widget) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (widget); - - return priv->sink_pad; -} - -GstElement * -empathy_video_widget_get_element (EmpathyVideoWidget *widget) -{ - EmpathyVideoWidgetPriv *priv = GET_PRIV (widget); - - return priv->videosink; -} diff --git a/libempathy-gtk/empathy-video-widget.h b/libempathy-gtk/empathy-video-widget.h deleted file mode 100644 index cfdd0354c..000000000 --- a/libempathy-gtk/empathy-video-widget.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * empathy-gst-gtk-widget.h - Header for EmpathyVideoWidget - * Copyright (C) 2008 Collabora Ltd. - * @author Sjoerd Simons - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __EMPATHY_VIDEO_WIDGET_H__ -#define __EMPATHY_VIDEO_WIDGET_H__ - -#define EMPATHY_VIDEO_WIDGET_DEFAULT_WIDTH 320 -#define EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT 240 - -#include -#include -#include - -G_BEGIN_DECLS - -typedef struct _EmpathyVideoWidget EmpathyVideoWidget; -typedef struct _EmpathyVideoWidgetClass EmpathyVideoWidgetClass; - -struct _EmpathyVideoWidgetClass { - GtkDrawingAreaClass parent_class; -}; - -struct _EmpathyVideoWidget { - GtkDrawingArea parent; -}; - -GType empathy_video_widget_get_type (void); - -/* TYPE MACROS */ -#define EMPATHY_TYPE_VIDEO_WIDGET \ - (empathy_video_widget_get_type ()) -#define EMPATHY_VIDEO_WIDGET(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_VIDEO_WIDGET, \ - EmpathyVideoWidget)) -#define EMPATHY_VIDEO_WIDGET_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_VIDEO_WIDGET, \ - EmpathyVideoWidgetClass)) -#define EMPATHY_IS_VIDEO_WIDGET(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_VIDEO_WIDGET)) -#define EMPATHY_IS_VIDEO_WIDGET_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_VIDEO_WIDGET)) -#define EMPATHY_VIDEO_WIDGET_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_VIDEO_WIDGET, \ - EmpathyVideoWidgetClass)) - -GtkWidget *empathy_video_widget_new (GstBus *bus); -GtkWidget *empathy_video_widget_new_with_size (GstBus *bus, - gint width, gint height); - -GstElement *empathy_video_widget_get_element (EmpathyVideoWidget *widget); -GstPad *empathy_video_widget_get_sink (EmpathyVideoWidget *widget); - -G_END_DECLS - -#endif /* #ifndef __EMPATHY_VIDEO_WIDGET_H__*/ diff --git a/src/Makefile.am b/src/Makefile.am index 1b0d4e078..ffa708390 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,6 +111,10 @@ empathy_debugger_SOURCES = \ empathy_av_SOURCES = \ empathy-av.c \ + empathy-audio-sink.c \ + empathy-audio-sink.h \ + empathy-audio-src.c \ + empathy-audio-src.h \ empathy-streamed-media-factory.c \ empathy-streamed-media-factory.h \ empathy-streamed-media-handler.c \ @@ -121,7 +125,10 @@ empathy_av_SOURCES = \ empathy-streamed-media-window.h \ empathy-sidebar.c \ empathy-sidebar.h \ - $(NULL) + empathy-video-src.c \ + empathy-video-src.h \ + empathy-video-widget.c \ + empathy-video-widget.h nodist_empathy_av_SOURCES = $(BUILT_SOURCES) diff --git a/src/empathy-audio-sink.c b/src/empathy-audio-sink.c new file mode 100644 index 000000000..1d2169593 --- /dev/null +++ b/src/empathy-audio-sink.c @@ -0,0 +1,235 @@ +/* + * empathy-gst-audio-sink.c - Source for EmpathyGstAudioSink + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "empathy-audio-sink.h" + + +G_DEFINE_TYPE(EmpathyGstAudioSink, empathy_audio_sink, GST_TYPE_BIN) + +/* signal enum */ +#if 0 +enum +{ + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; +#endif + +enum { + PROP_VOLUME = 1, +}; + +/* private structure */ +typedef struct _EmpathyGstAudioSinkPrivate EmpathyGstAudioSinkPrivate; + +struct _EmpathyGstAudioSinkPrivate +{ + gboolean dispose_has_run; + GstElement *sink; + GstElement *volume; + FsElementAddedNotifier *notifier; +}; + +#define EMPATHY_GST_AUDIO_SINK_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SINK, \ + EmpathyGstAudioSinkPrivate)) + +static void +empathy_audio_sink_element_added_cb (FsElementAddedNotifier *notifier, + GstBin *bin, GstElement *element, EmpathyGstAudioSink *self) +{ + EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self); + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume")) + { + gdouble volume; + + volume = empathy_audio_sink_get_volume (self); + empathy_audio_sink_set_volume (self, 1.0); + + if (priv->volume != NULL) + g_object_unref (priv->volume); + priv->volume = g_object_ref (element); + + if (volume != 1.0) + empathy_audio_sink_set_volume (self, volume); + } +} + +static void +empathy_audio_sink_init (EmpathyGstAudioSink *obj) +{ + EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (obj); + GstElement *resample; + GstPad *ghost, *sink; + + priv->notifier = fs_element_added_notifier_new (); + g_signal_connect (priv->notifier, "element-added", + G_CALLBACK (empathy_audio_sink_element_added_cb), obj); + + resample = gst_element_factory_make ("audioresample", NULL); + + priv->volume = gst_element_factory_make ("volume", NULL); + g_object_ref (priv->volume); + + priv->sink = gst_element_factory_make ("gconfaudiosink", NULL); + + fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->sink)); + + gst_bin_add_many (GST_BIN (obj), resample, priv->volume, priv->sink, NULL); + gst_element_link_many (resample, priv->volume, priv->sink, NULL); + + sink = gst_element_get_static_pad (resample, "sink"); + + ghost = gst_ghost_pad_new ("sink", sink); + gst_element_add_pad (GST_ELEMENT (obj), ghost); + + gst_object_unref (G_OBJECT (sink)); +} + +static void empathy_audio_sink_dispose (GObject *object); +static void empathy_audio_sink_finalize (GObject *object); + +static void +empathy_audio_sink_set_property (GObject *object, + guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_VOLUME: + empathy_audio_sink_set_volume (EMPATHY_GST_AUDIO_SINK (object), + g_value_get_double (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_audio_sink_get_property (GObject *object, + guint property_id, GValue *value, GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_VOLUME: + g_value_set_double (value, + empathy_audio_sink_get_volume (EMPATHY_GST_AUDIO_SINK (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_audio_sink_class_init (EmpathyGstAudioSinkClass + *empathy_audio_sink_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (empathy_audio_sink_class); + GParamSpec *param_spec; + + g_type_class_add_private (empathy_audio_sink_class, + sizeof (EmpathyGstAudioSinkPrivate)); + + object_class->dispose = empathy_audio_sink_dispose; + object_class->finalize = empathy_audio_sink_finalize; + + object_class->set_property = empathy_audio_sink_set_property; + object_class->get_property = empathy_audio_sink_get_property; + + param_spec = g_param_spec_double ("volume", "Volume", "volume control", + 0.0, 5.0, 1.0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_VOLUME, param_spec); +} + +void +empathy_audio_sink_dispose (GObject *object) +{ + EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object); + EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->notifier != NULL) + g_object_unref (priv->notifier); + priv->notifier = NULL; + + if (priv->volume != NULL) + g_object_unref (priv->volume); + priv->volume = NULL; + + if (G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose) + G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose (object); +} + +void +empathy_audio_sink_finalize (GObject *object) +{ + //EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object); + //EmpathyGstAudioSinkPrivate *priv = + // EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self); + + /* free any data held directly by the object here */ + + G_OBJECT_CLASS (empathy_audio_sink_parent_class)->finalize (object); +} + +GstElement * +empathy_audio_sink_new (void) +{ + static gboolean registered = FALSE; + + if (!registered) { + if (!gst_element_register (NULL, "empathyaudiosink", + GST_RANK_NONE, EMPATHY_TYPE_GST_AUDIO_SINK)) + return NULL; + registered = TRUE; + } + return gst_element_factory_make ("empathyaudiosink", NULL); +} + +void +empathy_audio_sink_set_volume (EmpathyGstAudioSink *sink, gdouble volume) +{ + EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (sink); + + g_object_set (G_OBJECT (priv->volume), "volume", volume, NULL); +} + +gdouble +empathy_audio_sink_get_volume (EmpathyGstAudioSink *sink) +{ + EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (sink); + gdouble volume; + + g_object_get (G_OBJECT (priv->volume), "volume", &volume, NULL); + + return volume; +} diff --git a/src/empathy-audio-sink.h b/src/empathy-audio-sink.h new file mode 100644 index 000000000..21ebf2b5a --- /dev/null +++ b/src/empathy-audio-sink.h @@ -0,0 +1,67 @@ +/* + * empathy-gst-video-sink.h - Header for EmpathyGstAudioSink + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EMPATHY_GST_AUDIO_SINK_H__ +#define __EMPATHY_GST_AUDIO_SINK_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _EmpathyGstAudioSink EmpathyGstAudioSink; +typedef struct _EmpathyGstAudioSinkClass EmpathyGstAudioSinkClass; + +struct _EmpathyGstAudioSinkClass { + GstBinClass parent_class; +}; + +struct _EmpathyGstAudioSink { + GstBin parent; +}; + +GType empathy_audio_sink_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_GST_AUDIO_SINK \ + (empathy_audio_sink_get_type ()) +#define EMPATHY_GST_AUDIO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_GST_AUDIO_SINK, \ + EmpathyGstAudioSink)) +#define EMPATHY_GST_AUDIO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_GST_AUDIO_SINK, \ + EmpathyGstAudioSinkClass)) +#define EMPATHY_IS_GST_AUDIO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_GST_AUDIO_SINK)) +#define EMPATHY_IS_GST_AUDIO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_GST_AUDIO_SINK)) +#define EMPATHY_GST_AUDIO_SINK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_GST_AUDIO_SINK, \ + EmpathyGstAudioSinkClass)) + +GstElement *empathy_audio_sink_new (void); + +void empathy_audio_sink_set_volume (EmpathyGstAudioSink *sink, gdouble volume); + +gdouble empathy_audio_sink_get_volume (EmpathyGstAudioSink *sink); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_GST_AUDIO_SINK_H__*/ diff --git a/src/empathy-audio-src.c b/src/empathy-audio-src.c new file mode 100644 index 000000000..a3416f2ea --- /dev/null +++ b/src/empathy-audio-src.c @@ -0,0 +1,387 @@ +/* + * empathy-gst-audio-src.c - Source for EmpathyGstAudioSrc + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include +#include "empathy-audio-src.h" + +G_DEFINE_TYPE(EmpathyGstAudioSrc, empathy_audio_src, GST_TYPE_BIN) + +/* signal enum */ +enum +{ + PEAK_LEVEL_CHANGED, + RMS_LEVEL_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + +enum { + PROP_VOLUME = 1, + PROP_RMS_LEVEL, + PROP_PEAK_LEVEL, +}; + +/* private structure */ +typedef struct _EmpathyGstAudioSrcPrivate EmpathyGstAudioSrcPrivate; + +struct _EmpathyGstAudioSrcPrivate +{ + gboolean dispose_has_run; + GstElement *src; + GstElement *volume; + GstElement *level; + FsElementAddedNotifier *notifier; + + gdouble peak_level; + gdouble rms_level; + + GMutex *lock; + guint idle_id; +}; + +#define EMPATHY_GST_AUDIO_SRC_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SRC, \ + EmpathyGstAudioSrcPrivate)) + +static void +empathy_audio_src_element_added_cb (FsElementAddedNotifier *notifier, + GstBin *bin, GstElement *element, EmpathyGstAudioSrc *self) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume")) + { + gdouble volume; + + volume = empathy_audio_src_get_volume (self); + empathy_audio_src_set_volume (self, 1.0); + + if (priv->volume != NULL) + g_object_unref (priv->volume); + priv->volume = g_object_ref (element); + + if (volume != 1.0) + empathy_audio_src_set_volume (self, volume); + } +} + +static void +empathy_audio_src_init (EmpathyGstAudioSrc *obj) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (obj); + GstPad *ghost, *src; + + priv->peak_level = -G_MAXDOUBLE; + priv->lock = g_mutex_new (); + + priv->notifier = fs_element_added_notifier_new (); + g_signal_connect (priv->notifier, "element-added", + G_CALLBACK (empathy_audio_src_element_added_cb), obj); + + priv->src = gst_element_factory_make ("gconfaudiosrc", NULL); + gst_bin_add (GST_BIN (obj), priv->src); + + fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->src)); + + priv->volume = gst_element_factory_make ("volume", NULL); + g_object_ref (priv->volume); + + gst_bin_add (GST_BIN (obj), priv->volume); + gst_element_link (priv->src, priv->volume); + + priv->level = gst_element_factory_make ("level", NULL); + gst_bin_add (GST_BIN (obj), priv->level); + gst_element_link (priv->volume, priv->level); + + src = gst_element_get_static_pad (priv->level, "src"); + + ghost = gst_ghost_pad_new ("src", src); + gst_element_add_pad (GST_ELEMENT (obj), ghost); + + gst_object_unref (G_OBJECT (src)); +} + +static void empathy_audio_src_dispose (GObject *object); +static void empathy_audio_src_finalize (GObject *object); +static void empathy_audio_src_handle_message (GstBin *bin, + GstMessage *message); + +static gboolean empathy_audio_src_levels_updated (gpointer user_data); + +static void +empathy_audio_src_set_property (GObject *object, + guint property_id, const GValue *value, GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_VOLUME: + empathy_audio_src_set_volume (EMPATHY_GST_AUDIO_SRC (object), + g_value_get_double (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_audio_src_get_property (GObject *object, + guint property_id, GValue *value, GParamSpec *pspec) +{ + EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object); + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + switch (property_id) + { + case PROP_VOLUME: + g_value_set_double (value, + empathy_audio_src_get_volume (self)); + break; + case PROP_PEAK_LEVEL: + g_mutex_lock (priv->lock); + g_value_set_double (value, priv->peak_level); + g_mutex_unlock (priv->lock); + break; + case PROP_RMS_LEVEL: + g_mutex_lock (priv->lock); + g_value_set_double (value, priv->rms_level); + g_mutex_unlock (priv->lock); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_audio_src_class_init (EmpathyGstAudioSrcClass + *empathy_audio_src_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (empathy_audio_src_class); + GstBinClass *gstbin_class = GST_BIN_CLASS (empathy_audio_src_class); + GParamSpec *param_spec; + + g_type_class_add_private (empathy_audio_src_class, + sizeof (EmpathyGstAudioSrcPrivate)); + + object_class->dispose = empathy_audio_src_dispose; + object_class->finalize = empathy_audio_src_finalize; + + object_class->set_property = empathy_audio_src_set_property; + object_class->get_property = empathy_audio_src_get_property; + + gstbin_class->handle_message = + GST_DEBUG_FUNCPTR (empathy_audio_src_handle_message); + + param_spec = g_param_spec_double ("volume", "Volume", "volume contol", + 0.0, 5.0, 1.0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_VOLUME, param_spec); + + param_spec = g_param_spec_double ("peak-level", "peak level", "peak level", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_VOLUME, param_spec); + + signals[PEAK_LEVEL_CHANGED] = g_signal_new ("peak-level-changed", + G_TYPE_FROM_CLASS (empathy_audio_src_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, G_TYPE_DOUBLE); + + param_spec = g_param_spec_double ("rms-level", "RMS level", "RMS level", + -G_MAXDOUBLE, G_MAXDOUBLE, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_VOLUME, param_spec); + + + signals[RMS_LEVEL_CHANGED] = g_signal_new ("rms-level-changed", + G_TYPE_FROM_CLASS (empathy_audio_src_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, G_TYPE_DOUBLE); +} + +void +empathy_audio_src_dispose (GObject *object) +{ + EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object); + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + if (priv->idle_id != 0) + g_source_remove (priv->idle_id); + + priv->idle_id = 0; + + /* release any references held by the object here */ + + if (G_OBJECT_CLASS (empathy_audio_src_parent_class)->dispose) + G_OBJECT_CLASS (empathy_audio_src_parent_class)->dispose (object); +} + +void +empathy_audio_src_finalize (GObject *object) +{ + EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (object); + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + /* free any data held directly by the object here */ + g_mutex_free (priv->lock); + + G_OBJECT_CLASS (empathy_audio_src_parent_class)->finalize (object); +} + +static gboolean +empathy_audio_src_levels_updated (gpointer user_data) +{ + EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (user_data); + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + g_mutex_lock (priv->lock); + + g_signal_emit (self, signals[PEAK_LEVEL_CHANGED], 0, priv->peak_level); + g_signal_emit (self, signals[RMS_LEVEL_CHANGED], 0, priv->rms_level); + priv->idle_id = 0; + + g_mutex_unlock (priv->lock); + + return FALSE; +} + +static void +empathy_audio_src_handle_message (GstBin *bin, GstMessage *message) +{ + EmpathyGstAudioSrc *self = EMPATHY_GST_AUDIO_SRC (bin); + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (self); + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT && + GST_MESSAGE_SRC (message) == GST_OBJECT (priv->level)) + { + const GstStructure *s; + const gchar *name; + const GValue *list; + guint i, len; + gdouble peak = -G_MAXDOUBLE; + gdouble rms = -G_MAXDOUBLE; + + s = gst_message_get_structure (message); + name = gst_structure_get_name (s); + + if (g_strcmp0 ("level", name) != 0) + goto out; + + list = gst_structure_get_value (s, "peak"); + len = gst_value_list_get_size (list); + + for (i =0 ; i < len; i++) + { + const GValue *value; + gdouble db; + + value = gst_value_list_get_value (list, i); + db = g_value_get_double (value); + peak = MAX (db, peak); + } + + list = gst_structure_get_value (s, "rms"); + len = gst_value_list_get_size (list); + + for (i =0 ; i < len; i++) + { + const GValue *value; + gdouble db; + + value = gst_value_list_get_value (list, i); + db = g_value_get_double (value); + rms = MAX (db, rms); + } + + g_mutex_lock (priv->lock); + + priv->peak_level = peak; + priv->rms_level = rms; + if (priv->idle_id == 0) + priv->idle_id = g_idle_add (empathy_audio_src_levels_updated, self); + + g_mutex_unlock (priv->lock); + } + +out: + GST_BIN_CLASS (empathy_audio_src_parent_class)->handle_message (bin, + message); +} + +GstElement * +empathy_audio_src_new (void) +{ + static gboolean registered = FALSE; + + if (!registered) { + if (!gst_element_register (NULL, "empathyaudiosrc", + GST_RANK_NONE, EMPATHY_TYPE_GST_AUDIO_SRC)) + return NULL; + registered = TRUE; + } + return gst_element_factory_make ("empathyaudiosrc", NULL); +} + +void +empathy_audio_src_set_volume (EmpathyGstAudioSrc *src, gdouble volume) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); + GParamSpec *pspec; + GParamSpecDouble *pspec_double; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (priv->volume), + "volume"); + + g_assert (pspec != NULL); + + pspec_double = G_PARAM_SPEC_DOUBLE (pspec); + + volume = CLAMP (volume, pspec_double->minimum, pspec_double->maximum); + + g_object_set (G_OBJECT (priv->volume), "volume", volume, NULL); +} + +gdouble +empathy_audio_src_get_volume (EmpathyGstAudioSrc *src) +{ + EmpathyGstAudioSrcPrivate *priv = EMPATHY_GST_AUDIO_SRC_GET_PRIVATE (src); + gdouble volume; + + g_object_get (G_OBJECT (priv->volume), "volume", &volume, NULL); + + return volume; +} + + diff --git a/src/empathy-audio-src.h b/src/empathy-audio-src.h new file mode 100644 index 000000000..4bca31b61 --- /dev/null +++ b/src/empathy-audio-src.h @@ -0,0 +1,66 @@ +/* + * empathy-gst-video-src.h - Header for EmpathyGstAudioSrc + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EMPATHY_GST_AUDIO_SRC_H__ +#define __EMPATHY_GST_AUDIO_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _EmpathyGstAudioSrc EmpathyGstAudioSrc; +typedef struct _EmpathyGstAudioSrcClass EmpathyGstAudioSrcClass; + +struct _EmpathyGstAudioSrcClass { + GstBinClass parent_class; +}; + +struct _EmpathyGstAudioSrc { + GstBin parent; +}; + +GType empathy_audio_src_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_GST_AUDIO_SRC \ + (empathy_audio_src_get_type ()) +#define EMPATHY_GST_AUDIO_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_GST_AUDIO_SRC, \ + EmpathyGstAudioSrc)) +#define EMPATHY_GST_AUDIO_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_GST_AUDIO_SRC, \ + EmpathyGstAudioSrcClass)) +#define EMPATHY_IS_GST_AUDIO_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_GST_AUDIO_SRC)) +#define EMPATHY_IS_GST_AUDIO_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_GST_AUDIO_SRC)) +#define EMPATHY_GST_AUDIO_SRC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_GST_AUDIO_SRC, \ + EmpathyGstAudioSrcClass)) + +GstElement *empathy_audio_src_new (void); + +void empathy_audio_src_set_volume (EmpathyGstAudioSrc *src, gdouble volume); +gdouble empathy_audio_src_get_volume (EmpathyGstAudioSrc *src); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_GST_AUDIO_SRC_H__*/ diff --git a/src/empathy-streamed-media-window.c b/src/empathy-streamed-media-window.c index 189537f7c..9635c6de5 100644 --- a/src/empathy-streamed-media-window.c +++ b/src/empathy-streamed-media-window.c @@ -38,10 +38,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -53,6 +49,10 @@ #include "empathy-streamed-media-window.h" #include "empathy-streamed-media-window-fullscreen.h" #include "empathy-sidebar.h" +#include "empathy-video-widget.h" +#include "empathy-audio-src.h" +#include "empathy-audio-sink.h" +#include "empathy-video-src.h" #define BUTTON_ID "empathy-call-dtmf-button-id" diff --git a/src/empathy-video-src.c b/src/empathy-video-src.c new file mode 100644 index 000000000..5c865daaa --- /dev/null +++ b/src/empathy-video-src.c @@ -0,0 +1,360 @@ +/* + * empathy-gst-video-src.c - Source for EmpathyGstVideoSrc + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include + +#include "empathy-video-src.h" + +G_DEFINE_TYPE(EmpathyGstVideoSrc, empathy_video_src, GST_TYPE_BIN) + +/* Keep in sync with EmpathyGstVideoSrcChannel */ +static const gchar *channel_names[NR_EMPATHY_GST_VIDEO_SRC_CHANNELS] = { + "contrast", "brightness", "gamma" }; + +/* signal enum */ +#if 0 +enum +{ + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; +#endif + +/* private structure */ +typedef struct _EmpathyGstVideoSrcPrivate EmpathyGstVideoSrcPrivate; + +struct _EmpathyGstVideoSrcPrivate +{ + gboolean dispose_has_run; + GstElement *src; + /* Element implementing a ColorBalance interface */ + GstElement *balance; +}; + +#define EMPATHY_GST_VIDEO_SRC_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_VIDEO_SRC, \ + EmpathyGstVideoSrcPrivate)) +/** + * empathy_gst_add_to_bin - create a new gst element, add to bin and link it. + * @bin - bin to add the new element to. + * @src - src element for the new element (may be NULL). + * @name - name of the factory for the new element + * + * Returns: The newly created element ot %NULL on failure + */ +static GstElement * +empathy_gst_add_to_bin (GstBin *bin, + GstElement *src, + const gchar *factoryname) +{ + GstElement *ret; + + if ((ret = gst_element_factory_make (factoryname, NULL)) == NULL) + { + g_message ("Element factory \"%s\" not found.", factoryname); + goto error; + } + + if (!gst_bin_add (bin, ret)) + { + g_warning ("Couldn't add \"%s\" to bin.", factoryname); + goto error; + } + + /* do not link if src == NULL, just exit here */ + if (src == NULL) + return ret; + + if (!gst_element_link (src, ret)) + { + g_warning ("Failed to link \"%s\".", factoryname); + gst_bin_remove (bin, ret); + goto error; + } + + return ret; + +error: + if (ret != NULL) + gst_object_unref (ret); + return NULL; +} + + +static void +empathy_video_src_init (EmpathyGstVideoSrc *obj) +{ + EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (obj); + GstElement *element, *element_back; + GstPad *ghost, *src; + GstCaps *caps; + gchar *str; + + /* allocate caps here, so we can update it by optional elements */ + caps = gst_caps_new_simple ("video/x-raw-yuv", + "width", G_TYPE_INT, 320, + "height", G_TYPE_INT, 240, + NULL); + + /* allocate any data required by the object here */ + if ((element = empathy_gst_add_to_bin (GST_BIN (obj), + NULL, "gconfvideosrc")) == NULL) + g_error ("Couldn't add \"gconfvideosrc\" (gst-plugins-good missing?)"); + + /* we need to save our source to priv->src */ + priv->src = element; + + /* videomaxrate is optional as it's part of gst-plugins-bad. So don't + * fail if it doesn't exist. */ + element_back = element; + if ((element = empathy_gst_add_to_bin (GST_BIN (obj), + element, "videomaxrate")) == NULL) + { + g_message ("Couldn't add \"videomaxrate\" (gst-plugins-bad missing?)"); + element = element_back; + } + else + { + gst_caps_set_simple (caps, + "framerate", GST_TYPE_FRACTION, 15, 1, + NULL); + } + + str = gst_caps_to_string (caps); + g_debug ("Current video src caps are : %s", str); + g_free (str); + + if ((element = empathy_gst_add_to_bin (GST_BIN (obj), + element, "ffmpegcolorspace")) == NULL) + g_error ("Failed to add \"ffmpegcolorspace\" (gst-plugins-base missing?)"); + + if ((element = empathy_gst_add_to_bin (GST_BIN (obj), + element, "videoscale")) == NULL) + g_error ("Failed to add \"videoscale\", (gst-plugins-base missing?)"); + + if ((element = empathy_gst_add_to_bin (GST_BIN (obj), + element, "capsfilter")) == NULL) + g_error ( + "Failed to add \"capsfilter\" (gstreamer core elements missing?)"); + + g_object_set (G_OBJECT (element), "caps", caps, NULL); + + + /* optionally add postproc_tmpnoise to improve the performance of encoders */ + element_back = element; + if ((element = empathy_gst_add_to_bin (GST_BIN (obj), + element, "postproc_tmpnoise")) == NULL) + { + g_message ("Failed to add \"postproc_tmpnoise\" (gst-ffmpeg missing?)"); + element = element_back; + } + + src = gst_element_get_static_pad (element, "src"); + g_assert (src != NULL); + + ghost = gst_ghost_pad_new ("src", src); + if (ghost == NULL) + g_error ("Unable to create ghost pad for the videosrc"); + + if (!gst_element_add_pad (GST_ELEMENT (obj), ghost)) + g_error ("pad with the same name already existed or " + "the pad already had another parent."); + + gst_object_unref (G_OBJECT (src)); +} + +static void empathy_video_src_dispose (GObject *object); +static void empathy_video_src_finalize (GObject *object); + +static void +empathy_video_src_class_init (EmpathyGstVideoSrcClass *empathy_video_src_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (empathy_video_src_class); + + g_type_class_add_private (empathy_video_src_class, + sizeof (EmpathyGstVideoSrcPrivate)); + + object_class->dispose = empathy_video_src_dispose; + object_class->finalize = empathy_video_src_finalize; +} + +void +empathy_video_src_dispose (GObject *object) +{ + EmpathyGstVideoSrc *self = EMPATHY_GST_VIDEO_SRC (object); + EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + /* release any references held by the object here */ + + if (G_OBJECT_CLASS (empathy_video_src_parent_class)->dispose) + G_OBJECT_CLASS (empathy_video_src_parent_class)->dispose (object); +} + +void +empathy_video_src_finalize (GObject *object) +{ + //EmpathyGstVideoSrc *self = EMPATHY_GST_VIDEO_SRC (object); + //EmpathyGstVideoSrcPrivate *priv = EMPATHY_GST_VIDEO_SRC_GET_PRIVATE (self); + + /* free any data held directly by the object here */ + + G_OBJECT_CLASS (empathy_video_src_parent_class)->finalize (object); +} + +GstElement * +empathy_video_src_new (void) +{ + static gboolean registered = FALSE; + + if (!registered) { + if (!gst_element_register (NULL, "empathyvideosrc", + GST_RANK_NONE, EMPATHY_TYPE_GST_VIDEO_SRC)) + return NULL; + registered = TRUE; + } + return gst_element_factory_make ("empathyvideosrc", NULL); +} + +void +empathy_video_src_set_channel (GstElement *src, + EmpathyGstVideoSrcChannel channel, guint percent) +{ + GstElement *color; + GstColorBalance *balance; + const GList *channels; + GList *l; + + /* Find something supporting GstColorBalance */ + color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE); + + if (color == NULL) + return; + + balance = GST_COLOR_BALANCE (color); + + channels = gst_color_balance_list_channels (balance); + + for (l = (GList *) channels; l != NULL; l = g_list_next (l)) + { + GstColorBalanceChannel *c = GST_COLOR_BALANCE_CHANNEL (l->data); + + if (g_ascii_strcasecmp (c->label, channel_names[channel]) == 0) + { + gst_color_balance_set_value (balance, c, + ((c->max_value - c->min_value) * percent)/100 + + c->min_value); + break; + } + } + + g_object_unref (color); +} + +guint +empathy_video_src_get_channel (GstElement *src, + EmpathyGstVideoSrcChannel channel) +{ + GstElement *color; + GstColorBalance *balance; + const GList *channels; + GList *l; + guint percent = 0; + + /* Find something supporting GstColorBalance */ + color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE); + + if (color == NULL) + return percent; + + balance = GST_COLOR_BALANCE (color); + + channels = gst_color_balance_list_channels (balance); + + for (l = (GList *) channels; l != NULL; l = g_list_next (l)) + { + GstColorBalanceChannel *c = GST_COLOR_BALANCE_CHANNEL (l->data); + + if (g_ascii_strcasecmp (c->label, channel_names[channel]) == 0) + { + percent = + ((gst_color_balance_get_value (balance, c) + - c->min_value) * 100) / + (c->max_value - c->min_value); + + break; + } + } + + g_object_unref (color); + + return percent; +} + + +guint +empathy_video_src_get_supported_channels (GstElement *src) +{ + GstElement *color; + GstColorBalance *balance; + const GList *channels; + GList *l; + guint result = 0; + + /* Find something supporting GstColorBalance */ + color = gst_bin_get_by_interface (GST_BIN (src), GST_TYPE_COLOR_BALANCE); + + if (color == NULL) + goto out; + + balance = GST_COLOR_BALANCE (color); + + channels = gst_color_balance_list_channels (balance); + + for (l = (GList *) channels; l != NULL; l = g_list_next (l)) + { + GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (l->data); + int i; + + for (i = 0; i < NR_EMPATHY_GST_VIDEO_SRC_CHANNELS; i++) + { + if (g_ascii_strcasecmp (channel->label, channel_names[i]) == 0) + { + result |= (1 << i); + break; + } + } + } + + g_object_unref (color); + +out: + return result; +} + diff --git a/src/empathy-video-src.h b/src/empathy-video-src.h new file mode 100644 index 000000000..fae5563eb --- /dev/null +++ b/src/empathy-video-src.h @@ -0,0 +1,86 @@ +/* + * empathy-gst-video-src.h - Header for EmpathyGstVideoSrc + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EMPATHY_GST_VIDEO_SRC_H__ +#define __EMPATHY_GST_VIDEO_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _EmpathyGstVideoSrc EmpathyGstVideoSrc; +typedef struct _EmpathyGstVideoSrcClass EmpathyGstVideoSrcClass; + +typedef enum { + EMPATHY_GST_VIDEO_SRC_CHANNEL_CONTRAST = 0, + EMPATHY_GST_VIDEO_SRC_CHANNEL_BRIGHTNESS = 1, + EMPATHY_GST_VIDEO_SRC_CHANNEL_GAMMA = 2, + NR_EMPATHY_GST_VIDEO_SRC_CHANNELS +} EmpathyGstVideoSrcChannel; + +#define EMPATHY_GST_VIDEO_SRC_SUPPORTS_CONTRAST \ + (1 << EMPATHY_GST_VIDEO_SRC_CHANNEL_CONTRAST) +#define EMPATHY_GST_VIDEO_SRC_SUPPORTS_BRIGHTNESS \ + (1 << EMPATHY_GST_VIDEO_SRC_CHANNEL_BRIGHTNESS) +#define EMPATHY_GST_VIDEO_SRC_SUPPORTS_GAMMA \ + (1 << EMPATHY_GST_VIDEO_SRC_CHANNEL_GAMMA) + +struct _EmpathyGstVideoSrcClass { + GstBinClass parent_class; +}; + +struct _EmpathyGstVideoSrc { + GstBin parent; +}; + +GType empathy_video_src_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_GST_VIDEO_SRC \ + (empathy_video_src_get_type ()) +#define EMPATHY_GST_VIDEO_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_GST_VIDEO_SRC, \ + EmpathyGstVideoSrc)) +#define EMPATHY_GST_VIDEO_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_GST_VIDEO_SRC, \ + EmpathyGstVideoSrcClass)) +#define EMPATHY_IS_GST_VIDEO_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_GST_VIDEO_SRC)) +#define EMPATHY_IS_GST_VIDEO_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_GST_VIDEO_SRC)) +#define EMPATHY_GST_VIDEO_SRC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_GST_VIDEO_SRC, \ + EmpathyGstVideoSrcClass)) + +GstElement *empathy_video_src_new (void); + +guint +empathy_video_src_get_supported_channels (GstElement *src); + +void empathy_video_src_set_channel (GstElement *src, + EmpathyGstVideoSrcChannel channel, guint percent); + +guint empathy_video_src_get_channel (GstElement *src, + EmpathyGstVideoSrcChannel channel); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_GST_VIDEO_SRC_H__*/ diff --git a/src/empathy-video-widget.c b/src/empathy-video-widget.c new file mode 100644 index 000000000..a3b13fd12 --- /dev/null +++ b/src/empathy-video-widget.c @@ -0,0 +1,485 @@ +/* + * empathy-gst-gtk-widget.c - Source for EmpathyVideoWidget + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include + +#include +#include +#include + +#include "empathy-video-widget.h" + +G_DEFINE_TYPE(EmpathyVideoWidget, empathy_video_widget, + GTK_TYPE_DRAWING_AREA) + +static void empathy_video_widget_element_added_cb ( + FsElementAddedNotifier *notifier, GstBin *bin, GstElement *element, + EmpathyVideoWidget *self); + +static void empathy_video_widget_sync_message_cb ( + GstBus *bus, GstMessage *message, EmpathyVideoWidget *self); + +/* signal enum */ +#if 0 +enum +{ + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; +#endif + +enum { + PROP_GST_ELEMENT = 1, + PROP_GST_BUS, + PROP_MIN_WIDTH, + PROP_MIN_HEIGHT, + PROP_SYNC, + PROP_ASYNC, +}; + +/* private structure */ +typedef struct _EmpathyVideoWidgetPriv EmpathyVideoWidgetPriv; + +struct _EmpathyVideoWidgetPriv +{ + gboolean dispose_has_run; + GstBus *bus; + GstElement *videosink; + GstPad *sink_pad; + GstElement *overlay; + FsElementAddedNotifier *notifier; + gint min_width; + gint min_height; + gboolean sync; + gboolean async; + + GMutex *lock; +}; + +#define GET_PRIV(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + EMPATHY_TYPE_VIDEO_WIDGET, EmpathyVideoWidgetPriv)) + +static void +empathy_video_widget_init (EmpathyVideoWidget *obj) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (obj); + GdkColor black; + + priv->lock = g_mutex_new (); + + priv->notifier = fs_element_added_notifier_new (); + g_signal_connect (priv->notifier, "element-added", + G_CALLBACK (empathy_video_widget_element_added_cb), + obj); + + if (gdk_color_parse ("Black", &black)) + gtk_widget_modify_bg (GTK_WIDGET (obj), GTK_STATE_NORMAL, + &black); + + gtk_widget_set_double_buffered (GTK_WIDGET (obj), FALSE); +} + +static void +empathy_video_widget_realized (GtkWidget *widget, gpointer user_data) +{ + /* requesting the XID forces the GdkWindow to be native in GTK+ 2.18 + * onwards, requesting the native window in a thread causes a BadWindowID, + * so we need to request it now. We could call gdk_window_ensure_native(), + * but that would mean we require GTK+ 2.18, so instead we call this */ + GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (widget))); +} + +static void +empathy_video_widget_constructed (GObject *object) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (object); + GstElement *colorspace, *videoscale, *sink; + GstPad *pad; + + g_signal_connect (object, "realize", + G_CALLBACK (empathy_video_widget_realized), NULL); + + priv->videosink = gst_bin_new (NULL); + + gst_object_ref (priv->videosink); + gst_object_sink (priv->videosink); + + priv->sink_pad = gst_element_get_static_pad (priv->videosink, "sink"); + + sink = gst_element_factory_make ("gconfvideosink", NULL); + g_assert (sink != NULL); + + videoscale = gst_element_factory_make ("videoscale", NULL); + g_assert (videoscale != NULL); + + g_object_set (videoscale, "qos", FALSE, NULL); + + colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL); + g_assert (colorspace != NULL); + + g_object_set (colorspace, "qos", FALSE, NULL); + + gst_bin_add_many (GST_BIN (priv->videosink), colorspace, videoscale, + sink, NULL); + + if (!gst_element_link (colorspace, videoscale)) + g_error ("Failed to link ffmpegcolorspace and videoscale"); + + if (!gst_element_link (videoscale, sink)) + g_error ("Failed to link videoscale and gconfvideosink"); + + pad = gst_element_get_static_pad (colorspace, "sink"); + g_assert (pad != NULL); + + priv->sink_pad = gst_ghost_pad_new ("sink", pad); + if (!gst_element_add_pad (priv->videosink, priv->sink_pad)) + g_error ("Couldn't add sink ghostpad to the bin"); + + gst_object_unref (pad); + + fs_element_added_notifier_add (priv->notifier, GST_BIN (priv->videosink)); + gst_bus_enable_sync_message_emission (priv->bus); + + g_signal_connect (priv->bus, "sync-message", + G_CALLBACK (empathy_video_widget_sync_message_cb), object); + + gtk_widget_set_size_request (GTK_WIDGET (object), priv->min_width, + priv->min_height); +} + +static void empathy_video_widget_dispose (GObject *object); +static void empathy_video_widget_finalize (GObject *object); + +static gboolean empathy_video_widget_expose_event (GtkWidget *widget, + GdkEventExpose *event); +static void +empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self); + +static void +empathy_video_widget_set_property (GObject *object, + guint property_id, const GValue *value, GParamSpec *pspec) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_GST_BUS: + priv->bus = g_value_dup_object (value); + break; + case PROP_MIN_WIDTH: + priv->min_width = g_value_get_int (value); + break; + case PROP_MIN_HEIGHT: + priv->min_height = g_value_get_int (value); + break; + case PROP_SYNC: + priv->sync = g_value_get_boolean (value); + empathy_video_widget_element_set_sink_properties ( + EMPATHY_VIDEO_WIDGET (object)); + break; + case PROP_ASYNC: + priv->async = g_value_get_boolean (value); + empathy_video_widget_element_set_sink_properties ( + EMPATHY_VIDEO_WIDGET (object)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +empathy_video_widget_get_property (GObject *object, + guint property_id, GValue *value, GParamSpec *pspec) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (object); + + switch (property_id) + { + case PROP_GST_ELEMENT: + g_value_set_object (value, priv->videosink); + break; + case PROP_GST_BUS: + g_value_set_object (value, priv->bus); + break; + case PROP_MIN_WIDTH: + g_value_set_int (value, priv->min_width); + break; + case PROP_MIN_HEIGHT: + g_value_set_int (value, priv->min_height); + break; + case PROP_SYNC: + g_value_set_boolean (value, priv->sync); + break; + case PROP_ASYNC: + g_value_set_boolean (value, priv->async); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + + +static void +empathy_video_widget_class_init ( + EmpathyVideoWidgetClass *empathy_video_widget_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (empathy_video_widget_class); + GtkWidgetClass *widget_class = + GTK_WIDGET_CLASS (empathy_video_widget_class); + GParamSpec *param_spec; + + g_type_class_add_private (empathy_video_widget_class, + sizeof (EmpathyVideoWidgetPriv)); + + object_class->dispose = empathy_video_widget_dispose; + object_class->finalize = empathy_video_widget_finalize; + object_class->constructed = empathy_video_widget_constructed; + + object_class->set_property = empathy_video_widget_set_property; + object_class->get_property = empathy_video_widget_get_property; + + widget_class->expose_event = empathy_video_widget_expose_event; + + param_spec = g_param_spec_object ("gst-element", + "gst-element", "The underlaying gstreamer element", + GST_TYPE_ELEMENT, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_GST_ELEMENT, param_spec); + + param_spec = g_param_spec_object ("gst-bus", + "gst-bus", + "The toplevel bus from the pipeline in which this bin will be added", + GST_TYPE_BUS, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_GST_BUS, param_spec); + + param_spec = g_param_spec_int ("min-width", + "min-width", + "Minimal width of the widget", + 0, G_MAXINT, EMPATHY_VIDEO_WIDGET_DEFAULT_WIDTH, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_MIN_WIDTH, param_spec); + + param_spec = g_param_spec_int ("min-height", + "min-height", + "Minimal height of the widget", + 0, G_MAXINT, EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_MIN_HEIGHT, param_spec); + + param_spec = g_param_spec_boolean ("sync", + "sync", + "Whether the underlying sink should be sync or not", + TRUE, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SYNC, param_spec); + + param_spec = g_param_spec_boolean ("async", + "async", + "Whether the underlying sink should be async or not", + TRUE, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_ASYNC, param_spec); +} + +void +empathy_video_widget_dispose (GObject *object) +{ + EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object); + EmpathyVideoWidgetPriv *priv = GET_PRIV (self); + + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; + + g_signal_handlers_disconnect_by_func (priv->bus, + empathy_video_widget_sync_message_cb, object); + + if (priv->bus != NULL) + g_object_unref (priv->bus); + + priv->bus = NULL; + + if (priv->videosink != NULL) + g_object_unref (priv->videosink); + + priv->videosink = NULL; + + + /* release any references held by the object here */ + + if (G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose) + G_OBJECT_CLASS (empathy_video_widget_parent_class)->dispose (object); +} + +void +empathy_video_widget_finalize (GObject *object) +{ + EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (object); + EmpathyVideoWidgetPriv *priv = GET_PRIV (self); + + /* free any data held directly by the object here */ + g_mutex_free (priv->lock); + + G_OBJECT_CLASS (empathy_video_widget_parent_class)->finalize (object); +} + + +static void +empathy_video_widget_element_set_sink_properties_unlocked ( + EmpathyVideoWidget *self) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (self); + + if (priv->overlay == NULL) + return; + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay), + "force-aspect-ratio")) + g_object_set (G_OBJECT (priv->overlay), "force-aspect-ratio", TRUE, NULL); + + if (g_object_class_find_property ( + G_OBJECT_GET_CLASS (priv->overlay), "sync")) + g_object_set (G_OBJECT (priv->overlay), "sync", priv->sync, NULL); + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (priv->overlay), + "async")) + g_object_set (G_OBJECT (priv->overlay), "async", priv->async, NULL); +} + +static void +empathy_video_widget_element_set_sink_properties (EmpathyVideoWidget *self) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (self); + + g_mutex_lock (priv->lock); + empathy_video_widget_element_set_sink_properties_unlocked (self); + g_mutex_unlock (priv->lock); +} + +static void +empathy_video_widget_element_added_cb (FsElementAddedNotifier *notifier, + GstBin *bin, GstElement *element, EmpathyVideoWidget *self) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (self); + + /* We assume the overlay is the sink */ + g_mutex_lock (priv->lock); + if (priv->overlay == NULL && GST_IS_X_OVERLAY (element)) + { + priv->overlay = element; + g_object_add_weak_pointer (G_OBJECT (element), + (gpointer) &priv->overlay); + empathy_video_widget_element_set_sink_properties_unlocked (self); + gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay)); + } + g_mutex_unlock (priv->lock); +} + +static void +empathy_video_widget_sync_message_cb (GstBus *bus, GstMessage *message, + EmpathyVideoWidget *self) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (self); + const GstStructure *s; + + if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) + return; + + if (GST_MESSAGE_SRC (message) != (GstObject *) priv->overlay) + return; + + s = gst_message_get_structure (message); + + if (gst_structure_has_name (s, "prepare-xwindow-id")) + { + g_assert (gtk_widget_get_realized (GTK_WIDGET (self))); + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay), + GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (self)))); + } +} + +static gboolean +empathy_video_widget_expose_event (GtkWidget *widget, GdkEventExpose *event) +{ + EmpathyVideoWidget *self = EMPATHY_VIDEO_WIDGET (widget); + EmpathyVideoWidgetPriv *priv = GET_PRIV (self); + GtkAllocation allocation; + + if (event != NULL && event->count > 0) + return TRUE; + + if (priv->overlay == NULL) + { + gtk_widget_get_allocation (widget, &allocation); + gdk_window_clear_area (gtk_widget_get_window (widget), 0, 0, + allocation.width, allocation.height); + return TRUE; + } + + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (priv->overlay), + GDK_WINDOW_XID (gtk_widget_get_window (widget))); + + gst_x_overlay_expose (GST_X_OVERLAY (priv->overlay)); + + return TRUE; +} + +GtkWidget * +empathy_video_widget_new_with_size (GstBus *bus, gint width, gint height) +{ + g_return_val_if_fail (bus != NULL, NULL); + + return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET, + "gst-bus", bus, + "min-width", width, + "min-height", height, + NULL)); +} + +GtkWidget * +empathy_video_widget_new (GstBus *bus) +{ + g_return_val_if_fail (bus != NULL, NULL); + + return GTK_WIDGET (g_object_new (EMPATHY_TYPE_VIDEO_WIDGET, + "gst-bus", bus, + NULL)); +} + +GstPad * +empathy_video_widget_get_sink (EmpathyVideoWidget *widget) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (widget); + + return priv->sink_pad; +} + +GstElement * +empathy_video_widget_get_element (EmpathyVideoWidget *widget) +{ + EmpathyVideoWidgetPriv *priv = GET_PRIV (widget); + + return priv->videosink; +} diff --git a/src/empathy-video-widget.h b/src/empathy-video-widget.h new file mode 100644 index 000000000..cfdd0354c --- /dev/null +++ b/src/empathy-video-widget.h @@ -0,0 +1,72 @@ +/* + * empathy-gst-gtk-widget.h - Header for EmpathyVideoWidget + * Copyright (C) 2008 Collabora Ltd. + * @author Sjoerd Simons + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __EMPATHY_VIDEO_WIDGET_H__ +#define __EMPATHY_VIDEO_WIDGET_H__ + +#define EMPATHY_VIDEO_WIDGET_DEFAULT_WIDTH 320 +#define EMPATHY_VIDEO_WIDGET_DEFAULT_HEIGHT 240 + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _EmpathyVideoWidget EmpathyVideoWidget; +typedef struct _EmpathyVideoWidgetClass EmpathyVideoWidgetClass; + +struct _EmpathyVideoWidgetClass { + GtkDrawingAreaClass parent_class; +}; + +struct _EmpathyVideoWidget { + GtkDrawingArea parent; +}; + +GType empathy_video_widget_get_type (void); + +/* TYPE MACROS */ +#define EMPATHY_TYPE_VIDEO_WIDGET \ + (empathy_video_widget_get_type ()) +#define EMPATHY_VIDEO_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), EMPATHY_TYPE_VIDEO_WIDGET, \ + EmpathyVideoWidget)) +#define EMPATHY_VIDEO_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), EMPATHY_TYPE_VIDEO_WIDGET, \ + EmpathyVideoWidgetClass)) +#define EMPATHY_IS_VIDEO_WIDGET(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), EMPATHY_TYPE_VIDEO_WIDGET)) +#define EMPATHY_IS_VIDEO_WIDGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), EMPATHY_TYPE_VIDEO_WIDGET)) +#define EMPATHY_VIDEO_WIDGET_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), EMPATHY_TYPE_VIDEO_WIDGET, \ + EmpathyVideoWidgetClass)) + +GtkWidget *empathy_video_widget_new (GstBus *bus); +GtkWidget *empathy_video_widget_new_with_size (GstBus *bus, + gint width, gint height); + +GstElement *empathy_video_widget_get_element (EmpathyVideoWidget *widget); +GstPad *empathy_video_widget_get_sink (EmpathyVideoWidget *widget); + +G_END_DECLS + +#endif /* #ifndef __EMPATHY_VIDEO_WIDGET_H__*/ -- cgit v1.2.3