tests/examples/seek/: Embedd the xwindow.

Original commit message from CVS:
* tests/examples/seek/Makefile.am:
* tests/examples/seek/seek.c:
Embedd the xwindow.
This commit is contained in:
Stefan Kost 2008-06-24 16:05:06 +00:00
parent 4b5e729246
commit 7922f23bbf
3 changed files with 167 additions and 28 deletions

View file

@ -1,3 +1,9 @@
2008-06-24 Stefan Kost <ensonic@users.sf.net>
* tests/examples/seek/Makefile.am:
* tests/examples/seek/seek.c:
Embedd the xwindow.
2008-06-24 Jan Schmidt <jan.schmidt@sun.com>
* sys/ximage/ximagesink.c (gst_ximagesink_ximage_put),

View file

@ -6,5 +6,7 @@ examples = $(GTK_EXAMPLES)
noinst_PROGRAMS = $(examples)
LIBS = $(GST_LIBS) $(GTK_LIBS)
AM_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS)
LDADD = $(GST_LIBS) $(GTK_LIBS) \
$(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \
$(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la
AM_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -I$(top_builddir)/gst-libs

View file

@ -26,6 +26,11 @@
#include <gst/gst.h>
#include <string.h>
#include <X11/Xlib.h>
#include <gdk/gdkx.h>
#include <gst/interfaces/xoverlay.h>
#include <gst/video/gstvideosink.h>
GST_DEBUG_CATEGORY_STATIC (seek_debug);
#define GST_CAT_DEFAULT (seek_debug)
@ -54,6 +59,8 @@ GST_DEBUG_CATEGORY_STATIC (seek_debug);
/* timeout for gst_element_get_state() after a seek */
#define SEEK_TIMEOUT 40 * GST_MSECOND
#define DEFAULT_VIDEO_HEIGHT 300
static GList *seekable_pads = NULL;
static GList *rate_pads = NULL;
@ -94,6 +101,10 @@ static gboolean need_streams = TRUE;
static GtkWidget *video_combo, *audio_combo, *text_combo, *vis_combo;
static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton;
static GtkWidget *video_window;
static guint embed_xid = 0;
GList *paths = NULL, *l = NULL;
/* we keep an array of the visualisation entries so that we can easily switch
* with the combo box index. */
@ -863,15 +874,30 @@ make_mpegnt_pipeline (const gchar * location)
return pipeline;
}
static void
playerbin_set_uri (GstElement * player, const gchar * location)
{
gchar *uri;
/* Add "file://" prefix for convenience */
if (g_str_has_prefix (location, "/")) {
uri = g_strconcat ("file://", location, NULL);
g_object_set (G_OBJECT (player), "uri", uri, NULL);
g_free (uri);
} else {
g_object_set (G_OBJECT (player), "uri", location, NULL);
}
}
static GstElement *
make_playerbin_pipeline (const gchar * location)
construct_playerbin (const gchar * name, const gchar * location)
{
GstElement *player;
player = gst_element_factory_make ("playbin", "player");
player = gst_element_factory_make (name, "player");
g_assert (player);
g_object_set (G_OBJECT (player), "uri", location, NULL);
playerbin_set_uri (player, location);
seekable_elements = g_list_prepend (seekable_elements, player);
@ -881,22 +907,16 @@ make_playerbin_pipeline (const gchar * location)
return player;
}
static GstElement *
make_playerbin_pipeline (const gchar * location)
{
return construct_playerbin ("playbin", location);
}
static GstElement *
make_playerbin2_pipeline (const gchar * location)
{
GstElement *player;
player = gst_element_factory_make ("playbin2", "player");
g_assert (player);
g_object_set (G_OBJECT (player), "uri", location, NULL);
seekable_elements = g_list_prepend (seekable_elements, player);
/* force element seeking on this pipeline */
elem_seek = TRUE;
return player;
return construct_playerbin ("playbin2", location);
}
#ifndef GST_DISABLE_PARSE
@ -2071,11 +2091,54 @@ msg_buffering (GstBus * bus, GstMessage * message, GstPipeline * data)
}
}
static GstBusSyncReply
bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * data)
{
if ((GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) &&
gst_structure_has_name (message->structure, "prepare-xwindow-id")) {
GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (message));
g_print ("got prepare-xwindow-id\n");
if (!embed_xid) {
embed_xid = GDK_WINDOW_XID (GDK_WINDOW (video_window->window));
}
if (g_object_class_find_property (G_OBJECT_GET_CLASS (element),
"force-aspect-ratio")) {
g_object_set (element, "force-aspect-ratio", TRUE, NULL);
}
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
embed_xid);
}
return GST_BUS_PASS;
}
static void
msg_eos (GstBus * bus, GstMessage * message, GstPipeline * data)
{
message_received (bus, message, data);
/* Set new uri for playerbins and continue playback */
if (l && (pipeline_type == 14 || pipeline_type == 16)) {
stop_cb (NULL, NULL);
l = g_list_next (l);
if (l) {
playerbin_set_uri (GST_ELEMENT (data), l->data);
play_cb (NULL, NULL);
}
}
}
static void
connect_bus_signals (GstElement * pipeline)
{
GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
/* handle prepare-xwindow-id element message synchronously */
gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler,
pipeline);
gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
g_signal_connect (bus, "message::state-changed",
@ -2091,8 +2154,7 @@ connect_bus_signals (GstElement * pipeline)
pipeline);
g_signal_connect (bus, "message::warning", (GCallback) message_received,
pipeline);
g_signal_connect (bus, "message::eos", (GCallback) message_received,
pipeline);
g_signal_connect (bus, "message::eos", (GCallback) msg_eos, pipeline);
g_signal_connect (bus, "message::tag", (GCallback) message_received,
pipeline);
g_signal_connect (bus, "message::element", (GCallback) message_received,
@ -2105,6 +2167,47 @@ connect_bus_signals (GstElement * pipeline)
gst_object_unref (bus);
}
/* Return GList of paths described in location string */
static GList *
handle_wildcards (const gchar * location)
{
GList *res = NULL;
gchar *path = g_path_get_dirname (location);
gchar *pattern = g_path_get_basename (location);
GPatternSpec *pspec = g_pattern_spec_new (pattern);
GDir *dir = g_dir_open (path, 0, NULL);
const gchar *name;
g_print ("matching %s from %s\n", pattern, path);
if (!dir) {
g_print ("opening directory %s failed\n", path);
goto out;
}
while ((name = g_dir_read_name (dir)) != NULL) {
if (g_pattern_match_string (pspec, name)) {
res = g_list_append (res, g_strjoin ("/", path, name, NULL));
g_print (" found clip %s\n", name);
}
}
g_dir_close (dir);
out:
g_pattern_spec_free (pspec);
g_free (pattern);
g_free (path);
return res;
}
static void
delete_event_cb (void)
{
stop_cb (NULL, NULL);
gtk_main_quit ();
}
static void
print_usage (int argc, char **argv)
{
@ -2142,6 +2245,11 @@ main (int argc, char **argv)
if (!g_thread_supported ())
g_thread_init (NULL);
if (!XInitThreads ()) {
g_print ("XInitThreads failed\n");
exit (-1);
}
ctx = g_option_context_new ("- test seeking in gsteamer");
g_option_context_add_main_entries (ctx, options, NULL);
g_option_context_add_group (ctx, gst_init_get_option_group ());
@ -2169,12 +2277,28 @@ main (int argc, char **argv)
pipeline_spec = argv[2];
pipeline = pipelines[pipeline_type].func (pipeline_spec);
if (g_strrstr (pipeline_spec, "*") != NULL ||
g_strrstr (pipeline_spec, "?") != NULL) {
paths = handle_wildcards (pipeline_spec);
} else {
paths = g_list_prepend (paths, g_strdup (pipeline_spec));
}
if (!paths) {
g_print ("opening %s failed\n", pipeline_spec);
exit (-1);
}
l = paths;
pipeline = pipelines[pipeline_type].func ((gchar *) l->data);
g_assert (pipeline);
/* initialize gui elements ... */
tips = gtk_tooltips_new ();
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
video_window = gtk_drawing_area_new ();
gtk_widget_set_double_buffered (video_window, FALSE);
statusbar = gtk_statusbar_new ();
status_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "seek");
gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stopped");
@ -2310,8 +2434,12 @@ main (int argc, char **argv)
/* do the packing stuff ... */
gtk_window_set_default_size (GTK_WINDOW (window), 250, 96);
/* FIXME: can we avoid this for audio only? */
gtk_widget_set_size_request (GTK_WIDGET (video_window), -1,
DEFAULT_VIDEO_HEIGHT);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_container_add (GTK_CONTAINER (vbox), hbox);
gtk_box_pack_start (GTK_BOX (vbox), video_window, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2);
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);
@ -2328,12 +2456,12 @@ main (int argc, char **argv)
gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_spinbutton, 3, 4, 1,
2);
if (panel && boxes && boxes2) {
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), boxes2, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (vbox), panel, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), boxes, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), boxes2, FALSE, FALSE, 2);
}
gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (vbox), statusbar, TRUE, TRUE, 2);
gtk_box_pack_start (GTK_BOX (vbox), hscale, FALSE, FALSE, 2);
gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 2);
/* connect things ... */
g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb),
@ -2357,7 +2485,7 @@ main (int argc, char **argv)
g_signal_connect (G_OBJECT (rate_spinbutton), "value_changed",
G_CALLBACK (rate_spinbutton_changed_cb), pipeline);
g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
g_signal_connect (G_OBJECT (window), "delete-event", delete_event_cb, NULL);
/* show the gui. */
gtk_widget_show_all (window);
@ -2376,5 +2504,8 @@ main (int argc, char **argv)
g_print ("free pipeline\n");
gst_object_unref (pipeline);
g_list_foreach (paths, (GFunc) g_free, NULL);
g_list_free (paths);
return 0;
}