gst/playback/gstplaybin2.c: Remove stream-info, we going for something easier.
authorWim Taymans <wim.taymans@gmail.com>
Fri, 1 Feb 2008 16:44:21 +0000 (16:44 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Fri, 1 Feb 2008 16:44:21 +0000 (16:44 +0000)
Original commit message from CVS:
* gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
(get_group), (get_n_pads), (gst_play_bin_get_property),
(pad_added_cb), (no_more_pads_cb), (perform_eos),
(autoplug_select_cb), (deactivate_group):
Remove stream-info, we going for something easier.
Refactor getting the current group.
Implement getting the number of audio/video/text streams.
* gst/playback/gststreamselector.c:
(gst_stream_selector_class_init), (gst_stream_selector_init),
(gst_stream_selector_get_property),
(gst_stream_selector_request_new_pad),
(gst_stream_selector_release_pad):
* gst/playback/gststreamselector.h:
Add property for number of pads.
* tests/examples/seek/seek.c: (set_scale), (update_flag),
(vis_toggle_cb), (audio_toggle_cb), (video_toggle_cb),
(text_toggle_cb), (update_streams), (msg_async_done),
(msg_state_changed), (main):
Block slider callback when updating the slider position.
Add gui elements for controlling playbin2.
Add callback for async_done that updates position/duration.

ChangeLog
gst/playback/gstplaybin2.c
gst/playback/gststreamselector.c
gst/playback/gststreamselector.h
tests/examples/seek/seek.c

index a36e7f8..f55edce 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2008-02-01  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       * gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
+       (get_group), (get_n_pads), (gst_play_bin_get_property),
+       (pad_added_cb), (no_more_pads_cb), (perform_eos),
+       (autoplug_select_cb), (deactivate_group):
+       Remove stream-info, we going for something easier.
+       Refactor getting the current group.
+       Implement getting the number of audio/video/text streams.
+
+       * gst/playback/gststreamselector.c:
+       (gst_stream_selector_class_init), (gst_stream_selector_init),
+       (gst_stream_selector_get_property),
+       (gst_stream_selector_request_new_pad),
+       (gst_stream_selector_release_pad):
+       * gst/playback/gststreamselector.h:
+       Add property for number of pads.
+
+       * tests/examples/seek/seek.c: (set_scale), (update_flag),
+       (vis_toggle_cb), (audio_toggle_cb), (video_toggle_cb),
+       (text_toggle_cb), (update_streams), (msg_async_done),
+       (msg_state_changed), (main):
+       Block slider callback when updating the slider position.
+       Add gui elements for controlling playbin2.
+       Add callback for async_done that updates position/duration.
+
 2008-02-01  Stefan Kost  <ensonic@users.sf.net>
 
        * docs/plugins/Makefile.am:
index 97987e5..edc8d4e 100644 (file)
@@ -336,7 +336,6 @@ struct _GstPlayBinClass
 /* props */
 #define DEFAULT_URI               NULL
 #define DEFAULT_SUBURI            NULL
-#define DEFAULT_STREAMINFO        NULL
 #define DEFAULT_SOURCE            NULL
 #define DEFAULT_FLAGS             GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \
                                  GST_PLAY_FLAG_SOFT_VOLUME
@@ -360,7 +359,6 @@ enum
   PROP_0,
   PROP_URI,
   PROP_SUBURI,
-  PROP_STREAMINFO,
   PROP_SOURCE,
   PROP_FLAGS,
   PROP_N_VIDEO,
@@ -476,12 +474,6 @@ gst_play_bin_class_init (GstPlayBinClass * klass)
       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
           NULL, G_PARAM_READWRITE));
 
-  g_object_class_install_property (gobject_klass, PROP_STREAMINFO,
-      g_param_spec_value_array ("stream-info",
-          "StreamInfo GValueArray", "value array of streaminfo",
-          g_param_spec_object ("streaminfo", "StreamInfo", "Streaminfo object",
-              GST_TYPE_STREAM_INFO, G_PARAM_READABLE), G_PARAM_READABLE));
-
   g_object_class_install_property (gobject_klass, PROP_SOURCE,
       g_param_spec_object ("source", "Source", "Source element",
           GST_TYPE_ELEMENT, G_PARAM_READABLE));
@@ -753,6 +745,32 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
   }
 }
 
+/* get the currently playing group or if nothing is playing, the next
+ * group. Must be called with the LOCK. */
+static GstSourceGroup *
+get_group (GstPlayBin * playbin)
+{
+  GstSourceGroup *result;
+
+  if (!(result = playbin->curr_group))
+    result = playbin->next_group;
+
+  return result;
+}
+
+static gint
+get_n_pads (GstSourceSelect * select)
+{
+  gint res;
+
+  if (select->selector == NULL)
+    return 0;
+
+  g_object_get (select->selector, "n-pads", &res, NULL);
+
+  return res;
+}
+
 static void
 gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
     GParamSpec * pspec)
@@ -763,36 +781,58 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
 
   switch (prop_id) {
     case PROP_URI:
+    {
+      GstSourceGroup *group;
+
       GST_OBJECT_LOCK (playbin);
-      /* get the currently playing group first, then the queued one, just in
-       * case we did not yet start playback. */
-      if (playbin->curr_group)
-        g_value_set_string (value, playbin->curr_group->uri);
-      else
-        g_value_set_string (value, playbin->next_group->uri);
+      group = get_group (playbin);
+      g_value_set_string (value, group->uri);
       GST_OBJECT_UNLOCK (playbin);
       break;
+    }
     case PROP_SUBURI:
+    {
+      GstSourceGroup *group;
+
       GST_OBJECT_LOCK (playbin);
-      /* get the currently playing group first, then the queued one */
-      if (playbin->curr_group)
-        g_value_set_string (value, playbin->curr_group->suburi);
-      else
-        g_value_set_string (value, playbin->next_group->suburi);
+      group = get_group (playbin);
+      g_value_set_string (value, group->suburi);
       GST_OBJECT_UNLOCK (playbin);
       break;
-    case PROP_STREAMINFO:
-      break;
+    }
     case PROP_SOURCE:
       break;
     case PROP_FLAGS:
       g_value_set_flags (value, gst_play_sink_get_flags (playbin->playsink));
       break;
     case PROP_N_VIDEO:
+    {
+      GstSourceGroup *group;
+      gint n_rawvideo, n_video;
+
+      GST_OBJECT_LOCK (playbin);
+      group = get_group (playbin);
+      n_rawvideo = get_n_pads (&group->selector[2]);
+      n_video = get_n_pads (&group->selector[3]);
+      g_value_set_int (value, n_rawvideo + n_video);
+      GST_OBJECT_UNLOCK (playbin);
       break;
+    }
     case PROP_CURRENT_VIDEO:
       break;
     case PROP_N_AUDIO:
+    {
+      GstSourceGroup *group;
+      gint n_rawaudio, n_audio;
+
+      GST_OBJECT_LOCK (playbin);
+      group = get_group (playbin);
+      n_rawaudio = get_n_pads (&group->selector[0]);
+      n_audio = get_n_pads (&group->selector[1]);
+      g_value_set_int (value, n_rawaudio + n_audio);
+      GST_OBJECT_UNLOCK (playbin);
+      break;
+    }
       break;
     case PROP_CURRENT_AUDIO:
       break;
@@ -878,7 +918,7 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
       GST_DEBUG_PAD_NAME (pad), caps, group);
 
   /* major type of the pad, this determines the selector to use */
-  for (i = 0; i < 3; i++) {
+  for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
     if (g_str_has_prefix (name, group->selector[i].media)) {
       select = &group->selector[i];
       break;
@@ -1011,7 +1051,7 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
 
   GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group);
 
-  for (i = 0; i < 3; i++) {
+  for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
     GstSourceSelect *select = &group->selector[i];
 
     if (select->selector) {
@@ -1035,7 +1075,7 @@ perform_eos (GstPlayBin * playbin, GstSourceGroup * group)
   GST_DEBUG_OBJECT (playbin, "doing EOS in group %p", group);
 
   event = gst_event_new_eos ();
-  for (i = 0; i < 3; i++) {
+  for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
     GstSourceSelect *select = &group->selector[i];
 
     if (select->selector) {
@@ -1231,7 +1271,7 @@ deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
 
   GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
 
-  for (i = 0; i < 3; i++) {
+  for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
     GstSourceSelect *select = &group->selector[i];
 
     if (!select->selector)
index 86ced9f..9681f01 100644 (file)
@@ -54,7 +54,10 @@ GST_STATIC_PAD_TEMPLATE ("src",
 
 enum
 {
-  PROP_ACTIVE_PAD = 1
+  PROP_0,
+  PROP_N_PADS,
+  PROP_ACTIVE_PAD,
+  PROP_LAST
 };
 
 static gboolean gst_stream_selector_is_active_sinkpad (GstStreamSelector * sel,
@@ -422,14 +425,20 @@ gst_stream_selector_class_init (GstStreamSelectorClass * klass)
   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class->dispose = gst_stream_selector_dispose;
   gobject_class->set_property =
       GST_DEBUG_FUNCPTR (gst_stream_selector_set_property);
   gobject_class->get_property =
       GST_DEBUG_FUNCPTR (gst_stream_selector_get_property);
+
+  g_object_class_install_property (gobject_class, PROP_N_PADS,
+      g_param_spec_int ("n-pads", "Number of Pads",
+          "The number of sink pads", 0, G_MAXINT, 0, G_PARAM_READABLE));
   g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD,
       g_param_spec_string ("active-pad", "Active pad",
           "Name of the currently" " active sink pad", NULL, G_PARAM_READWRITE));
-  gobject_class->dispose = gst_stream_selector_dispose;
+
   gstelement_class->request_new_pad = gst_stream_selector_request_new_pad;
   gstelement_class->release_pad = gst_stream_selector_release_pad;
 }
@@ -445,7 +454,8 @@ gst_stream_selector_init (GstStreamSelector * sel)
   gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad);
   /* sinkpad management */
   sel->active_sinkpad = NULL;
-  sel->nb_sinkpads = 0;
+  sel->padcount = 0;
+  sel->n_pads = 0;
   gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
 }
 
@@ -511,6 +521,11 @@ gst_stream_selector_get_property (GObject * object, guint prop_id,
   GstStreamSelector *sel = GST_STREAM_SELECTOR (object);
 
   switch (prop_id) {
+    case PROP_N_PADS:
+      GST_OBJECT_LOCK (object);
+      g_value_set_int (value, sel->n_pads);
+      GST_OBJECT_UNLOCK (object);
+      break;
     case PROP_ACTIVE_PAD:{
       GST_OBJECT_LOCK (object);
       if (sel->active_sinkpad != NULL) {
@@ -635,9 +650,10 @@ gst_stream_selector_request_new_pad (GstElement * element,
 
   sel = GST_STREAM_SELECTOR (element);
   g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL);
-  GST_LOG_OBJECT (sel, "Creating new pad %d", sel->nb_sinkpads);
+  GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount);
   GST_OBJECT_LOCK (sel);
-  name = g_strdup_printf ("sink%d", sel->nb_sinkpads++);
+  name = g_strdup_printf ("sink%d", sel->padcount++);
+  sel->n_pads++;
   sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD,
       "name", name, "direction", templ->direction, "template", templ, NULL);
   g_free (name);
@@ -673,6 +689,7 @@ gst_stream_selector_release_pad (GstElement * element, GstPad * pad)
     GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad));
     sel->active_sinkpad = NULL;
   }
+  sel->n_pads--;
   GST_OBJECT_UNLOCK (sel);
 
   gst_pad_set_active (pad, FALSE);
index a7c4b22..d64da77 100644 (file)
@@ -44,8 +44,10 @@ struct _GstStreamSelector {
 
   GstPad *srcpad;
 
+  guint padcount;
+
   GstPad *active_sinkpad;
-  guint nb_sinkpads;
+  guint n_pads;
 
   GstSegment segment;
 };
index fb6ddde..4c4b17c 100644 (file)
@@ -86,6 +86,9 @@ static guint update_id = 0;
 static guint seek_timeout_id = 0;
 static gulong changed_id;
 
+static GtkWidget *video_combo, *audio_combo, *text_combo;
+static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
+static GtkWidget *text_checkbox;
 
 /* pipeline construction */
 
@@ -1047,6 +1050,7 @@ static gboolean start_seek (GtkWidget * widget, GdkEventButton * event,
     gpointer user_data);
 static gboolean stop_seek (GtkWidget * widget, GdkEventButton * event,
     gpointer user_data);
+static void seek_cb (GtkWidget * widget);
 
 static void
 set_scale (gdouble value)
@@ -1055,11 +1059,14 @@ set_scale (gdouble value)
       (void *) pipeline);
   g_signal_handlers_block_by_func (hscale, (void *) stop_seek,
       (void *) pipeline);
+  g_signal_handlers_block_by_func (hscale, (void *) seek_cb, (void *) pipeline);
   gtk_adjustment_set_value (adjustment, value);
   g_signal_handlers_unblock_by_func (hscale, (void *) start_seek,
       (void *) pipeline);
   g_signal_handlers_unblock_by_func (hscale, (void *) stop_seek,
       (void *) pipeline);
+  g_signal_handlers_unblock_by_func (hscale, (void *) seek_cb,
+      (void *) pipeline);
   gtk_widget_queue_draw (hscale);
 }
 
@@ -1455,6 +1462,57 @@ rate_spinbutton_changed_cb (GtkSpinButton * button, GstPipeline * pipeline)
 }
 
 static void
+update_flag (GstPipeline * pipeline, gint num, gboolean state)
+{
+  gint flags;
+
+  g_object_get (pipeline, "flags", &flags, NULL);
+  if (state)
+    flags |= (1 << num);
+  else
+    flags &= ~(1 << num);
+  g_object_set (pipeline, "flags", flags, NULL);
+}
+
+static void
+vis_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
+{
+  update_flag (pipeline, 3, gtk_toggle_button_get_active (button));
+}
+
+static void
+audio_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
+{
+  update_flag (pipeline, 1, gtk_toggle_button_get_active (button));
+}
+
+static void
+video_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
+{
+  update_flag (pipeline, 0, gtk_toggle_button_get_active (button));
+}
+
+static void
+text_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline)
+{
+  update_flag (pipeline, 2, gtk_toggle_button_get_active (button));
+}
+
+static void
+update_streams (GstPipeline * pipeline)
+{
+  gint n_video, n_audio, n_text;
+
+  /* here we get and update the different streams detected by playbin2 */
+  g_object_get (pipeline, "n-video", &n_video, NULL);
+  g_object_get (pipeline, "n-audio", &n_audio, NULL);
+  g_object_get (pipeline, "n-text", &n_text, NULL);
+
+  g_print ("video %d, audio %d, text %d\n", n_video, n_audio, n_text);
+
+}
+
+static void
 message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
 {
   const GstStructure *s;
@@ -1475,6 +1533,18 @@ message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
 }
 
 static void
+msg_async_done (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
+{
+  GST_DEBUG ("async done");
+  /* when we get ASYNC_DONE we can query position, duration and other
+   * properties */
+  update_scale (pipeline);
+
+  /* update the available streams */
+  update_streams (pipeline);
+}
+
+static void
 msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
 {
   const GstStructure *s;
@@ -1487,7 +1557,7 @@ msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
 
     gst_message_parse_state_changed (message, &old, &new, &pending);
 
-    /* When state of the pipeline changes to playing we start updating scale */
+    /* When state of the pipeline changes to paused or playing we start updating scale */
     if (new == GST_STATE_PLAYING) {
       set_update_scale (TRUE);
     } else {
@@ -1542,7 +1612,7 @@ print_usage (int argc, char **argv)
 int
 main (int argc, char **argv)
 {
-  GtkWidget *window, *hbox, *vbox, *flagtable;
+  GtkWidget *window, *hbox, *vbox, *panel, *boxes, *flagtable;
   GtkWidget *play_button, *pause_button, *stop_button;
   GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox, *flush_checkbox;
   GtkWidget *scrub_checkbox, *play_scrub_checkbox, *rate_spinbutton;
@@ -1655,6 +1725,40 @@ main (int argc, char **argv)
   gtk_signal_connect (GTK_OBJECT (hscale),
       "format_value", G_CALLBACK (format_value), pipeline);
 
+  if (pipeline_type == 16) {
+    /* the playbin2 panel controls for the video/audio/subtitle tracks */
+    panel = gtk_hbox_new (FALSE, 0);
+    boxes = gtk_hbox_new (FALSE, 0);
+    video_combo = gtk_combo_box_new_text ();
+    audio_combo = gtk_combo_box_new_text ();
+    text_combo = gtk_combo_box_new_text ();
+    gtk_box_pack_start (GTK_BOX (panel), video_combo, TRUE, TRUE, 2);
+    gtk_box_pack_start (GTK_BOX (panel), audio_combo, TRUE, TRUE, 2);
+    gtk_box_pack_start (GTK_BOX (panel), text_combo, TRUE, TRUE, 2);
+    vis_checkbox = gtk_check_button_new_with_label ("Vis");
+    video_checkbox = gtk_check_button_new_with_label ("Video");
+    audio_checkbox = gtk_check_button_new_with_label ("Audio");
+    text_checkbox = gtk_check_button_new_with_label ("Text");
+    gtk_box_pack_start (GTK_BOX (boxes), vis_checkbox, TRUE, TRUE, 2);
+    gtk_box_pack_start (GTK_BOX (boxes), audio_checkbox, TRUE, TRUE, 2);
+    gtk_box_pack_start (GTK_BOX (boxes), video_checkbox, TRUE, TRUE, 2);
+    gtk_box_pack_start (GTK_BOX (boxes), text_checkbox, TRUE, TRUE, 2);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vis_checkbox), TRUE);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (audio_checkbox), TRUE);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (video_checkbox), TRUE);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_checkbox), TRUE);
+    g_signal_connect (G_OBJECT (vis_checkbox), "toggled",
+        G_CALLBACK (vis_toggle_cb), pipeline);
+    g_signal_connect (G_OBJECT (audio_checkbox), "toggled",
+        G_CALLBACK (audio_toggle_cb), pipeline);
+    g_signal_connect (G_OBJECT (video_checkbox), "toggled",
+        G_CALLBACK (video_toggle_cb), pipeline);
+    g_signal_connect (G_OBJECT (text_checkbox), "toggled",
+        G_CALLBACK (text_toggle_cb), pipeline);
+  } else {
+    panel = boxes = NULL;
+  }
+
   /* do the packing stuff ... */
   gtk_window_set_default_size (GTK_WINDOW (window), 250, 96);
   gtk_container_add (GTK_CONTAINER (window), vbox);
@@ -1674,6 +1778,10 @@ main (int argc, char **argv)
   gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_label, 3, 4, 0, 1);
   gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_spinbutton, 3, 4, 1,
       2);
+  if (panel && boxes) {
+    gtk_box_pack_start (GTK_BOX (vbox), panel, TRUE, TRUE, 2);
+    gtk_box_pack_start (GTK_BOX (vbox), boxes, TRUE, TRUE, 2);
+  }
   gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2);
 
   /* connect things ... */
@@ -1717,6 +1825,8 @@ main (int argc, char **argv)
         (GCallback) msg_state_changed, pipeline);
     g_signal_connect (bus, "message::segment-done",
         (GCallback) msg_segment_done, pipeline);
+    g_signal_connect (bus, "message::async-done",
+        (GCallback) msg_async_done, pipeline);
 
     g_signal_connect (bus, "message::new-clock", (GCallback) message_received,
         pipeline);