From dd42ebd45cf39bbdd8b1d5dd0fb0682c00d46b41 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Fri, 13 Feb 2015 16:30:13 +0100 Subject: missing plugins: Ask the user before spawning a plugin search Previously, the PackageKit session service implementation would use Totem's window xid to attach its own dialogs. This however no longer works in Wayland world. Instead of attaching a dialog to Totem's window, gnome-software by default now pops up a Shell notification asking for confirmation before launching the codec search. This is however just a fallback and the preferred way is for an app to pop up its own dialog / in-app notification before starting the codec installation. This commit implements the confirmation dialog within Totem and passes down necessary flags to supress the Shell notification in that case. https://bugzilla.gnome.org/show_bug.cgi?id=744610 --- .../bacon-video-widget-gst-missing-plugins.c | 156 ++++++++++++++++++++- 1 file changed, 150 insertions(+), 6 deletions(-) (limited to 'src/backend/bacon-video-widget-gst-missing-plugins.c') diff --git a/src/backend/bacon-video-widget-gst-missing-plugins.c b/src/backend/bacon-video-widget-gst-missing-plugins.c index 6ceead3de..c71756601 100644 --- a/src/backend/bacon-video-widget-gst-missing-plugins.c +++ b/src/backend/bacon-video-widget-gst-missing-plugins.c @@ -34,6 +34,8 @@ #include #include +#include +#include #include #ifdef GDK_WINDOWING_X11 @@ -236,8 +238,25 @@ on_plugin_installation_done (GstInstallPluginsReturn res, gpointer user_data) bacon_video_widget_gst_codec_install_context_free (ctx); } +#ifdef GDK_WINDOWING_X11 +#if GST_CHECK_VERSION (1, 5, 0) +static gchar * +set_startup_notification_id (GstInstallPluginsContext *install_ctx) +{ + gchar *startup_id; + guint32 timestamp; + + timestamp = gtk_get_current_event_time (); + startup_id = g_strdup_printf ("_TIME%u", timestamp); + gst_install_plugins_context_set_startup_notification_id (install_ctx, startup_id); + g_free (startup_id); +} +#endif +#endif + static gboolean -bacon_video_widget_start_plugin_installation (TotemCodecInstallContext *ctx) +bacon_video_widget_start_plugin_installation (TotemCodecInstallContext *ctx, + gboolean confirm_search) { GstInstallPluginsContext *install_ctx; GstInstallPluginsReturn status; @@ -248,6 +267,7 @@ bacon_video_widget_start_plugin_installation (TotemCodecInstallContext *ctx) install_ctx = gst_install_plugins_context_new (); #if GST_CHECK_VERSION (1, 5, 0) gst_install_plugins_context_set_desktop_id (install_ctx, "org.gnome.Totem.desktop"); + gst_install_plugins_context_set_confirm_search (install_ctx, confirm_search); #endif #ifdef GDK_WINDOWING_X11 @@ -259,6 +279,10 @@ bacon_video_widget_start_plugin_installation (TotemCodecInstallContext *ctx) { gulong xid = 0; +#if GST_CHECK_VERSION (1, 5, 0) + set_startup_notification_id (install_ctx); +#endif + xid = bacon_video_widget_gst_get_toplevel (GTK_WIDGET (ctx->bvw)); gst_install_plugins_context_set_xid (install_ctx, xid); } @@ -289,10 +313,121 @@ bacon_video_widget_start_plugin_installation (TotemCodecInstallContext *ctx) return TRUE; } +#if GST_CHECK_VERSION (1, 5, 0) +static void +codec_confirmation_dialog_response_cb (GtkDialog *dialog, + GtkResponseType response_type, + gpointer user_data) +{ + TotemCodecInstallContext *ctx = user_data; + + switch (response_type) { + case GTK_RESPONSE_ACCEPT: + bacon_video_widget_start_plugin_installation (ctx, FALSE); + break; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + break; + default: + g_assert_not_reached (); + } + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + +static void +show_codec_confirmation_dialog (TotemCodecInstallContext *ctx, + const gchar *install_helper_display_name) +{ + GtkWidget *button; + GtkWidget *dialog; + GtkWidget *toplevel; + gchar *button_text; + gchar *descriptions_text; + gchar *message_text; + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (ctx->bvw)); + + dialog = gtk_message_dialog_new (GTK_WINDOW (toplevel), + GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CANCEL, + _("Unable to play the file")); + + descriptions_text = g_strjoinv (", ", ctx->descriptions); + message_text = g_strdup_printf (ngettext ("%s is required to play the file, but is not installed.", + "%s are required to play the file, but are not installed.", + g_strv_length (ctx->descriptions)), + descriptions_text); + + /* TRANSLATORS: this is a button to launch a codec installer. + * %s will be replaced with the software installer's name, e.g. + * 'Software' in case of gnome-software. */ + button_text = g_strdup_printf ("_Find in %s", install_helper_display_name); + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", message_text); + button = gtk_dialog_add_button (GTK_DIALOG (dialog), + button_text, + GTK_RESPONSE_ACCEPT); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + gtk_style_context_add_class (gtk_widget_get_style_context (button), "suggested-action"); + g_signal_connect (dialog, "response", + G_CALLBACK (codec_confirmation_dialog_response_cb), + ctx); + + gtk_window_present (GTK_WINDOW (dialog)); + + g_free (button_text); + g_free (descriptions_text); + g_free (message_text); +} +#endif + +static void +on_packagekit_proxy_ready (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + TotemCodecInstallContext *ctx = (TotemCodecInstallContext *) user_data; + GDBusProxy *packagekit_proxy = NULL; + GVariant *property = NULL; + GError *error = NULL; + + packagekit_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + if (packagekit_proxy == NULL && + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { + goto out; + } + +#if GST_CHECK_VERSION (1, 5, 0) + if (packagekit_proxy != NULL) { + property = g_dbus_proxy_get_cached_property (packagekit_proxy, "DisplayName"); + if (property != NULL) { + const gchar *display_name; + + display_name = g_variant_get_string (property, NULL); + if (display_name != NULL && display_name[0] != '\0') { + show_codec_confirmation_dialog (ctx, display_name); + goto out; + } + } + } +#endif + + /* If the above failed, fall back to immediately starting the codec installation */ + bacon_video_widget_start_plugin_installation (ctx, TRUE); + +out: + g_clear_error (&error); + g_clear_pointer (&property, g_variant_unref); + g_clear_object (&packagekit_proxy); +} + static gboolean -bacon_video_widget_gst_on_missing_plugins_event (BaconVideoWidget *bvw, char **details, - char **descriptions, gboolean playing, - gpointer user_data) +bacon_video_widget_gst_on_missing_plugins_event (BaconVideoWidget *bvw, + char **details, + char **descriptions, + gboolean playing, + gpointer user_data) { TotemCodecInstallContext *ctx; guint i, num; @@ -331,8 +466,17 @@ bacon_video_widget_gst_on_missing_plugins_event (BaconVideoWidget *bvw, char **d return FALSE; } - if (!bacon_video_widget_start_plugin_installation (ctx)) - return FALSE; + /* Get the PackageKit session interface proxy and continue with the + * codec installation in the callback */ + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, /* g-interface-info */ + "org.freedesktop.PackageKit", + "/org/freedesktop/PackageKit", + "org.freedesktop.PackageKit.Modify2", + g_object_get_data (G_OBJECT (bvw), "missing-plugins-cancellable"), + on_packagekit_proxy_ready, + ctx); /* if we managed to start playing, pause playback, since some install * wizard should now take over in a second anyway and the user might not -- cgit v1.2.1