static void query_finished_cb (GObject *source_object, GAsyncResult *result, QueryData *data) { GtkWindow *window; GDataFeed *feed; GError *error = NULL; TotemYouTubePlugin *self = data->plugin; g_debug ("Search finished!"); feed = gdata_service_query_finish (GDATA_SERVICE (self->service), result, &error); /* Stop the progress bar; a little hacky, but it works */ self->progress_bar_increment[data->tree_view] = 1.0; increment_progress_bar_fraction (self, data->tree_view); if (feed != NULL) { /* Success! */ g_object_unref (feed); query_data_free (data); return; } /* Bail out if the operation was cancelled */ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) == TRUE) { /* Cancel the t-param and thumbnail threads, if applicable */ if (data->t_param_cancellable != NULL) g_cancellable_cancel (data->t_param_cancellable); if (data->thumbnail_cancellable != NULL) g_cancellable_cancel (data->thumbnail_cancellable); goto finish; } /* Error! */ window = totem_get_main_window (data->plugin->totem); if (g_error_matches (error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR) == TRUE) { /* Hide the ugly technical message libgdata gives behind a nice one telling them it's out of date (which it likely is * if we're receiving a protocol error). */ totem_interface_error (_("Error Searching for Videos"), _("The response from the server could not be understood. " "Please check you are running the latest version of libgdata."), window); } else { /* Spew out the error message as provided */ totem_interface_error (_("Error Searching for Videos"), error->message, window); } g_object_unref (window); finish: g_error_free (error); query_data_free (data); return; }
/** * totem_interface_load_with_full_path: * @filename: the #GtkBuilder UI file path to load * @fatal: %TRUE if errors loading the file should be fatal, %FALSE otherwise * @parent: (allow-none): the parent window to use when displaying error dialogues, or %NULL * @user_data: (allow-none): the user data to pass to gtk_builder_connect_signals(), or %NULL * * Load a #GtkBuilder UI file from the given path and return the #GtkBuilder instance for it. If loading the file fails, an error dialogue is shown. * * Return value: (transfer full): the loaded #GtkBuilder object, or %NULL */ GtkBuilder * totem_interface_load_with_full_path (const char *filename, gboolean fatal, GtkWindow *parent, gpointer user_data) { GtkBuilder *builder = NULL; GError *error = NULL; if (filename != NULL) { builder = gtk_builder_new (); gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); } if (builder == NULL || gtk_builder_add_from_file (builder, filename, &error) == FALSE) { char *msg; msg = g_strdup_printf (_("Couldn't load the '%s' interface. %s"), filename, error->message); if (fatal == FALSE) totem_interface_error (msg, _("Make sure that Totem is properly installed."), parent); else totem_interface_error_blocking (msg, _("Make sure that Totem is properly installed."), parent); g_free (msg); g_error_free (error); return NULL; } gtk_builder_connect_signals (builder, user_data); return builder; }
/** * totem_interface_load: * @name: the #GtkBuilder UI file to load * @fatal: %TRUE if errors loading the file should be fatal, %FALSE otherwise * @parent: (allow-none): the parent window to use when displaying error dialogues, or %NULL * @user_data: (allow-none): the user data to pass to gtk_builder_connect_signals(), or %NULL * * Load a #GtkBuilder UI file with the given name and return the #GtkBuilder instance for it. If loading the file fails, an error dialogue is shown. * * Return value: (transfer full): the loaded #GtkBuilder object, or %NULL */ GtkBuilder * totem_interface_load (const char *name, gboolean fatal, GtkWindow *parent, gpointer user_data) { GtkBuilder *builder = NULL; char *filename; filename = totem_interface_get_full_path (name); if (filename == NULL) { char *msg; msg = g_strdup_printf (_("Couldn't load the '%s' interface. %s"), name, _("The file does not exist.")); if (fatal == FALSE) totem_interface_error (msg, _("Make sure that Totem is properly installed."), parent); else totem_interface_error_blocking (msg, _("Make sure that Totem is properly installed."), parent); g_free (msg); return NULL; } builder = totem_interface_load_with_full_path (filename, fatal, parent, user_data); g_free (filename); return builder; }
static void totem_disc_recorder_plugin_burn (GAction *action, GVariant *variant, TotemDiscRecorderPlugin *pi) { char *path; char *error = NULL; path = totem_disc_recorder_plugin_write_video_project (pi, &error); if (!path) { totem_interface_error (_("The movie could not be recorded."), error, totem_object_get_main_window (pi->priv->totem)); g_free (error); return; } if (!totem_disc_recorder_plugin_start_burning (pi, path, FALSE)) g_remove (path); g_free (path); }
void open_in_web_browser_activate_cb (GtkAction *action, TotemYouTubePlugin *self) { GtkTreeSelection *selection; GtkTreeModel *model; GList *paths, *path; selection = gtk_tree_view_get_selection (self->tree_view[self->current_tree_view]); paths = gtk_tree_selection_get_selected_rows (selection, &model); for (path = paths; path != NULL; path = path->next) { GtkTreeIter iter; GDataYouTubeVideo *video; GDataLink *link; GError *error = NULL; if (gtk_tree_model_get_iter (model, &iter, (GtkTreePath*) (path->data)) == FALSE) continue; /* Get the HTML page for the video; its <link rel="alternate" ... /> */ gtk_tree_model_get (model, &iter, 3, &video, -1); link = gdata_entry_look_up_link (GDATA_ENTRY (video), GDATA_LINK_ALTERNATE); g_object_unref (video); /* Display the page */ if (gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (self->bvw)), gdata_link_get_uri (link), GDK_CURRENT_TIME, &error) == FALSE) { GtkWindow *window = totem_get_main_window (self->totem); totem_interface_error (_("Error Opening Video in Web Browser"), error->message, window); g_object_unref (window); g_error_free (error); } } g_list_foreach (paths, (GFunc) gtk_tree_path_free, NULL); g_list_free (paths); }
static gboolean totem_disc_recorder_plugin_start_burning (TotemDiscRecorderPlugin *pi, const char *path, gboolean copy) { GtkWindow *main_window; GdkScreen *screen; GdkDisplay *display; gchar *command_line; GList *uris; GAppInfo *info; GdkAppLaunchContext *context; GError *error = NULL; char *xid_arg; main_window = totem_object_get_main_window (pi->priv->totem); screen = gtk_widget_get_screen (GTK_WIDGET (main_window)); display = gdk_display_get_default (); /* Build a command line to use */ xid_arg = NULL; #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_DISPLAY (display)) xid_arg = g_strdup_printf ("-x %d", (int) gdk_x11_window_get_xid (gtk_widget_get_window (GTK_WIDGET (main_window)))); #endif /* GDK_WINDOWING_X11 */ g_object_unref (main_window); if (copy != FALSE) command_line = g_strdup_printf ("brasero %s -c", xid_arg ? xid_arg : ""); else command_line = g_strdup_printf ("brasero %s -r", xid_arg ? xid_arg : ""); /* Build the app info */ info = g_app_info_create_from_commandline (command_line, NULL, G_APP_INFO_CREATE_SUPPORTS_URIS | G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION, &error); g_free (command_line); if (error != NULL) goto error; /* Create a launch context and launch it */ context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (main_window))); gdk_app_launch_context_set_screen (context, screen); uris = g_list_prepend (NULL, (gpointer) path); g_app_info_launch_uris (info, uris, G_APP_LAUNCH_CONTEXT (context), &error); g_list_free (uris); g_object_unref (info); g_object_unref (context); if (error != NULL) goto error; return TRUE; error: main_window = totem_object_get_main_window (pi->priv->totem); if (copy != FALSE) totem_interface_error (_("The video disc could not be duplicated."), error->message, main_window); else totem_interface_error (_("The movie could not be recorded."), error->message, main_window); g_error_free (error); g_object_unref (main_window); return FALSE; }
static void resolve_t_param_cb (SoupSession *session, SoupMessage *message, TParamData *data) { gchar *video_uri = NULL; const gchar *video_id, *contents; gsize length; GMatchInfo *match_info; GtkTreeIter iter; TotemYouTubePlugin *self = data->plugin; /* Prevent cancellation */ g_cancellable_disconnect (data->cancellable, data->cancelled_id); /* Finish loading the page */ if (message->status_code != SOUP_STATUS_OK) { GtkWindow *window; /* Bail out if the operation was cancelled */ if (message->status_code == SOUP_STATUS_CANCELLED) goto free_data; /* Couldn't load the page contents; error */ window = totem_get_main_window (data->plugin->totem); totem_interface_error (_("Error Looking Up Video URI"), message->response_body->data, window); g_object_unref (window); goto free_data; } contents = message->response_body->data; length = message->response_body->length; video_id = gdata_youtube_video_get_video_id (GDATA_YOUTUBE_VIDEO (data->entry)); /* Check for the fmt_url_map parameter */ g_regex_match (self->regex, contents, 0, &match_info); if (g_match_info_matches (match_info) == TRUE) { gchar *fmt_url_map_escaped, *fmt_url_map; gchar **mappings, **i; GHashTable *fmt_table; gint connection_speed; /* We have a match */ fmt_url_map_escaped = g_match_info_fetch (match_info, 1); fmt_url_map = g_uri_unescape_string (fmt_url_map_escaped, NULL); g_free (fmt_url_map_escaped); /* The fmt_url_map parameter is in the following format: * fmt1|uri1,fmt2|uri2,fmt3|uri3,... * where fmtN is an identifier for the audio and video encoding and resolution as described here: * (http://en.wikipedia.org/wiki/YouTube#Quality_and_codecs) and uriN is the playback URI for that format. * * We parse it into a hash table from format to URI, and use that against a ranked list of preferred formats (based on the user's * connection speed) to determine the URI to use. */ fmt_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); mappings = g_strsplit (fmt_url_map, ",", 0); for (i = mappings; *i != NULL; i++) { /* For the moment we just take the first format we get */ gchar **mapping; gint fmt; mapping = g_strsplit (*i, "|", 2); if (mapping[0] == NULL || mapping[1] == NULL) { g_warning ("Bad format-URI mapping: %s", *i); g_strfreev (mapping); continue; } fmt = atoi (mapping[0]); if (fmt < 1) { g_warning ("Badly-formed format: %s", mapping[0]); g_strfreev (mapping); continue; } g_hash_table_insert (fmt_table, GUINT_TO_POINTER ((guint) fmt), g_strdup (mapping[1])); g_strfreev (mapping); } g_strfreev (mappings); /* Starting with the highest connection speed we support, look for video URIs matching our connection speed. */ connection_speed = MIN (bacon_video_widget_get_connection_speed (self->bvw), (gint) G_N_ELEMENTS (fmt_preferences) - 1); for (; connection_speed >= 0; connection_speed--) { guint idx = (guint) connection_speed; video_uri = g_strdup (g_hash_table_lookup (fmt_table, GUINT_TO_POINTER (fmt_preferences [idx]))); /* Have we found a match yet? */ if (video_uri != NULL) { g_debug ("Using video URI for format %u (connection speed %u)", fmt_preferences[idx], idx); break; } } g_hash_table_destroy (fmt_table); } /* Fallback */ if (video_uri == NULL) { GDataMediaContent *content; /* We don't have a match, which is odd; fall back to the FLV URI as advertised by the YouTube API */ content = GDATA_MEDIA_CONTENT (gdata_youtube_video_look_up_content (GDATA_YOUTUBE_VIDEO (data->entry), "application/x-shockwave-flash")); if (content != NULL) { video_uri = g_strdup (gdata_media_content_get_uri (content)); g_debug ("Couldn't find the t param of entry %s; falling back to its FLV URI (\"%s\")", video_id, video_uri); } else { /* Cop out */ g_warning ("Couldn't find the t param of entry %s or its FLV URI.", video_uri); video_uri = NULL; } } g_match_info_free (match_info); /* Update the tree view with the new MRL */ if (gtk_tree_model_get_iter (GTK_TREE_MODEL (self->list_store[data->tree_view]), &iter, data->path) == TRUE) { gtk_list_store_set (self->list_store[data->tree_view], &iter, 2, video_uri, -1); g_debug ("Updated list store with new video URI (\"%s\") for entry %s", video_uri, video_id); } g_free (video_uri); free_data: /* Update the progress bar */ increment_progress_bar_fraction (self, data->tree_view); g_object_unref (data->cancellable); g_object_unref (data->plugin); g_object_unref (data->entry); gtk_tree_path_free (data->path); g_slice_free (TParamData, data); }