From 6e10ee3baaf7db15ce07cc8d5d2b9d5185115938 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 11 Jun 2009 14:51:21 +0000 Subject: [PATCH] (trunk gtk) #2197: Adding a torrent from a browser sometimes doesn't work --- gtk/add-dialog.c | 14 +++-- gtk/main.c | 50 +++++++++++----- gtk/tr-core-dbus.xml | 4 +- gtk/tr-core.c | 140 ++++++++++++++++++++++++++----------------- gtk/tr-core.h | 8 ++- gtk/util.c | 54 ++++++++++------- 6 files changed, 170 insertions(+), 100 deletions(-) diff --git a/gtk/add-dialog.c b/gtk/add-dialog.c index 39a5c800c..aa2829761 100644 --- a/gtk/add-dialog.c +++ b/gtk/add-dialog.c @@ -264,6 +264,7 @@ addSingleTorrentDialog( GtkWindow * parent, GtkWidget * d; GtkWidget * t; GtkWidget * l; + GtkWidget * source_chooser; struct AddData * data; uint8_t flag; GSList * list; @@ -316,14 +317,11 @@ addSingleTorrentDialog( GtkWindow * parent, ++col; w = gtk_file_chooser_button_new( _( "Select Source File" ), GTK_FILE_CHOOSER_ACTION_OPEN ); + source_chooser = w; gtk_table_attach( GTK_TABLE( t ), w, col, col + 1, row, row + 1, ~0, 0, 0, 0 ); gtk_label_set_mnemonic_widget( GTK_LABEL( l ), w ); addTorrentFilters( GTK_FILE_CHOOSER( w ) ); - if( data->filename ) - if( !gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( w ), - data->filename ) ) - g_warning( "couldn't select '%s'", data->filename ); g_signal_connect( w, "selection-changed", G_CALLBACK( sourceChanged ), data ); @@ -387,6 +385,14 @@ addSingleTorrentDialog( GtkWindow * parent, t ), w, col, col + 2, row, row + 1, GTK_FILL, 0, 0, 0 ); + /* trigger sourceChanged, either directly or indirectly, + * so that it creates the tor/gtor objects */ + w = source_chooser; + if( data->filename ) + gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( w ), data->filename ); + else + sourceChanged( GTK_FILE_CHOOSER_BUTTON( w ), data ); + gtk_box_pack_start( GTK_BOX( GTK_DIALOG( d )->vbox ), t, TRUE, TRUE, 0 ); gtk_widget_show_all( d ); return d; diff --git a/gtk/main.c b/gtk/main.c index 5a20af217..e007176ca 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -331,7 +331,6 @@ main( int argc, char ** argv ) { char * err = NULL; - struct cbdata * cbdata; GSList * argfiles; GError * gerr; gboolean didinit = FALSE; @@ -358,8 +357,6 @@ main( int argc, { NULL, 0, 0, 0, NULL, NULL, NULL } }; - cbdata = g_new0( struct cbdata, 1 ); - /* bind the gettext domain */ setlocale( LC_ALL, "" ); bindtextdomain( domain, TRANSMISSIONLOCALEDIR ); @@ -392,39 +389,51 @@ main( int argc, tr_notify_init( ); didinit = cf_init( configDir, NULL ); /* must come before actions_init */ - myUIManager = gtk_ui_manager_new ( ); - actions_init ( myUIManager, cbdata ); - gtk_ui_manager_add_ui_from_string ( myUIManager, fallback_ui_file, -1, NULL ); - gtk_ui_manager_ensure_update ( myUIManager ); - gtk_window_set_default_icon_name ( MY_NAME ); - setupsighandlers( ); /* set up handlers for fatal signals */ - /* either get a lockfile s.t. this is the one instance of - * transmission that's running, OR if there are files to - * be added, delegate that to the running instance via dbus */ didlock = cf_lock( &tr_state, &err ); argfiles = checkfilenames( argc - 1, argv + 1 ); + if( !didlock && argfiles ) { + /* We have torrents to add but there's another copy of Transmsision + * running... chances are we've been invoked from a browser, etc. + * So send the files over to the "real" copy of Transmission, and + * if that goes well, then our work is done. */ GSList * l; gboolean delegated = FALSE; + for( l = argfiles; l; l = l->next ) delegated |= gtr_dbus_add_torrent( l->data ); - if( delegated ) - err = NULL; + + if( delegated ) { + g_slist_foreach( argfiles, (GFunc)g_free, NULL ); + g_slist_free( argfiles ); + argfiles = NULL; + + if( err ) { + g_free( err ); + err = NULL; + } + } } else if( ( !didlock ) && ( tr_state == TR_LOCKFILE_ELOCK ) ) { + /* There's already another copy of Transmission running, + * so tell it to present its window to the user */ gtr_dbus_present_window( ); err = NULL; } if( didlock && ( didinit || cf_init( configDir, &err ) ) ) { + /* No other copy of Transmission running... + * so we're going to be the primary. */ + const char * str; GtkWindow * win; tr_session * session; + struct cbdata * cbdata = g_new0( struct cbdata, 1 ); /* ensure the directories are created */ if(( str = pref_string_get( PREF_KEY_DIR_WATCH ))) @@ -438,6 +447,13 @@ main( int argc, pref_int_set( TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( session ) ); cbdata->core = tr_core_new( session ); + /* init the ui manager */ + myUIManager = gtk_ui_manager_new ( ); + actions_init ( myUIManager, cbdata ); + gtk_ui_manager_add_ui_from_string ( myUIManager, fallback_ui_file, -1, NULL ); + gtk_ui_manager_ensure_update ( myUIManager ); + gtk_window_set_default_icon_name ( MY_NAME ); + /* create main window now to be a parent to any error dialogs */ win = GTK_WINDOW( tr_window_new( myUIManager, cbdata->core ) ); g_signal_connect( win, "size-allocate", G_CALLBACK( onMainWindowSizeAllocated ), cbdata ); @@ -893,7 +909,8 @@ on_main_window_focus_in( GtkWidget * widget UNUSED, { struct cbdata * cbdata = gdata; - gtk_window_set_urgency_hint( GTK_WINDOW( cbdata->wind ), FALSE ); + if( cbdata->wind ) + gtk_window_set_urgency_hint( GTK_WINDOW( cbdata->wind ), FALSE ); } #endif @@ -909,7 +926,8 @@ onAddTorrent( TrCore * core, #if GTK_CHECK_VERSION( 2, 8, 0 ) g_signal_connect( w, "focus-in-event", G_CALLBACK( on_main_window_focus_in ), cbdata ); - gtk_window_set_urgency_hint( cbdata->wind, TRUE ); + if( cbdata->wind ) + gtk_window_set_urgency_hint( cbdata->wind, TRUE ); #endif } diff --git a/gtk/tr-core-dbus.xml b/gtk/tr-core-dbus.xml index fa326ade5..ddec6b4b1 100644 --- a/gtk/tr-core-dbus.xml +++ b/gtk/tr-core-dbus.xml @@ -1,9 +1,9 @@ - + - + diff --git a/gtk/tr-core.c b/gtk/tr-core.c index 971f56378..5351e1517 100644 --- a/gtk/tr-core.c +++ b/gtk/tr-core.c @@ -852,75 +852,103 @@ tr_core_errsig( TrCore * core, g_signal_emit( core, TR_CORE_GET_CLASS( core )->errsig, 0, type, msg ); } -static void -add_filename( TrCore * core, - const char * filename, - gboolean doStart, - gboolean doPrompt ) +static int +add_ctor( TrCore * core, tr_ctor * ctor, gboolean doPrompt ) +{ + tr_info inf; + int err = tr_torrentParse( ctor, &inf ); + + switch( err ) + { + case TR_EINVALID: + break; + + case TR_EDUPLICATE: + g_message( "it's a duplicate" ); + /* don't complain about .torrent files in the watch directory + * that have already been added... that gets annoying and we + * don't want to be nagging users to clean up their watch dirs */ + if( !tr_ctorGetSourceFile(ctor) || !core->priv->adding_from_watch_dir ) + tr_core_errsig( core, err, inf.name ); + tr_metainfoFree( &inf ); + break; + + default: + if( doPrompt ) + g_signal_emit( core, TR_CORE_GET_CLASS( core )->promptsig, 0, ctor ); + else { + tr_session * session = tr_core_session( core ); + TrTorrent * gtor = tr_torrent_new_ctor( session, ctor, &err ); + g_message( "creating a gtorrent" ); + if( !err ) + tr_core_add_torrent( core, gtor ); + } + tr_metainfoFree( &inf ); + break; + } + + return err; +} + +/* invoked remotely via dbus. */ +gboolean +tr_core_add_metainfo( TrCore * core, + const char * base64_metainfo, + gboolean * setme_success, + GError ** gerr UNUSED ) { tr_session * session = tr_core_session( core ); + if( !session ) + { + *setme_success = FALSE; + } + else + { + int err; + int file_length; + tr_ctor * ctor; + char * file_contents; + gboolean do_prompt = pref_flag_get( PREF_KEY_OPTIONS_PROMPT ); + + ctor = tr_ctorNew( session ); + tr_core_apply_defaults( ctor ); + + file_contents = tr_base64_decode( base64_metainfo, -1, &file_length ); + err = tr_ctorSetMetainfo( ctor, (const uint8_t*)file_contents, file_length ); + + if( !err ) + err = add_ctor( core, ctor, do_prompt ); + + tr_free( file_contents ); + tr_core_torrents_added( core ); + *setme_success = TRUE; + } + + return TRUE; +} + +static void +add_filename( TrCore * core, + const char * filename, + gboolean doStart, + gboolean doPrompt ) +{ + tr_session * session = tr_core_session( core ); if( filename && session ) { + int err; tr_ctor * ctor = tr_ctorNew( session ); tr_core_apply_defaults( ctor ); tr_ctorSetPaused( ctor, TR_FORCE, !doStart ); + tr_ctorSetMetainfoFromFile( ctor, filename ); - if( tr_ctorSetMetainfoFromFile( ctor, filename ) ) - { + err = add_ctor( core, ctor, doPrompt ); + if( err == TR_EINVALID ) tr_core_errsig( core, TR_EINVALID, filename ); - tr_ctorFree( ctor ); - } - else - { - tr_info inf; - int err = tr_torrentParse( ctor, &inf ); - - switch( err ) - { - case TR_EINVALID: - tr_core_errsig( core, err, filename ); - break; - - case TR_EDUPLICATE: - /* don't complain about .torrent files in the watch directory - * that have already been added... that gets annoying and we - * don't want to be naggign users to clean up their watch dirs */ - if( !core->priv->adding_from_watch_dir ) - tr_core_errsig( core, err, inf.name ); - tr_metainfoFree( &inf ); - break; - - default: - if( doPrompt ) - g_signal_emit( core, TR_CORE_GET_CLASS( core )->promptsig, 0, ctor ); - else { - TrTorrent * gtor = tr_torrent_new_ctor( session, ctor, &err ); - if( err ) - tr_core_errsig( core, err, filename ); - else - tr_core_add_torrent( core, gtor ); - } - tr_metainfoFree( &inf ); - break; - } - } } } -gboolean -tr_core_add_file( TrCore * core, - const char * filename, - gboolean * success, - GError ** err UNUSED ) -{ - add_filename( core, filename, - pref_flag_get( PREF_KEY_START ), - pref_flag_get( PREF_KEY_OPTIONS_PROMPT ) ); - *success = TRUE; - return TRUE; -} - gboolean tr_core_present_window( TrCore * core UNUSED, gboolean * success, diff --git a/gtk/tr-core.h b/gtk/tr-core.h index 61970ca8a..e26e121d6 100644 --- a/gtk/tr-core.h +++ b/gtk/tr-core.h @@ -140,8 +140,12 @@ void tr_core_add_list( TrCore * self, tr_core_add_list( c, l, PREF_FLAG_DEFAULT, PREF_FLAG_DEFAULT ) -/** Add a torrent. */ -gboolean tr_core_add_file( TrCore*, const char * filename, gboolean * setme_success, GError ** err ); +/** @brief Add a torrent. */ +gboolean tr_core_add_metainfo( TrCore * core, + const char * base64_metainfo, + gboolean * setme_success, + GError ** err ); + /** Add a torrent. */ void tr_core_add_torrent( TrCore*, TrTorrent* ); diff --git a/gtk/util.c b/gtk/util.c index b8432bdaf..cacd7ecbf 100644 --- a/gtk/util.c +++ b/gtk/util.c @@ -581,29 +581,43 @@ gtr_open_file( const char * path ) gboolean gtr_dbus_add_torrent( const char * filename ) { - static gboolean success = FALSE; - + /* FIXME: why is this static? */ + static gboolean success = FALSE; #ifdef HAVE_DBUS_GLIB - DBusGProxy * proxy = NULL; - GError * err = NULL; + DBusGProxy * proxy = NULL; + GError * err = NULL; DBusGConnection * conn; - if( ( conn = dbus_g_bus_get( DBUS_BUS_SESSION, &err ) ) ) - proxy = dbus_g_proxy_new_for_name ( conn, VALUE_SERVICE_NAME, - VALUE_SERVICE_OBJECT_PATH, - VALUE_SERVICE_INTERFACE ); - else if( err ) - g_message( "err: %s", err->message ); - if( proxy ) - dbus_g_proxy_call( proxy, "AddFile", &err, - G_TYPE_STRING, filename, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &success, - G_TYPE_INVALID ); - if( err ) - g_message( "err: %s", err->message ); + char * file_contents; + gsize file_length; + + if( g_file_get_contents( filename, &file_contents, &file_length, NULL ) ) + { + char * b64 = tr_base64_encode( file_contents, file_length, NULL ); + if(( conn = dbus_g_bus_get( DBUS_BUS_SESSION, &err ))) + proxy = dbus_g_proxy_new_for_name (conn, VALUE_SERVICE_NAME, + VALUE_SERVICE_OBJECT_PATH, + VALUE_SERVICE_INTERFACE ); + else if( err ) + g_message( "err: %s", err->message ); + if( proxy ) + dbus_g_proxy_call( proxy, "AddMetainfo", &err, + G_TYPE_STRING, b64, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &success, + G_TYPE_INVALID ); + if( err ) + g_message( "err: %s", err->message ); + + if( proxy ) + g_object_unref( proxy ); + if( conn ) + dbus_g_connection_unref( conn ); + + tr_free( b64 ); + g_free( file_contents ); + } + else g_message( "couldn't read %s", filename ); - g_object_unref( proxy ); - dbus_g_connection_unref( conn ); #endif return success; }