static void query_progress_cb (GDataEntry *entry, guint entry_key, guint entry_count, QueryData *data) { GList *thumbnails; GDataMediaThumbnail *thumbnail = NULL; gint delta = G_MININT; GtkTreeIter iter; const gchar *title, *id; GtkProgressBar *progress_bar; TotemYouTubePlugin *self = data->plugin; /* Add the entry to the tree view */ title = gdata_entry_get_title (entry); id = gdata_youtube_video_get_video_id (GDATA_YOUTUBE_VIDEO (entry)); gtk_list_store_append (self->list_store[data->tree_view], &iter); gtk_list_store_set (self->list_store[data->tree_view], &iter, 0, NULL, /* the thumbnail will be downloaded asynchronously and added to the tree view later */ 1, title, 2, NULL, /* the video URI will be resolved asynchronously and added to the tree view later */ 3, entry, -1); g_debug ("Added entry %s to tree view (title: \"%s\")", id, title); /* Update the progress bar; we have three steps for each entry in the results: the entry, its thumbnail, and its t parameter */ g_assert (entry_count > 0); progress_bar = self->progress_bar[data->tree_view]; self->progress_bar_increment[data->tree_view] = 1.0 / (entry_count * 3.0); g_debug ("Setting progress_bar_increment to 1.0 / (%u * 3.0) = %f", entry_count, self->progress_bar_increment[data->tree_view]); gtk_progress_bar_set_fraction (progress_bar, gtk_progress_bar_get_fraction (progress_bar) + self->progress_bar_increment[data->tree_view]); /* Resolve the t parameter for the video, which is required before it can be played */ /* This will be cancelled if the main query is cancelled, in query_finished_cb() */ data->t_param_cancellable = g_cancellable_new (); resolve_t_param (self, entry, &iter, data->tree_view, data->t_param_cancellable); /* Download the entry's thumbnail, ready for adding it to the tree view. * Find the thumbnail size which is closest to the wanted size (THUMBNAIL_WIDTH), so that we: * a) avoid fuzzy images due to scaling up, and * b) avoid downloading too much just to scale down by a factor of 10. */ thumbnails = gdata_youtube_video_get_thumbnails (GDATA_YOUTUBE_VIDEO (entry)); for (; thumbnails != NULL; thumbnails = thumbnails->next) { gint new_delta; GDataMediaThumbnail *current_thumb = (GDataMediaThumbnail*) thumbnails->data; g_debug ("%u pixel wide thumbnail available for entry %s", gdata_media_thumbnail_get_width (current_thumb), id); new_delta = gdata_media_thumbnail_get_width (current_thumb) - THUMBNAIL_WIDTH; if (delta == 0) { break; } else if ((delta == G_MININT) || (delta < 0 && new_delta > delta) || (delta > 0 && new_delta > 0 && new_delta < delta)) { delta = new_delta; thumbnail = current_thumb; g_debug ("Choosing a %u pixel wide thumbnail (delta: %i) for entry %s", gdata_media_thumbnail_get_width (current_thumb), new_delta, id); } } if (thumbnail != NULL) { GFile *thumbnail_file; ThumbnailData *t_data; t_data = g_slice_new (ThumbnailData); t_data->plugin = g_object_ref (self); t_data->path = gtk_tree_model_get_path (GTK_TREE_MODEL (self->list_store[data->tree_view]), &iter); t_data->tree_view = data->tree_view; /* We can use the same cancellable for reading the file and making a pixbuf out of it, as they're consecutive operations */ /* This will be cancelled if the main query is cancelled, in query_finished_cb() */ data->thumbnail_cancellable = g_cancellable_new (); t_data->cancellable = g_object_ref (data->thumbnail_cancellable); g_debug ("Starting thumbnail download for entry %s", id); thumbnail_file = g_file_new_for_uri (gdata_media_thumbnail_get_uri (thumbnail)); g_file_read_async (thumbnail_file, G_PRIORITY_DEFAULT, data->thumbnail_cancellable, (GAsyncReadyCallback) thumbnail_opened_cb, t_data); g_object_unref (thumbnail_file); } }
gint main (void) { GDataDocumentsFeed *feed = NULL; GDataDocumentsQuery *query = NULL; GDataDocumentsService *service = NULL; GError *error = NULL; GList *accounts = NULL; GList *entries; GList *l; GoaClient *client = NULL; client = goa_client_new_sync (NULL, &error); if (error != NULL) { g_warning ("%s", error->message); g_error_free (error); goto out; } accounts = goa_client_get_accounts (client); for (l = accounts; l != NULL; l = l->next) { GoaAccount *account; GoaObject *object = GOA_OBJECT (l->data); const gchar *provider_type; account = goa_object_peek_account (object); provider_type = goa_account_get_provider_type (account); if (g_strcmp0 (provider_type, "google") == 0) { GDataGoaAuthorizer *authorizer; authorizer = gdata_goa_authorizer_new (object); service = gdata_documents_service_new (GDATA_AUTHORIZER (authorizer)); g_object_unref (authorizer); } } if (service == NULL) { g_warning ("Account not found"); goto out; } query = gdata_documents_query_new_with_limits (NULL, 1, 10); gdata_documents_query_set_show_folders (query, TRUE); while (TRUE) { feed = gdata_documents_service_query_documents (service, query, NULL, NULL, NULL, &error); if (error != NULL) { g_warning ("%s", error->message); g_error_free (error); goto out; } entries = gdata_feed_get_entries (GDATA_FEED (feed)); if (entries == NULL) { goto out; } for (l = entries; l != NULL; l = l->next) { GDataEntry *entry = GDATA_ENTRY (l->data); const gchar *title; title = gdata_entry_get_title (entry); g_message ("%s", title); } gdata_query_next_page (GDATA_QUERY (query)); g_object_unref (feed); } out: g_clear_object (&feed); g_clear_object (&query); g_clear_object (&service); g_clear_object (&client); g_list_free_full (accounts, g_object_unref); return 0; }