diff options
author | Jussi Kukkonen <jussi.kukkonen@intel.com> | 2015-03-24 18:15:28 +0200 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-03-25 12:39:45 +0000 |
commit | 62fdc7b503c2423ea3d6c62e2b6cb37a6159d994 (patch) | |
tree | 62c55ce9859e7e91c9bfa083fec2fbc714066579 | |
parent | 14098e37c8e5dcd2e22c067706638ed9c530a3b0 (diff) | |
download | poky-62fdc7b503c2423ea3d6c62e2b6cb37a6159d994.tar.gz |
gst-player: Add error messages for missing plugins
Make it easier to understand problems with missing gstreamer plugins
(e.g. decoders) by adding an info bar with a message like "Missing
plugin 'MPEG-4 AAC decoder'" to the player.
(From OE-Core rev: fb04247ac27cf18b46efbc47aae6bb3f9fde8168)
Signed-off-by: Jussi Kukkonen <jussi.kukkonen@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/recipes-multimedia/gstreamer/gst-player/Add-error-signal-emission-for-missing-plugins.patch | 252 | ||||
-rw-r--r-- | meta/recipes-multimedia/gstreamer/gst-player_git.bb | 1 |
2 files changed, 253 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/gstreamer/gst-player/Add-error-signal-emission-for-missing-plugins.patch b/meta/recipes-multimedia/gstreamer/gst-player/Add-error-signal-emission-for-missing-plugins.patch new file mode 100644 index 0000000000..712d46daa0 --- /dev/null +++ b/meta/recipes-multimedia/gstreamer/gst-player/Add-error-signal-emission-for-missing-plugins.patch | |||
@@ -0,0 +1,252 @@ | |||
1 | From d64c7edb66f4a64ff49c4306cf77fd269b7079ab Mon Sep 17 00:00:00 2001 | ||
2 | From: Jussi Kukkonen <jussi.kukkonen@intel.com> | ||
3 | Date: Mon, 16 Mar 2015 13:45:30 +0200 | ||
4 | Subject: [PATCH] Add error signal emission for missing plugins | ||
5 | |||
6 | Add a missing plugins error signal to gst-player. Note that this error | ||
7 | does not necessarily mean the playback has completely failed, but in | ||
8 | practice the user experience will be bad (think, e.g. of a mp4 file | ||
9 | where H.264 codec is missing: AAC playback still works...). | ||
10 | |||
11 | Use the signal in gtk-play to show a infobar if plugins are missing. | ||
12 | |||
13 | Submitted upstream at https://github.com/sdroege/gst-player/pull/11 | ||
14 | |||
15 | Upstream-Status: Submitted | ||
16 | Signed-off-by: Jussi Kukkonen <jussi.kukkonen@intel.com> | ||
17 | --- | ||
18 | configure.ac | 2 +- | ||
19 | gtk/gtk-play.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- | ||
20 | lib/gst/player/gstplayer.c | 22 +++++++++++++++++++ | ||
21 | lib/gst/player/gstplayer.h | 3 ++- | ||
22 | 4 files changed, 78 insertions(+), 3 deletions(-) | ||
23 | |||
24 | diff --git a/configure.ac b/configure.ac | ||
25 | index 90ab74c..6cdb4eb 100644 | ||
26 | --- a/configure.ac | ||
27 | +++ b/configure.ac | ||
28 | @@ -53,7 +53,7 @@ AC_SUBST(LT_AGE) | ||
29 | PKG_PROG_PKG_CONFIG | ||
30 | |||
31 | PKG_CHECK_MODULES(GLIB, [glib-2.0 gobject-2.0]) | ||
32 | -PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0 >= 1.4 gstreamer-video-1.0 >= 1.4]) | ||
33 | +PKG_CHECK_MODULES(GSTREAMER, [gstreamer-1.0 >= 1.4 gstreamer-video-1.0 >= 1.4 gstreamer-pbutils-1.0]) | ||
34 | |||
35 | GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" | ||
36 | AC_SUBST(GLIB_PREFIX) | ||
37 | diff --git a/gtk/gtk-play.c b/gtk/gtk-play.c | ||
38 | index b92773b..e2b605a 100644 | ||
39 | --- a/gtk/gtk-play.c | ||
40 | +++ b/gtk/gtk-play.c | ||
41 | @@ -30,6 +30,8 @@ typedef struct | ||
42 | GtkWidget *prev_button, *next_button; | ||
43 | GtkWidget *seekbar; | ||
44 | GtkWidget *video_area; | ||
45 | + GtkWidget *info_label; | ||
46 | + GtkWidget *info_bar; | ||
47 | GtkWidget *volume_button; | ||
48 | gulong seekbar_value_changed_signal_id; | ||
49 | gboolean playing; | ||
50 | @@ -141,6 +143,13 @@ play_pause_clicked_cb (GtkButton * button, GtkPlay * play) | ||
51 | } | ||
52 | |||
53 | static void | ||
54 | +clear_missing_plugins (GtkPlay * play) | ||
55 | +{ | ||
56 | + gtk_label_set_text (GTK_LABEL (play->info_label), ""); | ||
57 | + gtk_widget_hide (play->info_bar); | ||
58 | +} | ||
59 | + | ||
60 | +static void | ||
61 | skip_prev_clicked_cb (GtkButton * button, GtkPlay * play) | ||
62 | { | ||
63 | GList *prev; | ||
64 | @@ -155,6 +164,7 @@ skip_prev_clicked_cb (GtkButton * button, GtkPlay * play) | ||
65 | |||
66 | gtk_widget_set_sensitive (play->next_button, TRUE); | ||
67 | gst_player_set_uri (play->player, prev->data); | ||
68 | + clear_missing_plugins (play); | ||
69 | gst_player_play (play->player); | ||
70 | set_title (play, prev->data); | ||
71 | gtk_widget_set_sensitive (play->prev_button, g_list_previous (prev) != NULL); | ||
72 | @@ -175,6 +185,7 @@ skip_next_clicked_cb (GtkButton * button, GtkPlay * play) | ||
73 | |||
74 | gtk_widget_set_sensitive (play->prev_button, TRUE); | ||
75 | gst_player_set_uri (play->player, next->data); | ||
76 | + clear_missing_plugins (play); | ||
77 | gst_player_play (play->player); | ||
78 | set_title (play, next->data); | ||
79 | gtk_widget_set_sensitive (play->next_button, g_list_next (next) != NULL); | ||
80 | @@ -193,10 +204,16 @@ volume_changed_cb (GtkScaleButton * button, gdouble value, GtkPlay * play) | ||
81 | gst_player_set_volume (play->player, value); | ||
82 | } | ||
83 | |||
84 | +void | ||
85 | +info_bar_response_cb (GtkInfoBar * bar, gint response, GtkPlay * play) | ||
86 | +{ | ||
87 | + gtk_widget_hide (GTK_WIDGET (bar)); | ||
88 | +} | ||
89 | + | ||
90 | static void | ||
91 | create_ui (GtkPlay * play) | ||
92 | { | ||
93 | - GtkWidget *controls, *main_hbox, *main_vbox; | ||
94 | + GtkWidget *controls, *main_hbox, *main_vbox, *info_bar, *content_area; | ||
95 | |||
96 | play->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); | ||
97 | g_signal_connect (G_OBJECT (play->window), "delete-event", | ||
98 | @@ -208,6 +225,20 @@ create_ui (GtkPlay * play) | ||
99 | g_signal_connect (play->video_area, "realize", | ||
100 | G_CALLBACK (video_area_realize_cb), play); | ||
101 | |||
102 | + play->info_bar = gtk_info_bar_new (); | ||
103 | + gtk_info_bar_set_message_type (GTK_INFO_BAR (play->info_bar), | ||
104 | + GTK_MESSAGE_WARNING); | ||
105 | + //gtk_info_bar_set_show_close_button (GTK_INFO_BAR (play->info_bar), | ||
106 | + // TRUE); | ||
107 | + gtk_widget_set_no_show_all (play->info_bar, TRUE); | ||
108 | + g_signal_connect (play->info_bar, "response", | ||
109 | + G_CALLBACK (info_bar_response_cb), play); | ||
110 | + | ||
111 | + content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (play->info_bar)); | ||
112 | + play->info_label = gtk_label_new (""); | ||
113 | + gtk_container_add (GTK_CONTAINER (content_area), play->info_label); | ||
114 | + gtk_widget_show (play->info_label); | ||
115 | + | ||
116 | /* Unified play/pause button */ | ||
117 | play->play_pause_button = | ||
118 | gtk_button_new_from_icon_name ("media-playback-pause", | ||
119 | @@ -258,6 +289,7 @@ create_ui (GtkPlay * play) | ||
120 | |||
121 | main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); | ||
122 | gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, TRUE, TRUE, 0); | ||
123 | + gtk_box_pack_start (GTK_BOX (main_vbox), play->info_bar, FALSE, FALSE, 0); | ||
124 | gtk_box_pack_start (GTK_BOX (main_vbox), controls, FALSE, FALSE, 0); | ||
125 | gtk_container_add (GTK_CONTAINER (play->window), main_vbox); | ||
126 | |||
127 | @@ -322,6 +354,7 @@ eos_cb (GstPlayer * unused, GtkPlay * play) | ||
128 | gtk_widget_set_sensitive (play->next_button, g_list_next (next) != NULL); | ||
129 | |||
130 | gst_player_set_uri (play->player, next->data); | ||
131 | + clear_missing_plugins (play); | ||
132 | gst_player_play (play->player); | ||
133 | set_title (play, next->data); | ||
134 | } else { | ||
135 | @@ -330,6 +363,24 @@ eos_cb (GstPlayer * unused, GtkPlay * play) | ||
136 | } | ||
137 | } | ||
138 | |||
139 | +static void | ||
140 | +error_cb (GstPlayer * player, GError * err, GtkPlay * play) | ||
141 | +{ | ||
142 | + char *message; | ||
143 | + | ||
144 | + if (g_error_matches (err, gst_player_error_quark (), | ||
145 | + GST_PLAYER_ERROR_MISSING_PLUGIN)) { | ||
146 | + // add message to end of any existing message: there may be | ||
147 | + // multiple missing plugins. | ||
148 | + message = g_strdup_printf ("%s%s. ", | ||
149 | + gtk_label_get_text (GTK_LABEL (play->info_label)), err->message); | ||
150 | + gtk_label_set_text (GTK_LABEL (play->info_label), message); | ||
151 | + g_free (message); | ||
152 | + | ||
153 | + gtk_widget_show (play->info_bar); | ||
154 | + } | ||
155 | +} | ||
156 | + | ||
157 | int | ||
158 | main (gint argc, gchar ** argv) | ||
159 | { | ||
160 | @@ -422,6 +473,7 @@ main (gint argc, gchar ** argv) | ||
161 | g_signal_connect (play.player, "video-dimensions-changed", | ||
162 | G_CALLBACK (video_dimensions_changed_cb), &play); | ||
163 | g_signal_connect (play.player, "end-of-stream", G_CALLBACK (eos_cb), &play); | ||
164 | + g_signal_connect (play.player, "error", G_CALLBACK (error_cb), &play); | ||
165 | |||
166 | /* We have file(s) that need playing. */ | ||
167 | set_title (&play, g_list_first (play.uris)->data); | ||
168 | diff --git a/lib/gst/player/gstplayer.c b/lib/gst/player/gstplayer.c | ||
169 | index bd682d9..78e7ba1 100644 | ||
170 | --- a/lib/gst/player/gstplayer.c | ||
171 | +++ b/lib/gst/player/gstplayer.c | ||
172 | @@ -47,6 +47,7 @@ | ||
173 | |||
174 | #include <gst/gst.h> | ||
175 | #include <gst/video/video.h> | ||
176 | +#include <gst/pbutils/missing-plugins.h> | ||
177 | |||
178 | GST_DEBUG_CATEGORY_STATIC (gst_player_debug); | ||
179 | #define GST_CAT_DEFAULT gst_player_debug | ||
180 | @@ -238,6 +239,7 @@ gst_player_class_init (GstPlayerClass * klass) | ||
181 | g_signal_new ("video-dimensions-changed", G_TYPE_FROM_CLASS (klass), | ||
182 | G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL, | ||
183 | NULL, NULL, G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); | ||
184 | + | ||
185 | } | ||
186 | |||
187 | static void | ||
188 | @@ -619,6 +621,21 @@ error_cb (GstBus * bus, GstMessage * msg, gpointer user_data) | ||
189 | g_mutex_unlock (&self->priv->lock); | ||
190 | } | ||
191 | |||
192 | +static void | ||
193 | +element_cb (GstBus * bus, GstMessage * msg, gpointer user_data) | ||
194 | +{ | ||
195 | + GstPlayer *self = GST_PLAYER (user_data); | ||
196 | + | ||
197 | + if (gst_is_missing_plugin_message (msg)) { | ||
198 | + gchar *desc; | ||
199 | + | ||
200 | + desc = gst_missing_plugin_message_get_description (msg); | ||
201 | + emit_error (self, g_error_new (GST_PLAYER_ERROR, | ||
202 | + GST_PLAYER_ERROR_MISSING_PLUGIN, "Missing plugin '%s'", desc)); | ||
203 | + g_free (desc); | ||
204 | + } | ||
205 | +} | ||
206 | + | ||
207 | static gboolean | ||
208 | eos_dispatch (gpointer user_data) | ||
209 | { | ||
210 | @@ -1059,6 +1076,8 @@ gst_player_main (gpointer data) | ||
211 | NULL, NULL); | ||
212 | g_source_attach (bus_source, self->priv->context); | ||
213 | |||
214 | + g_signal_connect (G_OBJECT (bus), "message::element", | ||
215 | + G_CALLBACK (element_cb), self); | ||
216 | g_signal_connect (G_OBJECT (bus), "message::error", G_CALLBACK (error_cb), | ||
217 | self); | ||
218 | g_signal_connect (G_OBJECT (bus), "message::eos", G_CALLBACK (eos_cb), self); | ||
219 | @@ -1560,6 +1579,7 @@ gst_player_error_get_type (void) | ||
220 | static gsize id = 0; | ||
221 | static const GEnumValue values[] = { | ||
222 | {C_ENUM (GST_PLAYER_ERROR_FAILED), "GST_PLAYER_ERROR_FAILED", "failed"}, | ||
223 | + {C_ENUM (GST_PLAYER_ERROR_MISSING_PLUGIN), "GST_PLAYER_ERROR_MISSING_PLUGIN", "missing-plugin"}, | ||
224 | {0, NULL, NULL} | ||
225 | }; | ||
226 | |||
227 | @@ -1577,6 +1597,8 @@ gst_player_error_get_name (GstPlayerError error) | ||
228 | switch (error) { | ||
229 | case GST_PLAYER_ERROR_FAILED: | ||
230 | return "failed"; | ||
231 | + case GST_PLAYER_ERROR_MISSING_PLUGIN: | ||
232 | + return "missing-plugin"; | ||
233 | } | ||
234 | |||
235 | g_assert_not_reached (); | ||
236 | diff --git a/lib/gst/player/gstplayer.h b/lib/gst/player/gstplayer.h | ||
237 | index c438513..35fb5bb 100644 | ||
238 | --- a/lib/gst/player/gstplayer.h | ||
239 | +++ b/lib/gst/player/gstplayer.h | ||
240 | @@ -44,7 +44,8 @@ GType gst_player_error_get_type (void); | ||
241 | #define GST_TYPE_PLAYER_ERROR (gst_player_error_get_type ()) | ||
242 | |||
243 | typedef enum { | ||
244 | - GST_PLAYER_ERROR_FAILED = 0 | ||
245 | + GST_PLAYER_ERROR_FAILED = 0, | ||
246 | + GST_PLAYER_ERROR_MISSING_PLUGIN | ||
247 | } GstPlayerError; | ||
248 | |||
249 | const gchar *gst_player_error_get_name (GstPlayerError error); | ||
250 | -- | ||
251 | 2.1.4 | ||
252 | |||
diff --git a/meta/recipes-multimedia/gstreamer/gst-player_git.bb b/meta/recipes-multimedia/gstreamer/gst-player_git.bb index 07224c00e3..54cfbbc927 100644 --- a/meta/recipes-multimedia/gstreamer/gst-player_git.bb +++ b/meta/recipes-multimedia/gstreamer/gst-player_git.bb | |||
@@ -9,6 +9,7 @@ SRC_URI = "git://github.com/sdroege/gst-player.git \ | |||
9 | file://filechooser.patch \ | 9 | file://filechooser.patch \ |
10 | file://gtk2.patch \ | 10 | file://gtk2.patch \ |
11 | file://Fix-pause-play.patch \ | 11 | file://Fix-pause-play.patch \ |
12 | file://Add-error-signal-emission-for-missing-plugins.patch \ | ||
12 | file://gst-player.desktop" | 13 | file://gst-player.desktop" |
13 | 14 | ||
14 | SRCREV = "5386c5b984d40ef5434673ed62204e69aaf52645" | 15 | SRCREV = "5386c5b984d40ef5434673ed62204e69aaf52645" |