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:
parent
4b5e729246
commit
7922f23bbf
@ -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>
|
2008-06-24 Jan Schmidt <jan.schmidt@sun.com>
|
||||||
|
|
||||||
* sys/ximage/ximagesink.c (gst_ximagesink_ximage_put),
|
* sys/ximage/ximagesink.c (gst_ximagesink_ximage_put),
|
||||||
|
@ -6,5 +6,7 @@ examples = $(GTK_EXAMPLES)
|
|||||||
|
|
||||||
noinst_PROGRAMS = $(examples)
|
noinst_PROGRAMS = $(examples)
|
||||||
|
|
||||||
LIBS = $(GST_LIBS) $(GTK_LIBS)
|
LDADD = $(GST_LIBS) $(GTK_LIBS) \
|
||||||
AM_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS)
|
$(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
|
||||||
|
@ -26,6 +26,11 @@
|
|||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <string.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);
|
GST_DEBUG_CATEGORY_STATIC (seek_debug);
|
||||||
#define GST_CAT_DEFAULT (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 */
|
/* timeout for gst_element_get_state() after a seek */
|
||||||
#define SEEK_TIMEOUT 40 * GST_MSECOND
|
#define SEEK_TIMEOUT 40 * GST_MSECOND
|
||||||
|
|
||||||
|
#define DEFAULT_VIDEO_HEIGHT 300
|
||||||
|
|
||||||
|
|
||||||
static GList *seekable_pads = NULL;
|
static GList *seekable_pads = NULL;
|
||||||
static GList *rate_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 *video_combo, *audio_combo, *text_combo, *vis_combo;
|
||||||
static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
|
static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox;
|
||||||
static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton;
|
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
|
/* we keep an array of the visualisation entries so that we can easily switch
|
||||||
* with the combo box index. */
|
* with the combo box index. */
|
||||||
@ -863,15 +874,30 @@ make_mpegnt_pipeline (const gchar * location)
|
|||||||
return pipeline;
|
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 *
|
static GstElement *
|
||||||
make_playerbin_pipeline (const gchar * location)
|
construct_playerbin (const gchar * name, const gchar * location)
|
||||||
{
|
{
|
||||||
GstElement *player;
|
GstElement *player;
|
||||||
|
|
||||||
player = gst_element_factory_make ("playbin", "player");
|
player = gst_element_factory_make (name, "player");
|
||||||
g_assert (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);
|
seekable_elements = g_list_prepend (seekable_elements, player);
|
||||||
|
|
||||||
@ -881,22 +907,16 @@ make_playerbin_pipeline (const gchar * location)
|
|||||||
return player;
|
return player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstElement *
|
||||||
|
make_playerbin_pipeline (const gchar * location)
|
||||||
|
{
|
||||||
|
return construct_playerbin ("playbin", location);
|
||||||
|
}
|
||||||
|
|
||||||
static GstElement *
|
static GstElement *
|
||||||
make_playerbin2_pipeline (const gchar * location)
|
make_playerbin2_pipeline (const gchar * location)
|
||||||
{
|
{
|
||||||
GstElement *player;
|
return construct_playerbin ("playbin2", location);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef GST_DISABLE_PARSE
|
#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
|
static void
|
||||||
connect_bus_signals (GstElement * pipeline)
|
connect_bus_signals (GstElement * pipeline)
|
||||||
{
|
{
|
||||||
GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (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);
|
gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
|
||||||
|
|
||||||
g_signal_connect (bus, "message::state-changed",
|
g_signal_connect (bus, "message::state-changed",
|
||||||
@ -2091,8 +2154,7 @@ connect_bus_signals (GstElement * pipeline)
|
|||||||
pipeline);
|
pipeline);
|
||||||
g_signal_connect (bus, "message::warning", (GCallback) message_received,
|
g_signal_connect (bus, "message::warning", (GCallback) message_received,
|
||||||
pipeline);
|
pipeline);
|
||||||
g_signal_connect (bus, "message::eos", (GCallback) message_received,
|
g_signal_connect (bus, "message::eos", (GCallback) msg_eos, pipeline);
|
||||||
pipeline);
|
|
||||||
g_signal_connect (bus, "message::tag", (GCallback) message_received,
|
g_signal_connect (bus, "message::tag", (GCallback) message_received,
|
||||||
pipeline);
|
pipeline);
|
||||||
g_signal_connect (bus, "message::element", (GCallback) message_received,
|
g_signal_connect (bus, "message::element", (GCallback) message_received,
|
||||||
@ -2105,6 +2167,47 @@ connect_bus_signals (GstElement * pipeline)
|
|||||||
gst_object_unref (bus);
|
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
|
static void
|
||||||
print_usage (int argc, char **argv)
|
print_usage (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -2142,6 +2245,11 @@ main (int argc, char **argv)
|
|||||||
if (!g_thread_supported ())
|
if (!g_thread_supported ())
|
||||||
g_thread_init (NULL);
|
g_thread_init (NULL);
|
||||||
|
|
||||||
|
if (!XInitThreads ()) {
|
||||||
|
g_print ("XInitThreads failed\n");
|
||||||
|
exit (-1);
|
||||||
|
}
|
||||||
|
|
||||||
ctx = g_option_context_new ("- test seeking in gsteamer");
|
ctx = g_option_context_new ("- test seeking in gsteamer");
|
||||||
g_option_context_add_main_entries (ctx, options, NULL);
|
g_option_context_add_main_entries (ctx, options, NULL);
|
||||||
g_option_context_add_group (ctx, gst_init_get_option_group ());
|
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_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);
|
g_assert (pipeline);
|
||||||
|
|
||||||
/* initialize gui elements ... */
|
/* initialize gui elements ... */
|
||||||
tips = gtk_tooltips_new ();
|
tips = gtk_tooltips_new ();
|
||||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
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 ();
|
statusbar = gtk_statusbar_new ();
|
||||||
status_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "seek");
|
status_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "seek");
|
||||||
gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stopped");
|
gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stopped");
|
||||||
@ -2310,8 +2434,12 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
/* do the packing stuff ... */
|
/* do the packing stuff ... */
|
||||||
gtk_window_set_default_size (GTK_WINDOW (window), 250, 96);
|
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 (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), play_button, FALSE, FALSE, 2);
|
||||||
gtk_box_pack_start (GTK_BOX (hbox), pause_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 (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,
|
gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_spinbutton, 3, 4, 1,
|
||||||
2);
|
2);
|
||||||
if (panel && boxes && boxes2) {
|
if (panel && boxes && boxes2) {
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), panel, TRUE, TRUE, 2);
|
gtk_box_pack_start (GTK_BOX (vbox), panel, FALSE, FALSE, 2);
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), boxes, TRUE, TRUE, 2);
|
gtk_box_pack_start (GTK_BOX (vbox), boxes, FALSE, FALSE, 2);
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), boxes2, TRUE, TRUE, 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), hscale, FALSE, FALSE, 2);
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), statusbar, TRUE, TRUE, 2);
|
gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 2);
|
||||||
|
|
||||||
/* connect things ... */
|
/* connect things ... */
|
||||||
g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb),
|
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_signal_connect (G_OBJECT (rate_spinbutton), "value_changed",
|
||||||
G_CALLBACK (rate_spinbutton_changed_cb), pipeline);
|
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. */
|
/* show the gui. */
|
||||||
gtk_widget_show_all (window);
|
gtk_widget_show_all (window);
|
||||||
@ -2376,5 +2504,8 @@ main (int argc, char **argv)
|
|||||||
g_print ("free pipeline\n");
|
g_print ("free pipeline\n");
|
||||||
gst_object_unref (pipeline);
|
gst_object_unref (pipeline);
|
||||||
|
|
||||||
|
g_list_foreach (paths, (GFunc) g_free, NULL);
|
||||||
|
g_list_free (paths);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user