summaryrefslogtreecommitdiffstats
path: root/examples/seeking
diff options
context:
space:
mode:
Diffstat (limited to 'examples/seeking')
-rw-r--r--examples/seeking/Makefile.am2
-rw-r--r--examples/seeking/cdplayer.c3
-rw-r--r--examples/seeking/chained.c104
-rw-r--r--examples/seeking/playbin.c270
4 files changed, 376 insertions, 3 deletions
diff --git a/examples/seeking/Makefile.am b/examples/seeking/Makefile.am
index 3d99ee2e..582306ac 100644
--- a/examples/seeking/Makefile.am
+++ b/examples/seeking/Makefile.am
@@ -1,4 +1,4 @@
-examples = seek spider_seek cdplayer cdparanoia vorbisfile
+examples = seek spider_seek cdplayer cdparanoia vorbisfile playbin chained
noinst_PROGRAMS = $(examples)
diff --git a/examples/seeking/cdplayer.c b/examples/seeking/cdplayer.c
index afccaa84..73ab9cf8 100644
--- a/examples/seeking/cdplayer.c
+++ b/examples/seeking/cdplayer.c
@@ -131,9 +131,8 @@ update_scale (gpointer data)
GstElement *element = GST_ELEMENT (seekable_elements->data);
gst_element_query (element, GST_QUERY_TOTAL, &format, &duration);
+ gst_element_query (element, GST_QUERY_POSITION, &format, &position);
}
- if (clock)
- position = gst_clock_get_time (clock);
if (stats) {
if (clock)
diff --git a/examples/seeking/chained.c b/examples/seeking/chained.c
new file mode 100644
index 00000000..5bd0e12d
--- /dev/null
+++ b/examples/seeking/chained.c
@@ -0,0 +1,104 @@
+#include <stdlib.h>
+#include <gst/gst.h>
+#include <string.h>
+
+static GstElement *bin;
+
+static void
+unlinked (GstPad * pad, GstPad * peerpad, GstElement * pipeline)
+{
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ gst_bin_remove (GST_BIN (pipeline), bin);
+ gst_element_set_state (bin, GST_STATE_READY);
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+}
+
+static void
+new_pad (GstElement * elem, GstPad * newpad, GstElement * pipeline)
+{
+ GstScheduler *sched;
+ GstClock *clock;
+
+ g_print ("new pad %s\n", gst_pad_get_name (newpad));
+
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ gst_bin_add (GST_BIN (pipeline), bin);
+
+ sched = gst_element_get_scheduler (GST_ELEMENT (pipeline));
+ clock = gst_scheduler_get_clock (sched);
+ gst_scheduler_set_clock (sched, clock);
+
+ gst_pad_link (newpad, gst_element_get_pad (bin, "sink"));
+
+ g_signal_connect (G_OBJECT (newpad), "unlinked", G_CALLBACK (unlinked),
+ pipeline);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+}
+
+int
+main (int argc, char **argv)
+{
+ GstElement *pipeline;
+ GstElement *filesrc;
+ GstElement *oggdemux;
+ GstElement *vorbisdec;
+ GstElement *audioconvert;
+ GstElement *osssink;
+
+ gst_init (&argc, &argv);
+
+ if (argc < 2) {
+ g_print ("usage: %s <oggfile>\n", argv[0]);
+ return (-1);
+ }
+
+ pipeline = gst_pipeline_new ("pipeline");
+
+ filesrc = gst_element_factory_make ("filesrc", "filesrc");
+ g_assert (filesrc);
+ g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
+
+ oggdemux = gst_element_factory_make ("oggdemux", "oggdemux");
+ g_assert (oggdemux);
+
+ gst_bin_add (GST_BIN (pipeline), filesrc);
+ gst_bin_add (GST_BIN (pipeline), oggdemux);
+
+ gst_element_link_pads (filesrc, "src", oggdemux, "sink");
+
+ g_signal_connect (G_OBJECT (oggdemux), "new_pad", G_CALLBACK (new_pad),
+ pipeline);
+
+ bin = gst_bin_new ("bin");
+ vorbisdec = gst_element_factory_make ("vorbisdec", "vorbisdec");
+ g_assert (vorbisdec);
+ audioconvert = gst_element_factory_make ("audioconvert", "audioconvert");
+ g_assert (audioconvert);
+ osssink = gst_element_factory_make ("osssink", "osssink");
+ g_assert (osssink);
+ gst_bin_add (GST_BIN (bin), vorbisdec);
+ gst_bin_add (GST_BIN (bin), audioconvert);
+ gst_bin_add (GST_BIN (bin), osssink);
+
+ gst_element_link_pads (vorbisdec, "src", audioconvert, "sink");
+ gst_element_link_pads (audioconvert, "src", osssink, "sink");
+
+ gst_element_add_ghost_pad (bin, gst_element_get_pad (vorbisdec, "sink"),
+ "sink");
+
+ g_object_ref (G_OBJECT (bin));
+
+ g_signal_connect (pipeline, "deep_notify",
+ G_CALLBACK (gst_element_default_deep_notify), NULL);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+ while (gst_bin_iterate (GST_BIN (pipeline)))
+ /* nop */ ;
+
+ /* stop probe */
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ return 0;
+}
diff --git a/examples/seeking/playbin.c b/examples/seeking/playbin.c
new file mode 100644
index 00000000..b6ff35b8
--- /dev/null
+++ b/examples/seeking/playbin.c
@@ -0,0 +1,270 @@
+#include <stdlib.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gst/gst.h>
+#include <string.h>
+
+static GstElement *playbin = NULL;
+static GstElement *pipeline;
+static guint64 duration;
+static GtkAdjustment *adjustment;
+static GtkWidget *hscale;
+static gboolean verbose = FALSE;
+
+static guint update_id;
+
+#define UPDATE_INTERVAL 500
+
+static GstElement *
+make_playerbin_pipeline (const gchar * location)
+{
+ playbin = gst_element_factory_make ("playbin", "player");
+ g_assert (playbin);
+
+ g_object_set (G_OBJECT (playbin), "uri", location, NULL);
+
+ return playbin;
+}
+
+static gchar *
+format_value (GtkScale * scale, gdouble value)
+{
+ gint64 real;
+ gint64 seconds;
+ gint64 subseconds;
+
+ real = value * duration / 100;
+ seconds = (gint64) real / GST_SECOND;
+ subseconds = (gint64) real / (GST_SECOND / 100);
+
+ return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02"
+ G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100);
+}
+
+static gboolean
+update_scale (gpointer data)
+{
+ GstClock *clock;
+ guint64 position;
+ GstFormat format = GST_FORMAT_TIME;
+ gboolean res;
+
+ duration = 0;
+ clock = gst_bin_get_clock (GST_BIN (pipeline));
+
+ res = gst_element_query (playbin, GST_QUERY_TOTAL, &format, &duration);
+ if (!res)
+ duration = 0;
+ res = gst_element_query (playbin, GST_QUERY_POSITION, &format, &position);
+ if (!res)
+ position = 0;
+
+ if (position >= duration)
+ duration = position;
+
+ if (duration > 0) {
+ gtk_adjustment_set_value (adjustment, position * 100.0 / duration);
+ gtk_widget_queue_draw (hscale);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+iterate (gpointer data)
+{
+ gboolean res;
+
+ if (!GST_FLAG_IS_SET (GST_OBJECT (data), GST_BIN_SELF_SCHEDULABLE)) {
+ res = gst_bin_iterate (GST_BIN (data));
+ } else {
+ g_usleep (UPDATE_INTERVAL);
+ res = gst_element_get_state (GST_ELEMENT (data)) == GST_STATE_PLAYING;
+ }
+
+ if (!res) {
+ gtk_timeout_remove (update_id);
+ g_print ("stopping iterations\n");
+ }
+ return res;
+}
+
+static gboolean
+start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
+{
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ gtk_timeout_remove (update_id);
+
+ return FALSE;
+}
+
+static gboolean
+stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data)
+{
+ gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100;
+ gboolean res;
+ GstEvent *s_event;
+
+ g_print ("seek to %" G_GINT64_FORMAT " on element %s\n", real,
+ gst_element_get_name (playbin));
+ s_event =
+ gst_event_new_seek (GST_FORMAT_TIME | GST_SEEK_METHOD_SET |
+ GST_SEEK_FLAG_FLUSH, real);
+
+ res = gst_element_send_event (playbin, s_event);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ gtk_idle_add ((GtkFunction) iterate, pipeline);
+ update_id =
+ gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline);
+
+ return FALSE;
+}
+
+static void
+print_media_info (GstElement * playbin)
+{
+ GList *streaminfo;
+ GList *s;
+
+ g_print ("have media info now\n");
+
+ /* get info about the stream */
+ g_object_get (G_OBJECT (playbin), "stream-info", &streaminfo, NULL);
+
+ for (s = streaminfo; s; s = g_list_next (s)) {
+ GObject *obj = G_OBJECT (s->data);
+ gint type;
+ gboolean mute;
+
+ g_object_get (obj, "type", &type, NULL);
+ g_object_get (obj, "mute", &mute, NULL);
+
+ g_print ("%d %d\n", type, mute);
+ }
+}
+
+static void
+play_cb (GtkButton * button, gpointer data)
+{
+ if (gst_element_get_state (pipeline) != GST_STATE_PLAYING) {
+ GstElementStateReturn res;
+
+ res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ if (res == GST_STATE_SUCCESS) {
+ print_media_info (playbin);
+
+ res = gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ gtk_idle_add ((GtkFunction) iterate, pipeline);
+ update_id =
+ gtk_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale,
+ pipeline);
+ } else {
+ g_print ("failed playing\n");
+ }
+ }
+}
+
+static void
+pause_cb (GtkButton * button, gpointer data)
+{
+ if (gst_element_get_state (pipeline) != GST_STATE_PAUSED) {
+ gst_element_set_state (pipeline, GST_STATE_PAUSED);
+ gtk_timeout_remove (update_id);
+ }
+}
+
+static void
+stop_cb (GtkButton * button, gpointer data)
+{
+ if (gst_element_get_state (pipeline) != GST_STATE_READY) {
+ gst_element_set_state (pipeline, GST_STATE_READY);
+ gtk_adjustment_set_value (adjustment, 0.0);
+ gtk_timeout_remove (update_id);
+ }
+}
+
+static void
+print_usage (int argc, char **argv)
+{
+ g_print ("usage: %s <uri>\n", argv[0]);
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window, *hbox, *vbox, *play_button, *pause_button, *stop_button;
+ struct poptOption options[] = {
+ {"verbose", 'v', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &verbose, 0,
+ "Verbose properties", NULL},
+ POPT_TABLEEND
+ };
+
+ gst_init_with_popt_table (&argc, &argv, options);
+ gtk_init (&argc, &argv);
+
+ if (argc != 2) {
+ print_usage (argc, argv);
+ exit (-1);
+ }
+
+ pipeline = make_playerbin_pipeline (argv[1]);
+ g_assert (pipeline);
+
+ /* initialize gui elements ... */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ hbox = gtk_hbox_new (FALSE, 0);
+ vbox = gtk_vbox_new (FALSE, 0);
+ play_button = gtk_button_new_with_label ("play");
+ pause_button = gtk_button_new_with_label ("pause");
+ stop_button = gtk_button_new_with_label ("stop");
+
+ adjustment =
+ GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0));
+ hscale = gtk_hscale_new (adjustment);
+ gtk_scale_set_digits (GTK_SCALE (hscale), 2);
+ gtk_range_set_update_policy (GTK_RANGE (hscale), GTK_UPDATE_CONTINUOUS);
+
+ gtk_signal_connect (GTK_OBJECT (hscale),
+ "button_press_event", G_CALLBACK (start_seek), pipeline);
+ gtk_signal_connect (GTK_OBJECT (hscale),
+ "button_release_event", G_CALLBACK (stop_seek), pipeline);
+ gtk_signal_connect (GTK_OBJECT (hscale),
+ "format_value", G_CALLBACK (format_value), pipeline);
+
+ /* do the packing stuff ... */
+ gtk_window_set_default_size (GTK_WINDOW (window), 96, 96);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_container_add (GTK_CONTAINER (vbox), hbox);
+ gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2);
+ gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2);
+
+ /* connect things ... */
+ g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb),
+ pipeline);
+ g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb),
+ pipeline);
+ g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb),
+ pipeline);
+ g_signal_connect (G_OBJECT (window), "delete_event", gtk_main_quit, NULL);
+
+ /* show the gui. */
+ gtk_widget_show_all (window);
+
+ if (verbose) {
+ g_signal_connect (pipeline, "deep_notify",
+ G_CALLBACK (gst_element_default_deep_notify), NULL);
+ }
+ g_signal_connect (pipeline, "error", G_CALLBACK (gst_element_default_error),
+ NULL);
+
+ gtk_main ();
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ gst_object_unref (GST_OBJECT (pipeline));
+
+ return 0;
+}