From d64c7edb66f4a64ff49c4306cf77fd269b7079ab Mon Sep 17 00:00:00 2001 From: Jussi Kukkonen Date: Mon, 16 Mar 2015 13:45:30 +0200 Subject: [PATCH] Add error signal emission for missing plugins Add a missing plugins error signal to gst-player. Note that this error does not necessarily mean the playback has completely failed, but in practice the user experience will be bad (think, e.g. of a mp4 file where H.264 codec is missing: AAC playback still works...). Use the signal in gtk-play to show a infobar if plugins are missing. Submitted upstream at https://github.com/sdroege/gst-player/pull/11 Upstream-Status: Submitted Signed-off-by: Jussi Kukkonen --- configure.ac | 2 +- gtk/gtk-play.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- lib/gst/player/gstplayer.c | 22 +++++++++++++++++++ lib/gst/player/gstplayer.h | 3 ++- 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 90ab74c..6cdb4eb 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,7 @@ AC_SUBST(LT_AGE) PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES(GLIB, [glib-2.0 gobject-2.0]) -PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0 >= 1.4 gstreamer-video-1.0 >= 1.4]) +PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0 >= 1.4 gstreamer-video-1.0 >= 1.4 gstreamer-pbutils-1.0]) GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" AC_SUBST(GLIB_PREFIX) diff --git a/gtk/gtk-play.c b/gtk/gtk-play.c index b92773b..e2b605a 100644 --- a/gtk/gtk-play.c +++ b/gtk/gtk-play.c @@ -30,6 +30,8 @@ typedef struct GtkWidget *prev_button, *next_button; GtkWidget *seekbar; GtkWidget *video_area; + GtkWidget *info_label; + GtkWidget *info_bar; GtkWidget *volume_button; gulong seekbar_value_changed_signal_id; gboolean playing; @@ -141,6 +143,13 @@ play_pause_clicked_cb (GtkButton * button, GtkPlay * play) } static void +clear_missing_plugins (GtkPlay * play) +{ + gtk_label_set_text (GTK_LABEL (play->info_label), ""); + gtk_widget_hide (play->info_bar); +} + +static void skip_prev_clicked_cb (GtkButton * button, GtkPlay * play) { GList *prev; @@ -155,6 +164,7 @@ skip_prev_clicked_cb (GtkButton * button, GtkPlay * play) gtk_widget_set_sensitive (play->next_button, TRUE); gst_player_set_uri (play->player, prev->data); + clear_missing_plugins (play); gst_player_play (play->player); set_title (play, prev->data); gtk_widget_set_sensitive (play->prev_button, g_list_previous (prev) != NULL); @@ -175,6 +185,7 @@ skip_next_clicked_cb (GtkButton * button, GtkPlay * play) gtk_widget_set_sensitive (play->prev_button, TRUE); gst_player_set_uri (play->player, next->data); + clear_missing_plugins (play); gst_player_play (play->player); set_title (play, next->data); gtk_widget_set_sensitive (play->next_button, g_list_next (next) != NULL); @@ -193,10 +204,16 @@ volume_changed_cb (GtkScaleButton * button, gdouble value, GtkPlay * play) gst_player_set_volume (play->player, value); } +void +info_bar_response_cb (GtkInfoBar * bar, gint response, GtkPlay * play) +{ + gtk_widget_hide (GTK_WIDGET (bar)); +} + static void create_ui (GtkPlay * play) { - GtkWidget *controls, *main_hbox, *main_vbox; + GtkWidget *controls, *main_hbox, *main_vbox, *info_bar, *content_area; play->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (play->window), "delete-event", @@ -208,6 +225,20 @@ create_ui (GtkPlay * play) g_signal_connect (play->video_area, "realize", G_CALLBACK (video_area_realize_cb), play); + play->info_bar = gtk_info_bar_new (); + gtk_info_bar_set_message_type (GTK_INFO_BAR (play->info_bar), + GTK_MESSAGE_WARNING); + //gtk_info_bar_set_show_close_button (GTK_INFO_BAR (play->info_bar), + // TRUE); + gtk_widget_set_no_show_all (play->info_bar, TRUE); + g_signal_connect (play->info_bar, "response", + G_CALLBACK (info_bar_response_cb), play); + + content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (play->info_bar)); + play->info_label = gtk_label_new (""); + gtk_container_add (GTK_CONTAINER (content_area), play->info_label); + gtk_widget_show (play->info_label); + /* Unified play/pause button */ play->play_pause_button = gtk_button_new_from_icon_name ("media-playback-pause", @@ -258,6 +289,7 @@ create_ui (GtkPlay * play) main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), play->info_bar, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (main_vbox), controls, FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (play->window), main_vbox); @@ -322,6 +354,7 @@ eos_cb (GstPlayer * unused, GtkPlay * play) gtk_widget_set_sensitive (play->next_button, g_list_next (next) != NULL); gst_player_set_uri (play->player, next->data); + clear_missing_plugins (play); gst_player_play (play->player); set_title (play, next->data); } else { @@ -330,6 +363,24 @@ eos_cb (GstPlayer * unused, GtkPlay * play) } } +static void +error_cb (GstPlayer * player, GError * err, GtkPlay * play) +{ + char *message; + + if (g_error_matches (err, gst_player_error_quark (), + GST_PLAYER_ERROR_MISSING_PLUGIN)) { + // add message to end of any existing message: there may be + // multiple missing plugins. + message = g_strdup_printf ("%s%s. ", + gtk_label_get_text (GTK_LABEL (play->info_label)), err->message); + gtk_label_set_text (GTK_LABEL (play->info_label), message); + g_free (message); + + gtk_widget_show (play->info_bar); + } +} + int main (gint argc, gchar ** argv) { @@ -422,6 +473,7 @@ main (gint argc, gchar ** argv) g_signal_connect (play.player, "video-dimensions-changed", G_CALLBACK (video_dimensions_changed_cb), &play); g_signal_connect (play.player, "end-of-stream", G_CALLBACK (eos_cb), &play); + g_signal_connect (play.player, "error", G_CALLBACK (error_cb), &play); /* We have file(s) that need playing. */ set_title (&play, g_list_first (play.uris)->data); diff --git a/lib/gst/player/gstplayer.c b/lib/gst/player/gstplayer.c index bd682d9..78e7ba1 100644 --- a/lib/gst/player/gstplayer.c +++ b/lib/gst/player/gstplayer.c @@ -47,6 +47,7 @@ #include #include +#include GST_DEBUG_CATEGORY_STATIC (gst_player_debug); #define GST_CAT_DEFAULT gst_player_debug @@ -238,6 +239,7 @@ gst_player_class_init (GstPlayerClass * klass) g_signal_new ("video-dimensions-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); + } static void @@ -619,6 +621,21 @@ error_cb (GstBus * bus, GstMessage * msg, gpointer user_data) g_mutex_unlock (&self->priv->lock); } +static void +element_cb (GstBus * bus, GstMessage * msg, gpointer user_data) +{ + GstPlayer *self = GST_PLAYER (user_data); + + if (gst_is_missing_plugin_message (msg)) { + gchar *desc; + + desc = gst_missing_plugin_message_get_description (msg); + emit_error (self, g_error_new (GST_PLAYER_ERROR, + GST_PLAYER_ERROR_MISSING_PLUGIN, "Missing plugin '%s'", desc)); + g_free (desc); + } +} + static gboolean eos_dispatch (gpointer user_data) { @@ -1059,6 +1076,8 @@ gst_player_main (gpointer data) NULL, NULL); g_source_attach (bus_source, self->priv->context); + g_signal_connect (G_OBJECT (bus), "message::element", + G_CALLBACK (element_cb), self); g_signal_connect (G_OBJECT (bus), "message::error", G_CALLBACK (error_cb), self); g_signal_connect (G_OBJECT (bus), "message::eos", G_CALLBACK (eos_cb), self); @@ -1560,6 +1579,7 @@ gst_player_error_get_type (void) static gsize id = 0; static const GEnumValue values[] = { {C_ENUM (GST_PLAYER_ERROR_FAILED), "GST_PLAYER_ERROR_FAILED", "failed"}, + {C_ENUM (GST_PLAYER_ERROR_MISSING_PLUGIN), "GST_PLAYER_ERROR_MISSING_PLUGIN", "missing-plugin"}, {0, NULL, NULL} }; @@ -1577,6 +1597,8 @@ gst_player_error_get_name (GstPlayerError error) switch (error) { case GST_PLAYER_ERROR_FAILED: return "failed"; + case GST_PLAYER_ERROR_MISSING_PLUGIN: + return "missing-plugin"; } g_assert_not_reached (); diff --git a/lib/gst/player/gstplayer.h b/lib/gst/player/gstplayer.h index c438513..35fb5bb 100644 --- a/lib/gst/player/gstplayer.h +++ b/lib/gst/player/gstplayer.h @@ -44,7 +44,8 @@ GType gst_player_error_get_type (void); #define GST_TYPE_PLAYER_ERROR (gst_player_error_get_type ()) typedef enum { - GST_PLAYER_ERROR_FAILED = 0 + GST_PLAYER_ERROR_FAILED = 0, + GST_PLAYER_ERROR_MISSING_PLUGIN } GstPlayerError; const gchar *gst_player_error_get_name (GstPlayerError error); -- 2.1.4