ges-source: Move common elements handling to the base class
authorSimon Corsin <simoncorsin@gmail.com>
Thu, 27 Jun 2013 12:20:00 +0000 (14:20 +0200)
committerThibault Saunier <thibault.saunier@collabora.com>
Tue, 3 Sep 2013 23:44:31 +0000 (19:44 -0400)
  + And port all the subclasses

ges/ges-audio-test-source.c
ges/ges-image-source.c
ges/ges-source.c
ges/ges-source.h
ges/ges-title-source.c
ges/ges-uri-source.c
ges/ges-uri-source.h
ges/ges-video-test-source.c

index 4d0f9dd..82b443c 100644 (file)
@@ -51,21 +51,20 @@ static void ges_audio_test_source_get_property (GObject * object, guint
 static void ges_audio_test_source_set_property (GObject * object, guint
     property_id, const GValue * value, GParamSpec * pspec);
 
-static GstElement *ges_audio_test_source_create_element (GESTrackElement *
-    self);
+static GstElement *ges_audio_test_source_create_source (GESTrackElement * self);
 
 static void
 ges_audio_test_source_class_init (GESAudioTestSourceClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GESTrackElementClass *bg_class = GES_TRACK_ELEMENT_CLASS (klass);
+  GESSourceClass *source_class = GES_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GESAudioTestSourcePrivate));
 
   object_class->get_property = ges_audio_test_source_get_property;
   object_class->set_property = ges_audio_test_source_set_property;
 
-  bg_class->create_element = ges_audio_test_source_create_element;
+  source_class->create_source = ges_audio_test_source_create_source;
 }
 
 static void
@@ -99,7 +98,7 @@ ges_audio_test_source_set_property (GObject * object,
 }
 
 static GstElement *
-ges_audio_test_source_create_element (GESTrackElement * trksrc)
+ges_audio_test_source_create_source (GESTrackElement * trksrc)
 {
   GESAudioTestSource *self;
   GstElement *ret;
index cdc2852..f2089f3 100644 (file)
@@ -110,7 +110,7 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GstElement * scale)
 }
 
 static GstElement *
-ges_image_source_create_element (GESTrackElement * track_element)
+ges_image_source_create_source (GESTrackElement * track_element)
 {
   GstElement *bin, *source, *scale, *freeze, *iconv;
   GstPad *src, *target;
@@ -150,7 +150,7 @@ static void
 ges_image_source_class_init (GESImageSourceClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GESTrackElementClass *gesobj_class = GES_TRACK_ELEMENT_CLASS (klass);
+  GESSourceClass *source_class = GES_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GESImageSourcePrivate));
 
@@ -166,7 +166,7 @@ ges_image_source_class_init (GESImageSourceClass * klass)
   g_object_class_install_property (object_class, PROP_URI,
       g_param_spec_string ("uri", "URI", "uri of the resource",
           NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-  gesobj_class->create_element = ges_image_source_create_element;
+  source_class->create_source = ges_image_source_create_source;
 }
 
 static void
index 1cbb4d8..f1373e9 100644 (file)
  * @short_description: Base Class for single-media sources
  */
 
-#include "ges-internal.h"
+#include "ges/ges-meta-container.h"
 #include "ges-track-element.h"
 #include "ges-source.h"
+#include "ges-layer.h"
+#include "gstframepositionner.h"
 
 G_DEFINE_TYPE (GESSource, ges_source, GES_TYPE_TRACK_ELEMENT);
 
 struct _GESSourcePrivate
 {
   /*  Dummy variable */
-  void *nothing;
+  GstFramePositionner *positionner;
 };
 
 static void
+_pad_added_cb (GstElement * element, GstPad * srcpad, GstPad * sinkpad)
+{
+  gst_element_no_more_pads (element);
+  gst_pad_link (srcpad, sinkpad);
+}
+
+static void
+_ghost_pad_added_cb (GstElement * element, GstPad * srcpad, GstElement * bin)
+{
+  GstPad *ghost;
+
+  ghost = gst_ghost_pad_new ("src", srcpad);
+  gst_pad_set_active (ghost, TRUE);
+  gst_element_add_pad (bin, ghost);
+  gst_element_no_more_pads (element);
+}
+
+static GstElement *
+_create_bin (const gchar * bin_name, GstElement * sub_element, ...)
+{
+  va_list argp;
+
+  GstElement *element;
+  GstElement *prev = NULL;
+  GstElement *first = NULL;
+  GstElement *bin;
+  GstPad *sub_srcpad;
+
+  va_start (argp, sub_element);
+  bin = gst_bin_new (bin_name);
+  gst_bin_add (GST_BIN (bin), sub_element);
+
+  while ((element = va_arg (argp, GstElement *)) != NULL) {
+    gst_bin_add (GST_BIN (bin), element);
+    if (prev)
+      gst_element_link (prev, element);
+    prev = element;
+    if (first == NULL)
+      first = element;
+  }
+
+  va_end (argp);
+
+  sub_srcpad = gst_element_get_static_pad (sub_element, "src");
+
+  if (prev != NULL) {
+    GstPad *srcpad, *sinkpad, *ghost;
+
+    srcpad = gst_element_get_static_pad (prev, "src");
+    ghost = gst_ghost_pad_new ("src", srcpad);
+    gst_pad_set_active (ghost, TRUE);
+    gst_element_add_pad (bin, ghost);
+
+    sinkpad = gst_element_get_static_pad (first, "sink");
+    if (sub_srcpad)
+      gst_pad_link (sub_srcpad, sinkpad);
+    else
+      g_signal_connect (sub_element, "pad-added", G_CALLBACK (_pad_added_cb),
+          sinkpad);
+
+    gst_object_unref (srcpad);
+    gst_object_unref (sinkpad);
+
+  } else if (sub_srcpad) {
+    GstPad *ghost;
+
+    ghost = gst_ghost_pad_new ("src", sub_srcpad);
+    gst_pad_set_active (ghost, TRUE);
+    gst_element_add_pad (bin, ghost);
+  } else {
+    g_signal_connect (sub_element, "pad-added",
+        G_CALLBACK (_ghost_pad_added_cb), bin);
+  }
+
+  return bin;
+}
+
+static void
+_sync_element_to_layer_property_float (GESTrackElement * trksrc,
+    GstElement * element, const gchar * meta, const gchar * propname)
+{
+  GESTimelineElement *parent;
+  GESLayer *layer;
+  gfloat value;
+
+  parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc));
+  layer = ges_clip_get_layer (GES_CLIP (parent));
+
+  gst_object_unref (parent);
+
+  if (layer != NULL) {
+
+    ges_meta_container_get_float (GES_META_CONTAINER (layer), meta, &value);
+    g_object_set (element, propname, value, NULL);
+    GST_DEBUG_OBJECT (trksrc, "Setting %s to %f", propname, value);
+
+  } else {
+
+    GST_DEBUG_OBJECT (trksrc, "NOT setting the %s", propname);
+  }
+
+  gst_object_unref (layer);
+}
+
+static void
+update_z_order_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED,
+    GESSource * self)
+{
+  GESLayer *layer = ges_clip_get_layer (clip);
+
+  if (layer == NULL)
+    return;
+
+  /* 10000 is the max value of zorder on videomixerpad, hardcoded */
+
+  g_object_set (self->priv->positionner, "zorder",
+      10000 - ges_layer_get_priority (layer), NULL);
+
+  gst_object_unref (layer);
+}
+
+static GstElement *
+ges_source_create_element (GESTrackElement * trksrc)
+{
+  GstElement *topbin;
+  GstElement *sub_element;
+  GESSourceClass *source_class = GES_SOURCE_GET_CLASS (trksrc);
+  GESTrack *track;
+  GESSource *self;
+
+  if (!source_class->create_source)
+    return NULL;
+
+  sub_element = source_class->create_source (trksrc);
+
+  track = ges_track_element_get_track (trksrc);
+
+  self = (GESSource *) trksrc;
+
+  switch (track->type) {
+    case GES_TRACK_TYPE_AUDIO:
+    {
+      const gchar *props[] = { "volume", "mute", NULL };
+      GstElement *volume;
+
+      GST_DEBUG_OBJECT (trksrc, "Creating a bin sub_element ! volume");
+
+      volume = gst_element_factory_make ("volume", NULL);
+
+      topbin = _create_bin ("audio-src-bin", sub_element, volume, NULL);
+
+      _sync_element_to_layer_property_float (trksrc, volume, GES_META_VOLUME,
+          "volume");
+      ges_track_element_add_children_props (trksrc, volume, NULL, NULL, props);
+      break;
+    }
+    case GES_TRACK_TYPE_VIDEO:
+    {
+      GstElement *positionner;
+      const gchar *props[] = { "alpha", "posx", "posy", NULL };
+      GESTimelineElement *parent;
+
+      /* That positionner will add metadata to buffers according to its
+         properties, acting like a proxy for our smart-mixer dynamic pads. */
+      positionner =
+          gst_element_factory_make ("framepositionner", "frame_tagger");
+
+      ges_track_element_add_children_props (trksrc, positionner, NULL, NULL,
+          props);
+      topbin = _create_bin ("video-src-bin", sub_element, positionner, NULL);
+      parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc));
+      if (parent) {
+        self->priv->positionner = GST_FRAME_POSITIONNER (positionner);
+        g_signal_connect (parent, "notify::layer",
+            (GCallback) update_z_order_cb, trksrc);
+        update_z_order_cb (GES_CLIP (parent), NULL, self);
+        gst_object_unref (parent);
+      } else {
+        GST_WARNING ("No parent timeline element, SHOULD NOT HAPPEN");
+      }
+      break;
+    }
+    default:
+      topbin = _create_bin ("a-questionable-name", sub_element, NULL);
+      break;
+  }
+
+  return topbin;
+}
+
+static void
 ges_source_class_init (GESSourceClass * klass)
 {
   GESTrackElementClass *track_class = GES_TRACK_ELEMENT_CLASS (klass);
+  GESSourceClass *source_class = GES_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GESSourcePrivate));
 
   track_class->gnlobject_factorytype = "gnlsource";
-  track_class->create_element = NULL;
+  track_class->create_element = ges_source_create_element;
+  source_class->create_source = NULL;
 }
 
 static void
@@ -51,4 +246,5 @@ ges_source_init (GESSource * self)
 {
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
       GES_TYPE_SOURCE, GESSourcePrivate);
+  self->priv->positionner = NULL;
 }
index 9ab8022..73339c2 100644 (file)
@@ -65,6 +65,7 @@ struct _GESSource {
 
 /**
  * GESSourceClass:
+ * @create_source: method to return the GstElement to put in the source topbin.
  */
 
 struct _GESSourceClass {
@@ -73,6 +74,7 @@ struct _GESSourceClass {
 
   /*< private >*/
   /* Padding for API extension */
+  GstElement*  (*create_source)           (GESTrackElement * object);
   gpointer _ges_reserved[GES_PADDING];
 };
 
index 13b5ee5..1fd8ac8 100644 (file)
@@ -58,13 +58,13 @@ static void ges_title_source_get_property (GObject * object, guint
 static void ges_title_source_set_property (GObject * object, guint
     property_id, const GValue * value, GParamSpec * pspec);
 
-static GstElement *ges_title_source_create_element (GESTrackElement * self);
+static GstElement *ges_title_source_create_source (GESTrackElement * self);
 
 static void
 ges_title_source_class_init (GESTitleSourceClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GESTrackElementClass *bg_class = GES_TRACK_ELEMENT_CLASS (klass);
+  GESSourceClass *source_class = GES_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GESTitleSourcePrivate));
 
@@ -72,7 +72,7 @@ ges_title_source_class_init (GESTitleSourceClass * klass)
   object_class->set_property = ges_title_source_set_property;
   object_class->dispose = ges_title_source_dispose;
 
-  bg_class->create_element = ges_title_source_create_element;
+  source_class->create_source = ges_title_source_create_source;
 }
 
 static void
@@ -139,7 +139,7 @@ ges_title_source_set_property (GObject * object,
 }
 
 static GstElement *
-ges_title_source_create_element (GESTrackElement * object)
+ges_title_source_create_source (GESTrackElement * object)
 {
   GESTitleSource *self = GES_TITLE_SOURCE (object);
   GESTitleSourcePrivate *priv = self->priv;
index a339681..671b7d8 100644 (file)
 #include "ges-uri-source.h"
 #include "ges-uri-asset.h"
 #include "ges-extractable.h"
-#include "ges-layer.h"
-#include "gstframepositionner.h"
 
 struct _GESUriSourcePrivate
 {
-  GstFramePositionner *positionner;
+  void *nothing;
 };
 
 enum
@@ -46,190 +44,24 @@ enum
   PROP_URI
 };
 
-/* Callbacks */
-
-static void
-_pad_added_cb (GstElement * element, GstPad * srcpad, GstPad * sinkpad)
-{
-  gst_element_no_more_pads (element);
-  gst_pad_link (srcpad, sinkpad);
-}
-
-static void
-_ghost_pad_added_cb (GstElement * element, GstPad * srcpad, GstElement * bin)
-{
-  GstPad *ghost;
-
-  ghost = gst_ghost_pad_new ("src", srcpad);
-  gst_pad_set_active (ghost, TRUE);
-  gst_element_add_pad (bin, ghost);
-  gst_element_no_more_pads (element);
-}
-
-/* Internal methods */
-
+/* GESSource VMethod */
 static GstElement *
-_create_bin (const gchar * bin_name, GstElement * decodebin, ...)
-{
-  va_list argp;
-
-  GstElement *element;
-  GstElement *prev = NULL;
-  GstElement *first = NULL;
-  GstElement *bin;
-
-  va_start (argp, decodebin);
-  bin = gst_bin_new (bin_name);
-  gst_bin_add (GST_BIN (bin), decodebin);
-
-  while ((element = va_arg (argp, GstElement *)) != NULL) {
-    gst_bin_add (GST_BIN (bin), element);
-    if (prev)
-      gst_element_link (prev, element);
-    prev = element;
-    if (first == NULL)
-      first = element;
-  }
-
-  va_end (argp);
-
-  if (prev != NULL) {
-    GstPad *srcpad, *sinkpad, *ghost;
-
-    srcpad = gst_element_get_static_pad (prev, "src");
-    ghost = gst_ghost_pad_new ("src", srcpad);
-    gst_pad_set_active (ghost, TRUE);
-    gst_element_add_pad (bin, ghost);
-
-    sinkpad = gst_element_get_static_pad (first, "sink");
-    g_signal_connect (decodebin, "pad-added", G_CALLBACK (_pad_added_cb),
-        sinkpad);
-
-    gst_object_unref (srcpad);
-    gst_object_unref (sinkpad);
-
-  } else {
-    /* Our decodebin is alone in the bin, we need to ghost its source when it appears */
-
-    g_signal_connect (decodebin, "pad-added", G_CALLBACK (_ghost_pad_added_cb),
-        bin);
-  }
-
-  return bin;
-}
-
-static void
-_sync_element_to_layer_property_float (GESTrackElement * trksrc,
-    GstElement * element, const gchar * meta, const gchar * propname)
-{
-  GESTimelineElement *parent;
-  GESLayer *layer;
-  gfloat value;
-
-  parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc));
-  layer = ges_clip_get_layer (GES_CLIP (parent));
-
-  gst_object_unref (parent);
-
-  if (layer != NULL) {
-
-    ges_meta_container_get_float (GES_META_CONTAINER (layer), meta, &value);
-    g_object_set (element, propname, value, NULL);
-    GST_DEBUG_OBJECT (trksrc, "Setting %s to %f", propname, value);
-
-  } else {
-
-    GST_DEBUG_OBJECT (trksrc, "NOT setting the %s", propname);
-  }
-
-  gst_object_unref (layer);
-}
-
-/* TrackElement VMethods */
-
-static void
-update_z_order_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED,
-    GESUriSource * self)
-{
-  GESLayer *layer = ges_clip_get_layer (clip);
-
-  if (layer == NULL)
-    return;
-
-  /* 10000 is the max value of zorder on videomixerpad, hardcoded */
-
-  g_object_set (self->priv->positionner, "zorder",
-      10000 - ges_layer_get_priority (layer), NULL);
-
-  gst_object_unref (layer);
-}
-
-static GstElement *
-ges_uri_source_create_element (GESTrackElement * trksrc)
+ges_uri_source_create_source (GESTrackElement * trksrc)
 {
   GESUriSource *self;
   GESTrack *track;
   GstElement *decodebin;
-  GstElement *topbin, *volume;
-  GstElement *positionner;
-  GESTimelineElement *parent;
 
   self = (GESUriSource *) trksrc;
-  track = ges_track_element_get_track (trksrc);
-
-  switch (track->type) {
-    case GES_TRACK_TYPE_AUDIO:
-    {
-      const gchar *props[] = { "volume", "mute", NULL };
-
-      GST_DEBUG_OBJECT (trksrc, "Creating a bin uridecodebin ! volume");
-
-      decodebin = gst_element_factory_make ("uridecodebin", NULL);
-      volume = gst_element_factory_make ("volume", NULL);
 
-      topbin = _create_bin ("audio-src-bin", decodebin, volume, NULL);
+  track = ges_track_element_get_track (trksrc);
 
-      _sync_element_to_layer_property_float (trksrc, volume, GES_META_VOLUME,
-          "volume");
-      ges_track_element_add_children_props (trksrc, volume, NULL, NULL, props);
-      break;
-    }
-    case GES_TRACK_TYPE_VIDEO:
-    {
-      const gchar *props[] = { "alpha", "posx", "posy", NULL };
-
-      decodebin = gst_element_factory_make ("uridecodebin", NULL);
-
-      /* That positionner will add metadata to buffers according to its
-         properties, acting like a proxy for our smart-mixer dynamic pads. */
-      positionner =
-          gst_element_factory_make ("framepositionner", "frame_tagger");
-
-      ges_track_element_add_children_props (trksrc, positionner, NULL, NULL,
-          props);
-      topbin = _create_bin ("video-src-bin", decodebin, positionner, NULL);
-      parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc));
-      if (parent) {
-        self->priv->positionner = GST_FRAME_POSITIONNER (positionner);
-        g_signal_connect (parent, "notify::layer",
-            (GCallback) update_z_order_cb, trksrc);
-        update_z_order_cb (GES_CLIP (parent), NULL, self);
-        gst_object_unref (parent);
-      } else {
-        GST_WARNING ("No parent timeline element, SHOULD NOT HAPPEN");
-      }
-      break;
-    }
-    default:
-      decodebin = gst_element_factory_make ("uridecodebin", NULL);
-      topbin = _create_bin ("video-src-bin", decodebin, NULL);
-      break;
-  }
+  decodebin = gst_element_factory_make ("uridecodebin", NULL);
 
   g_object_set (decodebin, "caps", ges_track_get_caps (track),
       "expose-all-streams", FALSE, "uri", self->uri, NULL);
 
-  return topbin;
+  return decodebin;
 }
 
 /* Extractable interface implementation */
@@ -319,7 +151,7 @@ static void
 ges_track_filesource_class_init (GESUriSourceClass * klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GESTrackElementClass *track_class = GES_TRACK_ELEMENT_CLASS (klass);
+  GESSourceClass *source_class = GES_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GESUriSourcePrivate));
 
@@ -336,7 +168,7 @@ ges_track_filesource_class_init (GESUriSourceClass * klass)
       g_param_spec_string ("uri", "URI", "uri of the resource",
           NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
-  track_class->create_element = ges_uri_source_create_element;
+  source_class->create_source = ges_uri_source_create_source;
 }
 
 static void
@@ -344,7 +176,6 @@ ges_track_filesource_init (GESUriSource * self)
 {
   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
       GES_TYPE_URI_SOURCE, GESUriSourcePrivate);
-  self->priv->positionner = NULL;
 }
 
 /**
index b2c1143..1401684 100644 (file)
@@ -24,7 +24,6 @@
 #include <glib-object.h>
 #include <ges/ges-types.h>
 #include <ges/ges-source.h>
-#include <ges/ges-meta-container.h>
 
 G_BEGIN_DECLS
 
index f71eca8..4a4dbe1 100644 (file)
@@ -36,17 +36,16 @@ struct _GESVideoTestSourcePrivate
   GESVideoTestPattern pattern;
 };
 
-static GstElement *ges_video_test_source_create_element (GESTrackElement *
-    self);
+static GstElement *ges_video_test_source_create_source (GESTrackElement * self);
 
 static void
 ges_video_test_source_class_init (GESVideoTestSourceClass * klass)
 {
-  GESTrackElementClass *track_element_class = GES_TRACK_ELEMENT_CLASS (klass);
+  GESSourceClass *source_class = GES_SOURCE_CLASS (klass);
 
   g_type_class_add_private (klass, sizeof (GESVideoTestSourcePrivate));
 
-  track_element_class->create_element = ges_video_test_source_create_element;
+  source_class->create_source = ges_video_test_source_create_source;
 }
 
 static void
@@ -59,7 +58,7 @@ ges_video_test_source_init (GESVideoTestSource * self)
 }
 
 static GstElement *
-ges_video_test_source_create_element (GESTrackElement * self)
+ges_video_test_source_create_source (GESTrackElement * self)
 {
   gint pattern;
   GstElement *ret;