gst/playback/gstplaybin.c: On the fly visualisation switch, works disabling, enabling...
authorJulien Moutte <julien@moutte.net>
Thu, 26 Jan 2006 12:32:58 +0000 (12:32 +0000)
committerJulien Moutte <julien@moutte.net>
Thu, 26 Jan 2006 12:32:58 +0000 (12:32 +0000)
Original commit message from CVS:
2006-01-26  Julien MOUTTE  <julien@moutte.net>

* gst/playback/gstplaybin.c: (gst_play_bin_init),
(gst_play_bin_dispose), (gst_play_bin_vis_unblocked),
(gst_play_bin_vis_blocked), (gst_play_bin_set_property):
On the fly visualisation switch, works disabling, enabling as
well but it won't be able to enable vis in a playbin that was
created with no visualisation.

ChangeLog
gst/playback/gstplaybin.c

index ac4ed58..14261ce 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2006-01-26  Julien MOUTTE  <julien@moutte.net>
+
+       * gst/playback/gstplaybin.c: (gst_play_bin_init),
+       (gst_play_bin_dispose), (gst_play_bin_vis_unblocked),
+       (gst_play_bin_vis_blocked), (gst_play_bin_set_property): 
+       On the fly visualisation switch, works disabling, enabling as
+       well but it won't be able to enable vis in a playbin that was
+       created with no visualisation.
+
 2006-01-25  Wim Taymans  <wim@fluendo.com>
 
        * gst-libs/gst/audio/gstbaseaudiosink.c:
index 3bd6a49..87d6054 100644 (file)
@@ -65,6 +65,7 @@ struct _GstPlayBin
   GstElement *audio_sink;
   GstElement *video_sink;
   GstElement *visualisation;
+  GstElement *pending_visualisation;
   GstElement *volume_element;
   GstElement *textoverlay_element;
   gfloat volume;
@@ -220,6 +221,7 @@ gst_play_bin_init (GstPlayBin * play_bin)
   play_bin->video_sink = NULL;
   play_bin->audio_sink = NULL;
   play_bin->visualisation = NULL;
+  play_bin->pending_visualisation = NULL;
   play_bin->volume_element = NULL;
   play_bin->textoverlay_element = NULL;
   play_bin->volume = 1.0;
@@ -258,12 +260,126 @@ gst_play_bin_dispose (GObject * object)
     gst_object_unref (play_bin->visualisation);
     play_bin->visualisation = NULL;
   }
+  if (play_bin->pending_visualisation != NULL) {
+    gst_element_set_state (play_bin->pending_visualisation, GST_STATE_NULL);
+    gst_object_unref (play_bin->pending_visualisation);
+    play_bin->pending_visualisation = NULL;
+  }
   g_free (play_bin->font_desc);
   play_bin->font_desc = NULL;
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
+static void
+gst_play_bin_vis_unblocked (GstPad * tee_pad, gboolean blocked,
+    gpointer user_data)
+{
+  /* Unblocked */
+}
+
+static void
+gst_play_bin_vis_blocked (GstPad * tee_pad, gboolean blocked,
+    gpointer user_data)
+{
+  GstPlayBin *play_bin = GST_PLAY_BIN (user_data);
+  GstBin *vis_bin = NULL;
+  GstPad *vis_sink_pad = NULL, *vis_src_pad = NULL, *vqueue_pad = NULL;
+  GstState bin_state;
+
+  /* We want to disable visualisation */
+  if (!GST_IS_ELEMENT (play_bin->pending_visualisation)) {
+    /* Set visualisation element to READY */
+    gst_element_set_state (play_bin->visualisation, GST_STATE_READY);
+    goto beach;
+  }
+
+  vis_bin =
+      GST_BIN (gst_object_get_parent (GST_OBJECT (play_bin->visualisation)));
+
+  if (!GST_IS_BIN (vis_bin) || !GST_IS_PAD (tee_pad)) {
+    goto beach;
+  }
+
+  vis_src_pad = gst_element_get_pad (play_bin->visualisation, "src");
+  vis_sink_pad = gst_pad_get_peer (tee_pad);
+
+  /* Can be fakesink */
+  if (GST_IS_PAD (vis_src_pad)) {
+    vqueue_pad = gst_pad_get_peer (vis_src_pad);
+  }
+
+  if (!GST_IS_PAD (vis_sink_pad)) {
+    goto beach;
+  }
+
+  /* Check the bin's state */
+  GST_OBJECT_LOCK (vis_bin);
+  bin_state = GST_STATE (vis_bin);
+  GST_OBJECT_UNLOCK (vis_bin);
+
+  /* Unlink */
+  gst_pad_unlink (tee_pad, vis_sink_pad);
+  gst_object_unref (vis_sink_pad);
+  vis_sink_pad = NULL;
+
+  if (GST_IS_PAD (vqueue_pad)) {
+    gst_pad_unlink (vis_src_pad, vqueue_pad);
+    gst_object_unref (vis_src_pad);
+    vis_src_pad = NULL;
+  }
+
+  /* Remove from vis_bin */
+  gst_bin_remove (vis_bin, play_bin->visualisation);
+  /* Set state to NULL */
+  gst_element_set_state (play_bin->visualisation, GST_STATE_NULL);
+  /* And loose our ref */
+  gst_object_unref (play_bin->visualisation);
+
+  if (play_bin->pending_visualisation) {
+    /* Ref this new visualisation element before adding to the bin */
+    gst_object_ref (play_bin->pending_visualisation);
+    /* Add the new one */
+    gst_bin_add (vis_bin, play_bin->pending_visualisation);
+    /* Synchronizing state */
+    gst_element_set_state (play_bin->pending_visualisation, bin_state);
+
+    vis_sink_pad = gst_element_get_pad (play_bin->pending_visualisation,
+        "sink");
+    vis_src_pad = gst_element_get_pad (play_bin->pending_visualisation, "src");
+
+    if (!GST_IS_PAD (vis_sink_pad) || !GST_IS_PAD (vis_src_pad)) {
+      goto beach;
+    }
+
+    /* Link */
+    gst_pad_link (tee_pad, vis_sink_pad);
+    gst_pad_link (vis_src_pad, vqueue_pad);
+  }
+
+  /* We are done */
+  gst_object_unref (play_bin->visualisation);
+  play_bin->visualisation = play_bin->pending_visualisation;
+  play_bin->pending_visualisation = NULL;
+
+beach:
+  if (vis_sink_pad) {
+    gst_object_unref (vis_sink_pad);
+  }
+  if (vis_src_pad) {
+    gst_object_unref (vis_src_pad);
+  }
+  if (vqueue_pad) {
+    gst_object_unref (vqueue_pad);
+  }
+  if (vis_bin) {
+    gst_object_unref (vis_bin);
+  }
+
+  /* Unblock the pad */
+  gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_bin_vis_unblocked,
+      play_bin);
+}
 
 static void
 gst_play_bin_set_property (GObject * object, guint prop_id,
@@ -302,15 +418,70 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
       g_hash_table_remove (play_bin->cache, "abin");
       break;
     case ARG_VIS_PLUGIN:
-      if (play_bin->visualisation != NULL) {
-        gst_object_unref (play_bin->visualisation);
-      }
-      play_bin->visualisation = g_value_get_object (value);
-      if (play_bin->visualisation != NULL) {
-        gst_object_ref (play_bin->visualisation);
-        gst_object_sink (GST_OBJECT (play_bin->visualisation));
+    {
+      /* Do we already have a visualisation change pending ? */
+      if (play_bin->pending_visualisation) {
+        gst_object_unref (play_bin->pending_visualisation);
+        play_bin->pending_visualisation = g_value_get_object (value);
+        /* Take ownership */
+        if (play_bin->pending_visualisation) {
+          gst_object_ref (play_bin->pending_visualisation);
+          gst_object_sink (GST_OBJECT (play_bin->pending_visualisation));
+        }
+      } else {
+        play_bin->pending_visualisation = g_value_get_object (value);
+
+        /* Take ownership */
+        if (play_bin->pending_visualisation) {
+          gst_object_ref (play_bin->pending_visualisation);
+          gst_object_sink (GST_OBJECT (play_bin->pending_visualisation));
+        }
+
+        /* Was there a visualisation already set ? */
+        if (play_bin->visualisation != NULL) {
+          GstBin *vis_bin = NULL;
+
+          vis_bin =
+              GST_BIN (gst_object_get_parent (GST_OBJECT (play_bin->
+                      visualisation)));
+
+          /* Check if the visualisation is already in a bin */
+          if (GST_IS_BIN (vis_bin)) {
+            GstPad *vis_sink_pad = NULL, *tee_pad = NULL;
+
+            /* Now get tee pad and block it async */
+            vis_sink_pad = gst_element_get_pad (play_bin->visualisation,
+                "sink");
+            if (!GST_IS_PAD (vis_sink_pad)) {
+              goto beach;
+            }
+            tee_pad = gst_pad_get_peer (vis_sink_pad);
+            if (!GST_IS_PAD (tee_pad)) {
+              goto beach;
+            }
+
+            /* Block with callback */
+            gst_pad_set_blocked_async (tee_pad, TRUE, gst_play_bin_vis_blocked,
+                play_bin);
+          beach:
+            if (vis_sink_pad) {
+              gst_object_unref (vis_sink_pad);
+            }
+            if (tee_pad) {
+              gst_object_unref (tee_pad);
+            }
+            gst_object_unref (vis_bin);
+          } else {
+            play_bin->visualisation = play_bin->pending_visualisation;
+            play_bin->pending_visualisation = NULL;
+          }
+        } else {
+          play_bin->visualisation = play_bin->pending_visualisation;
+          play_bin->pending_visualisation = NULL;
+        }
       }
       break;
+    }
     case ARG_VOLUME:
       play_bin->volume = g_value_get_double (value);
       if (play_bin->volume_element) {