From 1d6f77d4c4fafd0a9cafddd2797249557e601dba Mon Sep 17 00:00:00 2001 From: Alan F Date: Wed, 19 Feb 2014 08:54:10 +0000 Subject: refactor the torrent upload code (it's called from a few places so is probably worth it), and make it easier to use a HTTP response as the input. --- src/Makefile.am | 1 + src/requests.c | 17 ++++- src/requests.h | 5 +- src/trg-client.c | 18 ++--- src/trg-files-tree-view.c | 2 +- src/trg-main-window.c | 75 +++++++++++--------- src/trg-main-window.h | 3 +- src/trg-rss-model.c | 94 ++++++++++++------------- src/trg-rss-model.h | 2 + src/trg-rss-window.c | 68 ++++++++++++++++--- src/trg-torrent-add-dialog.c | 143 +++++++++++++-------------------------- src/trg-torrent-add-dialog.h | 16 ----- src/trg-torrent-add-url-dialog.c | 2 +- src/trg-torrent-move-dialog.c | 2 +- src/trg-torrent-props-dialog.c | 2 +- src/trg-trackers-tree-view.c | 2 +- src/upload.c | 62 +++++++++++++++++ src/upload.h | 25 +++++++ 18 files changed, 317 insertions(+), 222 deletions(-) create mode 100644 src/upload.c create mode 100644 src/upload.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index f82a7f5..bb11db2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -107,6 +107,7 @@ transmission_remote_gtk_SOURCES = \ main.c \ trg-rss-window.c \ trg-rss-model.c \ + upload.c \ $(NULL) transmission_remote_gtk_LDFLAGS = -lm $(jsonglib_LIBS) $(gtk_LIBS) $(gthread_LIBS) $(GEOIP_LIBS) $(gio_LIBS) $(notify_LIBS) $(libproxy_LIBS) $(libcurl_LIBS) $(libappindicator_LIBS) $(rssglib_LIBS) diff --git a/src/requests.c b/src/requests.c index 95be1d7..43a8561 100644 --- a/src/requests.c +++ b/src/requests.c @@ -227,7 +227,22 @@ JsonNode *torrent_add_url(const gchar * url, gboolean paused) return root; } -JsonNode *torrent_add(gchar * target, gint flags) +JsonNode *torrent_add_from_response(trg_response *response, gint flags) { + JsonNode *root = base_request(METHOD_TORRENT_ADD); + JsonObject *args = node_get_arguments(root); + gchar *encoded = g_base64_encode((guchar *)response->raw, response->size); + + json_object_set_string_member(args, PARAM_METAINFO, + encoded); + g_free(encoded); + + json_object_set_boolean_member(args, PARAM_PAUSED, + (flags & TORRENT_ADD_FLAG_PAUSED)); + + return root; +} + +JsonNode *torrent_add_from_file(gchar * target, gint flags) { JsonNode *root; JsonObject *args; diff --git a/src/requests.h b/src/requests.h index 5ea9b2a..7430fda 100644 --- a/src/requests.h +++ b/src/requests.h @@ -23,6 +23,8 @@ #include #include +#include "trg-client.h" + JsonNode *generic_request(gchar * method, JsonArray * array); JsonNode *session_set(void); @@ -34,7 +36,8 @@ JsonNode *torrent_start(JsonArray * array); JsonNode *torrent_verify(JsonArray * array); JsonNode *torrent_reannounce(JsonArray * array); JsonNode *torrent_remove(JsonArray * array, int removeData); -JsonNode *torrent_add(gchar * filename, gint flags); +JsonNode *torrent_add_from_response(trg_response *response, gint flags); +JsonNode *torrent_add_from_file(gchar * filename, gint flags); JsonNode *torrent_add_url(const gchar * url, gboolean paused); JsonNode *torrent_set_location(JsonArray * array, gchar * location, gboolean move); diff --git a/src/trg-client.c b/src/trg-client.c index 6f33b36..8ab2afd 100644 --- a/src/trg-client.c +++ b/src/trg-client.c @@ -442,11 +442,15 @@ void trg_client_configunlock(TrgClient * tc) void trg_response_free(trg_response * response) { - if (response->obj) - json_object_unref(response->obj); - if (response->raw) - g_free(response->raw); - g_free(response); + if (response) { + if (response->obj) + json_object_unref(response->obj); + + if (response->raw) + g_free(response->raw); + + g_free(response); + } } static size_t @@ -559,10 +563,6 @@ static CURL* get_curl(TrgClient *tc, guint http_class) priv->http_class = http_class; } - if (http_class == HTTP_CLASS_TRANSMISSION) { - curl_easy_setopt(curl, CURLOPT_URL, trg_client_get_url(tc)); - } - curl_easy_setopt(curl, CURLOPT_TIMEOUT, (long) trg_prefs_get_int(prefs, TRG_PREFS_KEY_TIMEOUT, TRG_PREFS_CONNECTION)); diff --git a/src/trg-files-tree-view.c b/src/trg-files-tree-view.c index 1c93ad6..ae9e071 100644 --- a/src/trg-files-tree-view.c +++ b/src/trg-files-tree-view.c @@ -93,7 +93,7 @@ static gboolean on_files_update(gpointer data) response->cb_data = priv->win; - return on_generic_interactive_action(data); + return on_generic_interactive_action_response(data); } static void send_updated_file_prefs(TrgFilesTreeView * tv) diff --git a/src/trg-main-window.c b/src/trg-main-window.c index f4e479c..3066c4d 100644 --- a/src/trg-main-window.c +++ b/src/trg-main-window.c @@ -76,6 +76,7 @@ #include "trg-rss-window.h" #include "trg-remote-prefs-dialog.h" #include "trg-preferences-dialog.h" +#include "upload.h" /* The rather large main window class, which glues everything together. */ @@ -480,7 +481,7 @@ static void pause_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_pause(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void pause_all_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) @@ -489,7 +490,7 @@ static void pause_all_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) if (trg_client_is_connected(priv->client)) dispatch_async(priv->client, torrent_pause(NULL), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris) @@ -505,10 +506,14 @@ gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris) return EXIT_SUCCESS; } - if (uris) - for (i = 0; uris[i]; i++) - if (uris[i]) + if (uris) { + for (i = 0; uris[i]; i++) { + if (is_minimised_arg(uris[i])) + g_free(uris[i]); + else if (uris[i]) filesList = g_slist_append(filesList, uris[i]); + } + } g_free(uris); @@ -518,20 +523,20 @@ gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris) if (trg_prefs_get_bool(prefs, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, TRG_PREFS_GLOBAL)) { TrgTorrentAddDialog *dialog = - trg_torrent_add_dialog_new(win, client, + trg_torrent_add_dialog_new_from_filenames(win, client, filesList); gtk_widget_show_all(GTK_WIDGET(dialog)); } else { - struct add_torrent_threadfunc_args *args = - g_new0(struct add_torrent_threadfunc_args, 1); - args->list = filesList; - args->cb_data = win; - args->client = client; - args->extraArgs = FALSE; - args->flags = trg_prefs_get_add_flags(prefs); - - launch_add_thread(args); + trg_upload *upload = g_new0(trg_upload, 1); + + upload->list = filesList; + upload->main_window = win; + upload->client = client; + upload->extra_args = FALSE; + upload->flags = trg_prefs_get_add_flags(prefs); + + trg_do_upload(upload); } return EXIT_SUCCESS; @@ -543,7 +548,7 @@ static void resume_all_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) if (trg_client_is_connected(priv->client)) dispatch_async(priv->client, torrent_start(NULL), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void resume_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) @@ -554,7 +559,7 @@ static void resume_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_start(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void disconnect_cb(GtkWidget * w G_GNUC_UNUSED, gpointer data) @@ -713,7 +718,7 @@ static void reannounce_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_reannounce(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void verify_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) @@ -724,7 +729,7 @@ static void verify_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_verify(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void start_now_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) @@ -735,7 +740,7 @@ static void start_now_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_start_now(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void up_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) @@ -746,7 +751,7 @@ static void up_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_queue_move_up(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void top_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) @@ -757,7 +762,7 @@ static void top_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_queue_move_top(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void @@ -769,7 +774,7 @@ bottom_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_queue_move_bottom(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static void down_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) @@ -780,7 +785,7 @@ static void down_queue_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) dispatch_async(priv->client, torrent_queue_move_down(build_json_id_array (priv->torrentTreeView)), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); } static gint @@ -882,7 +887,7 @@ static void remove_cb(GtkWidget * w G_GNUC_UNUSED, TrgMainWindow * win) _("Remove %d torrents?"), GTK_STOCK_REMOVE) == GTK_RESPONSE_ACCEPT) dispatch_async(priv->client, torrent_remove(ids, FALSE), - on_generic_interactive_action, win); + on_generic_interactive_action_response, win); else json_array_unref(ids); } @@ -1584,13 +1589,10 @@ gboolean on_delete_complete(gpointer data) trg_client_update_session(priv->client, on_session_get, response->cb_data); - return on_generic_interactive_action(data); + return on_generic_interactive_action_response(data); } -gboolean on_generic_interactive_action(gpointer data) -{ - trg_response *response = (trg_response *) data; - TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); +void on_generic_interactive_action(TrgMainWindow *win, trg_response *response) { TrgMainWindowPrivate *priv = win->priv; TrgClient *tc = priv->client; @@ -1610,6 +1612,15 @@ gboolean on_generic_interactive_action(gpointer data) } trg_response_free(response); +} + +gboolean on_generic_interactive_action_response(gpointer data) +{ + trg_response *response = (trg_response *) data; + TrgMainWindow *win = TRG_MAIN_WINDOW(response->cb_data); + + on_generic_interactive_action(win, response); + return FALSE; } @@ -1944,7 +1955,7 @@ static void set_limit_cb(GtkWidget * w, TrgMainWindow * win) json_object_set_boolean_member(args, enabledKey, speed >= 0); if (limitIds) - dispatch_async(priv->client, req, on_generic_interactive_action, + dispatch_async(priv->client, req, on_generic_interactive_action_response, win); else dispatch_async(priv->client, req, on_session_set, win); @@ -1969,7 +1980,7 @@ static void set_priority_cb(GtkWidget * w, TrgMainWindow * win) json_object_set_int_member(args, FIELD_BANDWIDTH_PRIORITY, priority); - dispatch_async(priv->client, req, on_generic_interactive_action, win); + dispatch_async(priv->client, req, on_generic_interactive_action_response, win); } static GtkWidget *limit_item_new(TrgMainWindow * win, GtkWidget * menu, diff --git a/src/trg-main-window.h b/src/trg-main-window.h index 3c6ace5..3fb69af 100644 --- a/src/trg-main-window.h +++ b/src/trg-main-window.h @@ -63,7 +63,8 @@ GType trg_main_window_get_type(void); gint trg_add_from_filename(TrgMainWindow * win, gchar ** uris); gboolean on_session_set(gpointer data); gboolean on_delete_complete(gpointer data); -gboolean on_generic_interactive_action(gpointer data); +void on_generic_interactive_action(TrgMainWindow *win, trg_response *response); +gboolean on_generic_interactive_action_response(gpointer data); void auto_connect_if_required(TrgMainWindow * win); void trg_main_window_set_start_args(TrgMainWindow * win, gchar ** args); TrgMainWindow *trg_main_window_new(TrgClient * tc, gboolean minonstart); diff --git a/src/trg-rss-model.c b/src/trg-rss-model.c index bc43ef7..12b2d2b 100644 --- a/src/trg-rss-model.c +++ b/src/trg-rss-model.c @@ -45,10 +45,8 @@ typedef struct { TrgRssModel *model; gchar *feed_id; gchar *feed_url; - gint status; - RssParser *parser; - gboolean success; GError *error; + trg_response *response; } feed_update; static void feed_update_free(feed_update *update) { @@ -58,61 +56,52 @@ static void feed_update_free(feed_update *update) { g_free(update->feed_id); g_free(update->feed_url); - if (update->parser) - g_object_unref(update->parser); - g_free(update); } -static gboolean on_rss_receive_idle(gpointer data) { - feed_update *update = (feed_update*) data; - TrgRssModel *model = update->model; - TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(model); - - if (update->success) { - RssDocument *doc = rss_parser_get_document(update->parser); - GtkTreeIter iter; - GList *list, *tmp; - gchar *title; - - list = rss_document_get_items(doc); - - for (tmp = list; tmp != NULL; tmp = tmp->next) { - RssItem *item = (RssItem*) tmp->data; - const gchar *guid = rss_item_get_guid(item); - if (g_hash_table_lookup(priv->table, guid) != (void*) 1) { - gtk_list_store_append(GTK_LIST_STORE(model), &iter); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, RSSCOL_ID, - guid, RSSCOL_TITLE, rss_item_get_title(item), - RSSCOL_LINK, rss_item_get_link(item), -1); - g_hash_table_insert(priv->table, g_strdup(guid), (void*) 1); - } - } - - g_list_free(list); - g_object_unref(doc); - } - - feed_update_free(update); - - return FALSE; -} - static gboolean on_rss_receive(gpointer data) { trg_response *response = (trg_response *) data; feed_update *update = (feed_update*) response->cb_data; - - update->status = response->status; + TrgRssModel *model = update->model; + TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(model); if (response->status == CURLE_OK) { - update->parser = rss_parser_new(); - update->success = rss_parser_load_from_data(update->parser, - response->raw, response->size, &(update->error)); - } + RssParser* parser = rss_parser_new(); + GError *error = NULL; + if (rss_parser_load_from_data(parser, response->raw, + response->size, &error)) { + RssDocument *doc = rss_parser_get_document(parser); + GtkTreeIter iter; + GList *list, *tmp; + gchar *title; + + list = rss_document_get_items(doc); + + for (tmp = list; tmp != NULL; tmp = tmp->next) { + RssItem *item = (RssItem*) tmp->data; + const gchar *guid = rss_item_get_guid(item); + if (g_hash_table_lookup(priv->table, guid) != (void*) 1) { + gtk_list_store_append(GTK_LIST_STORE(model), &iter); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, RSSCOL_ID, + guid, RSSCOL_TITLE, rss_item_get_title(item), + RSSCOL_LINK, rss_item_get_link(item), RSSCOL_FEED, + update->feed_id, RSSCOL_PUBDATE, + rss_item_get_pub_date(item), -1); + g_hash_table_insert(priv->table, g_strdup(guid), (void*) 1); + } + } - g_idle_add(on_rss_receive_idle, update); + g_list_free(list); + g_object_unref(doc); + g_object_unref(parser); + } else { + g_error_free(error); + g_message("parse error?"); + } + } trg_response_free(response); + feed_update_free(update); return FALSE; } @@ -126,7 +115,8 @@ void trg_rss_model_update(TrgRssModel * model) { if (!feeds) return; - for (li = json_array_get_elements(feeds); li != NULL; li = g_list_next(li)) { + for (li = json_array_get_elements(feeds); li != NULL; + li = g_list_next(li)) { JsonObject *feed = json_node_get_object((JsonNode *) li->data); const gchar *url = json_object_get_string_member(feed, "url"); const gchar *id = json_object_get_string_member(feed, "id"); @@ -174,11 +164,10 @@ static GObject *trg_rss_model_constructor(GType type, return obj; } -static void trg_rss_model_dispose(GObject * object) -{ +static void trg_rss_model_dispose(GObject * object) { TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(object); g_hash_table_destroy(priv->table); - G_OBJECT_CLASS(trg_rss_model_parent_class)->dispose(object); + G_OBJECT_CLASS(trg_rss_model_parent_class)->dispose(object); } static void trg_rss_model_class_init(TrgRssModelClass * klass) { @@ -199,12 +188,13 @@ static void trg_rss_model_class_init(TrgRssModelClass * klass) { } static void trg_rss_model_init(TrgRssModel * self) { - //TrgRssModelPrivate *priv = TRG_RSS_MODEL_GET_PRIVATE(self); GType column_types[RSSCOL_COLUMNS]; column_types[RSSCOL_ID] = G_TYPE_STRING; column_types[RSSCOL_TITLE] = G_TYPE_STRING; column_types[RSSCOL_LINK] = G_TYPE_STRING; + column_types[RSSCOL_FEED] = G_TYPE_STRING; + column_types[RSSCOL_PUBDATE] = G_TYPE_STRING; gtk_list_store_set_column_types(GTK_LIST_STORE(self), RSSCOL_COLUMNS, column_types); diff --git a/src/trg-rss-model.h b/src/trg-rss-model.h index 9befa48..799629a 100644 --- a/src/trg-rss-model.h +++ b/src/trg-rss-model.h @@ -57,6 +57,8 @@ enum { RSSCOL_ID, RSSCOL_TITLE, RSSCOL_LINK, + RSSCOL_FEED, + RSSCOL_PUBDATE, RSSCOL_COLUMNS }; diff --git a/src/trg-rss-window.c b/src/trg-rss-window.c index 52a096f..942dddc 100644 --- a/src/trg-rss-window.c +++ b/src/trg-rss-window.c @@ -23,7 +23,9 @@ #include "trg-rss-window.h" #include "trg-rss-model.h" +#include "trg-torrent-add-dialog.h" #include "trg-client.h" +#include "upload.h" #include "util.h" G_DEFINE_TYPE(TrgRssWindow, trg_rss_window, @@ -84,15 +86,59 @@ trg_rss_window_set_property(GObject * object, } } +static gboolean on_torrent_receive(gpointer data) { + trg_response *response = (trg_response *) data; + TrgRssWindow *win = TRG_RSS_WINDOW(response->cb_data); + TrgRssWindowPrivate *priv = TRG_RSS_WINDOW_GET_PRIVATE(response->cb_data); + TrgClient *client = priv->client; + TrgPrefs *prefs = trg_client_get_prefs(client); + TrgMainWindow *main_win = priv->parent; + + if (response->status == CURLE_OK) { + if (trg_prefs_get_bool(prefs, TRG_PREFS_KEY_ADD_OPTIONS_DIALOG, + TRG_PREFS_GLOBAL)) { + /*TrgTorrentAddDialog *dialog = + trg_torrent_add_dialog_new_from_filenames(main_win, client, + filesList); + gtk_widget_show_all(GTK_WIDGET(dialog));*/ + } else { + trg_upload *upload = g_new0(trg_upload, 1); + + upload->upload_response = response; + upload->main_window = main_win; + upload->client = client; + upload->extra_args = FALSE; + upload->flags = trg_prefs_get_add_flags(prefs); + + trg_do_upload(upload); + } + } else { + trg_error_dialog(GTK_WINDOW(win), response); + trg_response_free(response); + } + + return FALSE; +} + static void -trg_rss_window_response_cb(GtkDialog * dlg, gint res_id, - gpointer data G_GNUC_UNUSED) +rss_item_activated(GtkTreeView * treeview, + GtkTreePath * path, + GtkTreeViewColumn * + col G_GNUC_UNUSED, gpointer userdata) { - TrgRssWindowPrivate *priv = - TRG_RSS_WINDOW_GET_PRIVATE(dlg); + TrgRssWindow *win = TRG_RSS_WINDOW(userdata); + TrgRssWindowPrivate *priv = TRG_RSS_WINDOW_GET_PRIVATE(win); + GtkTreeModel *model = gtk_tree_view_get_model(treeview); + GtkTreeIter iter; + gchar *link; + + gtk_tree_model_get_iter(model, &iter, path); + + gtk_tree_model_get(model, &iter, RSSCOL_LINK, &link, -1); + + async_http_request(priv->client, link, on_torrent_receive, userdata); - gtk_widget_destroy(GTK_WIDGET(dlg)); - instance = NULL; + g_free(link); } static GObject *trg_rss_window_constructor(GType type, @@ -105,7 +151,7 @@ static GObject *trg_rss_window_constructor(GType type, TrgRssWindowPrivate *priv; TrgRssModel *model; GtkTreeView *view; - GtkWidget *vbox, *toolbar, *contentbox; + GtkWidget *vbox, *toolbar; GtkToolItem *item; object = G_OBJECT_CLASS @@ -120,10 +166,14 @@ static GObject *trg_rss_window_constructor(GType type, view = GTK_TREE_VIEW(gtk_tree_view_new()); gtk_tree_view_set_model(view, GTK_TREE_MODEL(model)); gtk_tree_view_insert_column_with_attributes(view, -1, "Title", gtk_cell_renderer_text_new(), "text", RSSCOL_TITLE, NULL); + gtk_tree_view_insert_column_with_attributes(view, -1, "Feed", gtk_cell_renderer_text_new(), "text", RSSCOL_FEED, NULL); + gtk_tree_view_insert_column_with_attributes(view, -1, "Published", gtk_cell_renderer_text_new(), "text", RSSCOL_PUBDATE, NULL); + gtk_tree_view_insert_column_with_attributes(view, -1, "URL", gtk_cell_renderer_text_new(), "text", RSSCOL_LINK, NULL); - gtk_window_set_title(GTK_WINDOW(object), _("RSS Viewer")); + g_signal_connect(view, "row-activated", + G_CALLBACK(rss_item_activated), object); - //contentbox = gtk_dialog_get_content_area(GTK_DIALOG(object)); + gtk_window_set_title(GTK_WINDOW(object), _("RSS Feeds")); toolbar = gtk_toolbar_new(); diff --git a/src/trg-torrent-add-dialog.c b/src/trg-torrent-add-dialog.c index 517797e..702efd4 100644 --- a/src/trg-torrent-add-dialog.c +++ b/src/trg-torrent-add-dialog.c @@ -45,9 +45,10 @@ #include "torrent.h" #include "json.h" #include "protocol-constants.h" +#include "upload.h" enum { - PROP_0, PROP_FILENAME, PROP_PARENT, PROP_CLIENT + PROP_0, PROP_FILENAME, PROP_PARENT, PROP_CLIENT, PROP_RESPONSE }; enum { @@ -63,6 +64,7 @@ struct _TrgTorrentAddDialogPrivate { TrgClient *client; TrgMainWindow *parent; GSList *filenames; + trg_response *response; GtkWidget *source_chooser; GtkWidget *dest_combo; GtkWidget *priority_combo; @@ -115,65 +117,6 @@ trg_torrent_add_dialog_get_property(GObject * object, } } -static void -add_set_common_args(JsonObject * args, gint priority, gchar * dir) -{ - json_object_set_string_member(args, FIELD_FILE_DOWNLOAD_DIR, dir); - json_object_set_int_member(args, FIELD_BANDWIDTH_PRIORITY, - (gint64) priority); -} - -static gpointer add_files_threadfunc(gpointer data) -{ - struct add_torrent_threadfunc_args *files_thread_data = - (struct add_torrent_threadfunc_args *) data; - - GSList *li; - - for (li = files_thread_data->list; li; li = g_slist_next(li)) { - gchar *fileName = (gchar *) li->data; - JsonNode *request = - torrent_add(fileName, files_thread_data->flags); - JsonObject *args; - trg_response *response; - - if (!request) - continue; - - args = node_get_arguments(request); - - if (files_thread_data->extraArgs) - add_set_common_args(args, files_thread_data->priority, - files_thread_data->dir); - - response = dispatch(files_thread_data->client, request); - response->cb_data = files_thread_data->cb_data; - g_idle_add(on_generic_interactive_action, response); - } - - g_str_slist_free(files_thread_data->list); - - if (files_thread_data->extraArgs) - g_free(files_thread_data->dir); - - g_free(files_thread_data); - - return NULL; -} - -void launch_add_thread(struct add_torrent_threadfunc_args *args) -{ - GError *error = NULL; - g_thread_create(add_files_threadfunc, args, FALSE, &error); - - if (error) { - g_error("thread creation error: %s", error->message); - g_error_free(error); - g_str_slist_free(args->list); - g_free(args); - } -} - static gboolean add_file_indexes_foreachfunc(GtkTreeModel * model, GtkTreePath * @@ -226,32 +169,17 @@ trg_torrent_add_response_cb(GtkDialog * dlg, gint res_id, gpointer data) trg_destination_combo_get_dir(TRG_DESTINATION_COMBO (priv->dest_combo)); - if (g_slist_length(priv->filenames) == 1) { - JsonNode *req = - torrent_add((gchar *) priv->filenames->data, flags); - if (req) { - JsonObject *args = node_get_arguments(req); - gtk_tree_model_foreach(GTK_TREE_MODEL(priv->store), - add_file_indexes_foreachfunc, args); - add_set_common_args(args, priority, dir); - dispatch_async(priv->client, req, - on_generic_interactive_action, - priv->parent); - } - g_str_slist_free(priv->filenames); - } else { - struct add_torrent_threadfunc_args *args = - g_new(struct add_torrent_threadfunc_args, 1); - args->list = priv->filenames; - args->cb_data = priv->parent; - args->client = priv->client; - args->dir = g_strdup(dir); - args->priority = priority; - args->flags = flags; - args->extraArgs = TRUE; - - launch_add_thread(args); - } + trg_upload *upload = g_new0(trg_upload, 1); + + upload->list = priv->filenames; + upload->main_window = priv->parent; + upload->client = priv->client; + upload->dir = dir; + upload->priority = priority; + upload->flags = flags; + upload->extra_args = TRUE; + + trg_do_upload(upload); trg_destination_combo_save_selection(TRG_DESTINATION_COMBO (priv->dest_combo)); @@ -867,6 +795,21 @@ trg_torrent_add_dialog_class_init(TrgTorrentAddDialogClass * klass) | G_PARAM_STATIC_BLURB)); + g_object_class_install_property(object_class, + PROP_RESPONSE, + g_param_spec_pointer("response", + "response", + "response", + G_PARAM_READWRITE + | + G_PARAM_CONSTRUCT_ONLY + | + G_PARAM_STATIC_NAME + | + G_PARAM_STATIC_NICK + | + G_PARAM_STATIC_BLURB)); + g_object_class_install_property(object_class, PROP_CLIENT, g_param_spec_pointer("client", @@ -902,7 +845,7 @@ static void trg_torrent_add_dialog_init(TrgTorrentAddDialog * self) { } -TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * parent, +TrgTorrentAddDialog *trg_torrent_add_dialog_new_from_filenames(TrgMainWindow * parent, TrgClient * client, GSList * filenames) { @@ -911,6 +854,15 @@ TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * parent, NULL); } +TrgTorrentAddDialog *trg_torrent_add_dialog_new_from_response(TrgMainWindow * parent, + TrgClient * client, + trg_response *response) +{ + return g_object_new(TRG_TYPE_TORRENT_ADD_DIALOG, "response", + response, "parent", parent, "client", client, + NULL); +} + void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client) { GtkWidget *w; @@ -937,22 +889,21 @@ void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client) prefs); if (showOptions) { - TrgTorrentAddDialog *dialog = trg_torrent_add_dialog_new(win, + TrgTorrentAddDialog *dialog = trg_torrent_add_dialog_new_from_filenames(win, client, l); gtk_widget_show_all(GTK_WIDGET(dialog)); } else { - struct add_torrent_threadfunc_args *args = - g_new0(struct add_torrent_threadfunc_args, 1); + trg_upload *upload = g_new0(trg_upload, 1); - args->list = l; - args->cb_data = win; - args->client = client; - args->extraArgs = FALSE; - args->flags = trg_prefs_get_add_flags(prefs); + upload->list = l; + upload->main_window = win; + upload->client = client; + upload->extra_args = FALSE; + upload->flags = trg_prefs_get_add_flags(prefs); - launch_add_thread(args); + trg_do_upload(upload); } } diff --git a/src/trg-torrent-add-dialog.h b/src/trg-torrent-add-dialog.h index 0f45e2c..ab6721e 100644 --- a/src/trg-torrent-add-dialog.h +++ b/src/trg-torrent-add-dialog.h @@ -46,28 +46,12 @@ typedef struct { GtkDialogClass parent_class; } TrgTorrentAddDialogClass; -/* Use synchronous dispatch() in our dedicated thread function. - * This means torrents are added in sequence, instead of dispatch_async() - * working concurrently for each upload. - */ - -struct add_torrent_threadfunc_args { - GSList *list; - TrgClient *client; - gpointer cb_data; - guint flags; - gchar *dir; - gint priority; - gboolean extraArgs; -}; - GType trg_torrent_add_dialog_get_type(void); TrgTorrentAddDialog *trg_torrent_add_dialog_new(TrgMainWindow * win, TrgClient * client, GSList * filenames); void trg_torrent_add_dialog(TrgMainWindow * win, TrgClient * client); -void launch_add_thread(struct add_torrent_threadfunc_args *args); G_END_DECLS #endif /* TRG_TORRENT_ADD_DIALOG_H_ */ diff --git a/src/trg-torrent-add-url-dialog.c b/src/trg-torrent-add-url-dialog.c index 7f6335e..8ed15d8 100644 --- a/src/trg-torrent-add-url-dialog.c +++ b/src/trg-torrent-add-url-dialog.c @@ -90,7 +90,7 @@ trg_torrent_add_url_response_cb(TrgTorrentAddUrlDialog * dlg, gint res_id, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(priv->startCheck))); dispatch_async(priv->client, request, - on_generic_interactive_action, data); + on_generic_interactive_action_response, data); } gtk_widget_destroy(GTK_WIDGET(dlg)); diff --git a/src/trg-torrent-move-dialog.c b/src/trg-torrent-move-dialog.c index 7669545..99a11fb 100644 --- a/src/trg-torrent-move-dialog.c +++ b/src/trg-torrent-move-dialog.c @@ -69,7 +69,7 @@ trg_torrent_move_response_cb(GtkDialog * dlg, gint res_id, gpointer data) trg_destination_combo_save_selection(TRG_DESTINATION_COMBO (priv->location_combo)); dispatch_async(priv->client, request, - on_generic_interactive_action, data); + on_generic_interactive_action_response, data); } else { json_array_unref(priv->ids); } diff --git a/src/trg-torrent-props-dialog.c b/src/trg-torrent-props-dialog.c index 90ef4e3..71a9c71 100644 --- a/src/trg-torrent-props-dialog.c +++ b/src/trg-torrent-props-dialog.c @@ -172,7 +172,7 @@ static void trg_torrent_props_response_cb(GtkDialog * dialog, gint res_id, trg_json_widgets_save(priv->widgets, args); trg_json_widget_desc_list_free(priv->widgets); - dispatch_async(priv->client, request, on_generic_interactive_action, + dispatch_async(priv->client, request, on_generic_interactive_action_response, priv->parent); } diff --git a/src/trg-trackers-tree-view.c b/src/trg-trackers-tree-view.c index 7ce05b7..54948f3 100644 --- a/src/trg-trackers-tree-view.c +++ b/src/trg-trackers-tree-view.c @@ -66,7 +66,7 @@ static gboolean on_trackers_update(gpointer data) trg_trackers_model_set_accept(TRG_TRACKERS_MODEL(model), TRUE); response->cb_data = priv->win; - return on_generic_interactive_action(data); + return on_generic_interactive_action_response(data); } void diff --git a/src/upload.c b/src/upload.c new file mode 100644 index 0000000..5bac869 --- /dev/null +++ b/src/upload.c @@ -0,0 +1,62 @@ +#include "protocol-constants.h" +#include "requests.h" +#include "trg-client.h" +#include "upload.h" +#include "util.h" +#include "trg-main-window.h" + +static gboolean upload_complete_callback(gpointer data); +static void next_upload(trg_upload *upload); + +static void +add_set_common_args(JsonObject * args, gint priority, gchar * dir) +{ + json_object_set_string_member(args, FIELD_FILE_DOWNLOAD_DIR, dir); + json_object_set_int_member(args, FIELD_BANDWIDTH_PRIORITY, + (gint64) priority); +} + +void trg_upload_free(trg_upload *upload) { + g_str_slist_free(upload->list); + g_free(upload->dir); + trg_response_free(upload->upload_response); + g_free(upload); +} + +static void next_upload(trg_upload *upload) { + if (upload->upload_response && upload->progress_index < 1) { + JsonNode *req = torrent_add_from_response(upload->upload_response, 0); + /*JsonObject *args = + if (upload->extra_args) + add_set_common_args()*/ + upload->progress_index++; + dispatch_async(upload->client, req, upload_complete_callback, upload); + } else if (upload->list && upload->progress_index < g_slist_length(upload->list)) { + JsonNode *req = torrent_add_from_file((gchar*)g_slist_nth_data(upload->list, upload->progress_index), 0); + upload->progress_index++; + dispatch_async(upload->client, req, upload_complete_callback, upload); + } else { + trg_upload_free(upload); + } +} + +static gboolean upload_complete_callback(gpointer data) { + trg_response *response = (trg_response*)data; + trg_upload *upload = (trg_upload*)response->cb_data; + + next_upload(upload); + + /* the callback we're delegating to will destroy the response */ + + if (upload->main_window) + on_generic_interactive_action(upload->main_window, response); + else /* otherwise need to do it here */ + trg_response_free(response); + + return FALSE; +} + +void trg_do_upload(trg_upload *upload) +{ + next_upload(upload); +} diff --git a/src/upload.h b/src/upload.h new file mode 100644 index 0000000..9f3f719 --- /dev/null +++ b/src/upload.h @@ -0,0 +1,25 @@ +#ifndef UPLOAD_H_ +#define UPLOAD_H_ + +#include + +#include "trg-client.h" +#include "trg-main-window.h" + +typedef struct { + GSList *list; // list of filenames + trg_response *upload_response; // OR: a HTTP response containing a torrent + TrgClient *client; + gpointer cb_data; + TrgMainWindow *main_window; // a parent window to attach any error dialogs to + guint flags; + gchar *dir; + gint priority; + gboolean extra_args; + guint progress_index; + +} trg_upload; + +void trg_do_upload(trg_upload *upload); + +#endif -- cgit v1.2.3