mirror of
https://github.com/transmission/transmission.git
synced 2026-05-08 09:39:08 +01:00
(trunk gtk) first cut at using GApplication. This lets glib replace hundreds of lines of homegrown code. Whee!
This commit is contained in:
+3
-88
@@ -44,96 +44,11 @@
|
||||
#define MY_READABLE_NAME "transmission-gtk"
|
||||
|
||||
static char * gl_confdir = NULL;
|
||||
static char * gl_lockpath = NULL;
|
||||
|
||||
/* errstr may be NULL, this might be called before GTK is initialized */
|
||||
gboolean
|
||||
cf_init( const char * configDir, char ** errstr )
|
||||
void
|
||||
gtr_pref_init( const char * config_dir )
|
||||
{
|
||||
if( errstr != NULL )
|
||||
*errstr = NULL;
|
||||
|
||||
gl_confdir = g_strdup( configDir );
|
||||
|
||||
if( g_file_test( gl_confdir, G_FILE_TEST_IS_DIR ) )
|
||||
return true;
|
||||
|
||||
if( g_mkdir_with_parents( gl_confdir, 0755 ) )
|
||||
return true;
|
||||
|
||||
if( errstr != NULL )
|
||||
*errstr = g_strdup_printf( _( "Couldn't create \"%1$s\": %2$s" ),
|
||||
gl_confdir, g_strerror( errno ) );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
**** Lockfile
|
||||
****
|
||||
***/
|
||||
|
||||
/* errstr may be NULL, this might be called before GTK is initialized */
|
||||
static gboolean
|
||||
lockfile( const char * filename, gtr_lockfile_state_t * tr_state, char ** errstr )
|
||||
{
|
||||
const gtr_lockfile_state_t state = gtr_lockfile( filename );
|
||||
const gboolean success = state == GTR_LOCKFILE_SUCCESS;
|
||||
|
||||
if( errstr ) switch( state )
|
||||
{
|
||||
case GTR_LOCKFILE_EOPEN:
|
||||
*errstr =
|
||||
g_strdup_printf( _( "Couldn't open \"%1$s\": %2$s" ),
|
||||
filename, g_strerror( errno ) );
|
||||
break;
|
||||
|
||||
case GTR_LOCKFILE_ELOCK:
|
||||
*errstr = g_strdup_printf( _( "%s is already running." ),
|
||||
g_get_application_name( ) );
|
||||
break;
|
||||
|
||||
case GTR_LOCKFILE_SUCCESS:
|
||||
*errstr = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if( tr_state != NULL )
|
||||
*tr_state = state;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static char*
|
||||
getLockFilename( void )
|
||||
{
|
||||
g_assert( gl_confdir != NULL );
|
||||
return g_build_filename( gl_confdir, "lock", NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
cf_removelocks( void )
|
||||
{
|
||||
if( gl_lockpath )
|
||||
{
|
||||
g_unlink( gl_lockpath );
|
||||
g_free( gl_lockpath );
|
||||
}
|
||||
}
|
||||
|
||||
/* errstr may be NULL, this might be called before GTK is initialized */
|
||||
gboolean
|
||||
cf_lock( gtr_lockfile_state_t * tr_state, char ** errstr )
|
||||
{
|
||||
char * path = getLockFilename( );
|
||||
const gboolean didLock = lockfile( path, tr_state, errstr );
|
||||
|
||||
if( didLock )
|
||||
gl_lockpath = g_strdup( path );
|
||||
g_atexit( cf_removelocks );
|
||||
g_free( path );
|
||||
return didLock;
|
||||
gl_confdir = g_strdup( config_dir );
|
||||
}
|
||||
|
||||
/***
|
||||
|
||||
+3
-10
@@ -26,8 +26,9 @@
|
||||
#define GTR_CONFIG_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <libtransmission/transmission.h>
|
||||
#include "util.h" /* gtr_lockfile */
|
||||
#include <libtransmission/transmission.h> /* tr_benc, tr_session */
|
||||
|
||||
void gtr_pref_init ( const char * config_dir );
|
||||
|
||||
int64_t gtr_pref_int_get ( const char * key );
|
||||
void gtr_pref_int_set ( const char * key, int64_t value );
|
||||
@@ -44,12 +45,4 @@ void gtr_pref_string_set ( const char * key, const char * val
|
||||
void gtr_pref_save ( tr_session * );
|
||||
struct tr_benc* gtr_pref_get_all ( void );
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
||||
gboolean cf_init( const char *confdir, char ** errstr );
|
||||
|
||||
gboolean cf_lock( gtr_lockfile_state_t * tr_state, char ** errstr );
|
||||
|
||||
#endif /* GTR_CONFIG_H */
|
||||
|
||||
+165
-258
@@ -73,7 +73,10 @@ static const char * LICENSE =
|
||||
|
||||
struct cbdata
|
||||
{
|
||||
char * config_dir;
|
||||
gboolean start_paused;
|
||||
gboolean is_iconified;
|
||||
|
||||
guint timer;
|
||||
guint update_model_soon_tag;
|
||||
guint refresh_actions_tag;
|
||||
@@ -348,11 +351,7 @@ on_selection_changed( GtkTreeSelection * s UNUSED, gpointer gdata )
|
||||
****
|
||||
***/
|
||||
|
||||
static void app_setup( TrWindow * wind,
|
||||
GSList * torrent_files,
|
||||
struct cbdata * cbdata,
|
||||
gboolean paused,
|
||||
gboolean minimized );
|
||||
static void app_setup( TrWindow * wind, struct cbdata * cbdata );
|
||||
|
||||
static void main_window_setup( struct cbdata * cbdata, TrWindow * wind );
|
||||
|
||||
@@ -560,240 +559,181 @@ signal_handler( int sig )
|
||||
}
|
||||
}
|
||||
|
||||
/****
|
||||
*****
|
||||
*****
|
||||
****/
|
||||
|
||||
static void
|
||||
setupsighandlers( void )
|
||||
on_startup( GApplication * application, gpointer user_data )
|
||||
{
|
||||
const char * str;
|
||||
GtkWindow * win;
|
||||
GtkUIManager * ui_manager;
|
||||
tr_session * session;
|
||||
struct cbdata * cbdata = user_data;
|
||||
|
||||
signal( SIGINT, signal_handler );
|
||||
signal( SIGKILL, signal_handler );
|
||||
|
||||
sighandler_cbdata = cbdata;
|
||||
|
||||
/* ensure the directories are created */
|
||||
if(( str = gtr_pref_string_get( TR_PREFS_KEY_DOWNLOAD_DIR )))
|
||||
g_mkdir_with_parents( str, 0777 );
|
||||
if(( str = gtr_pref_string_get( TR_PREFS_KEY_INCOMPLETE_DIR )))
|
||||
g_mkdir_with_parents( str, 0777 );
|
||||
|
||||
/* initialize the libtransmission session */
|
||||
session = tr_sessionInit( "gtk", cbdata->config_dir, TRUE, gtr_pref_get_all( ) );
|
||||
|
||||
gtr_pref_flag_set( TR_PREFS_KEY_ALT_SPEED_ENABLED, tr_sessionUsesAltSpeed( session ) );
|
||||
gtr_pref_int_set( TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( session ) );
|
||||
cbdata->core = gtr_core_new( session );
|
||||
|
||||
/* init the ui manager */
|
||||
ui_manager = gtk_ui_manager_new ( );
|
||||
gtr_actions_init ( ui_manager, cbdata );
|
||||
gtk_ui_manager_add_ui_from_string ( ui_manager, fallback_ui_file, -1, NULL );
|
||||
gtk_ui_manager_ensure_update ( ui_manager );
|
||||
|
||||
/* create main window now to be a parent to any error dialogs */
|
||||
win = GTK_WINDOW( gtr_window_new( ui_manager, cbdata->core ) );
|
||||
g_signal_connect( win, "size-allocate", G_CALLBACK( on_main_window_size_allocated ), cbdata );
|
||||
g_application_hold( application );
|
||||
g_object_weak_ref( G_OBJECT( win ), (GWeakNotify)g_application_release, application );
|
||||
app_setup( win, cbdata );
|
||||
tr_sessionSetRPCCallback( session, on_rpc_changed, cbdata );
|
||||
|
||||
/* check & see if it's time to update the blocklist */
|
||||
if( gtr_pref_flag_get( TR_PREFS_KEY_BLOCKLIST_ENABLED ) ) {
|
||||
if( gtr_pref_flag_get( PREF_KEY_BLOCKLIST_UPDATES_ENABLED ) ) {
|
||||
const int64_t last_time = gtr_pref_int_get( "blocklist-date" );
|
||||
const int SECONDS_IN_A_WEEK = 7 * 24 * 60 * 60;
|
||||
const time_t now = time( NULL );
|
||||
if( last_time + SECONDS_IN_A_WEEK < now )
|
||||
gtr_core_blocklist_update( cbdata->core );
|
||||
}
|
||||
}
|
||||
|
||||
/* if there's no magnet link handler registered, register us */
|
||||
register_magnet_link_handler( );
|
||||
}
|
||||
|
||||
static void
|
||||
on_activate( GApplication * app UNUSED, gpointer unused UNUSED )
|
||||
{
|
||||
gtr_action_activate( "present-main-window" );
|
||||
}
|
||||
|
||||
static void
|
||||
open_files( GSList * files, gpointer gdata )
|
||||
{
|
||||
struct cbdata * cbdata = gdata;
|
||||
const gboolean do_start = gtr_pref_flag_get( TR_PREFS_KEY_START ) && !cbdata->start_paused;
|
||||
const gboolean do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
|
||||
const gboolean do_notify = TRUE;
|
||||
|
||||
gtr_core_add_files( cbdata->core, files, do_start, do_prompt, do_notify );
|
||||
}
|
||||
|
||||
static void
|
||||
on_open (GApplication * application UNUSED,
|
||||
GFile ** f,
|
||||
gint file_count,
|
||||
gchar * hint UNUSED,
|
||||
gpointer gdata )
|
||||
{
|
||||
int i;
|
||||
GSList * files = NULL;
|
||||
|
||||
for( i=0; i<file_count; ++i )
|
||||
files = g_slist_append( files, f[i] );
|
||||
|
||||
open_files( files, gdata );
|
||||
|
||||
g_slist_free( files );
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static GSList *
|
||||
checkfilenames( int argc, char **argv )
|
||||
{
|
||||
int i;
|
||||
GSList * ret = NULL;
|
||||
char * pwd = g_get_current_dir( );
|
||||
|
||||
for( i=0; i<argc; ++i )
|
||||
{
|
||||
const char * arg = argv[i];
|
||||
|
||||
if( gtr_is_supported_url( arg ) || gtr_is_magnet_link( arg ) )
|
||||
{
|
||||
ret = g_slist_prepend( ret, g_strdup( arg ) );
|
||||
}
|
||||
else /* local file */
|
||||
{
|
||||
char * filename;
|
||||
|
||||
if( g_path_is_absolute( arg ) )
|
||||
filename = g_strdup( arg );
|
||||
else {
|
||||
filename = g_filename_from_uri( arg, NULL, NULL );
|
||||
|
||||
if( filename == NULL )
|
||||
filename = g_build_filename( pwd, arg, NULL );
|
||||
}
|
||||
|
||||
if( g_file_test( filename, G_FILE_TEST_EXISTS ) )
|
||||
ret = g_slist_prepend( ret, filename );
|
||||
else {
|
||||
if( gtr_is_hex_hashcode( argv[i] ) )
|
||||
ret = g_slist_prepend( ret, g_strdup_printf( "magnet:?xt=urn:btih:%s", argv[i] ) );
|
||||
g_free( filename );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_free( pwd );
|
||||
return g_slist_reverse( ret );
|
||||
}
|
||||
|
||||
/****
|
||||
*****
|
||||
*****
|
||||
****/
|
||||
|
||||
int
|
||||
main( int argc, char ** argv )
|
||||
{
|
||||
char * err = NULL;
|
||||
GSList * argfiles;
|
||||
GError * gerr;
|
||||
gboolean didinit = FALSE;
|
||||
gboolean didlock = FALSE;
|
||||
gboolean showversion = FALSE;
|
||||
gboolean startpaused = FALSE;
|
||||
gboolean startminimized = FALSE;
|
||||
const char * domain = MY_READABLE_NAME;
|
||||
char * configDir = NULL;
|
||||
gtr_lockfile_state_t tr_state;
|
||||
int ret;
|
||||
struct stat sb;
|
||||
char * application_id;
|
||||
GApplication * app;
|
||||
GOptionContext * option_context;
|
||||
bool show_version = false;
|
||||
GError * error = NULL;
|
||||
struct cbdata cbdata;
|
||||
|
||||
GOptionEntry entries[] = {
|
||||
{ "paused", 'p', 0, G_OPTION_ARG_NONE,
|
||||
&startpaused, _( "Start with all torrents paused" ), NULL },
|
||||
{ "version", '\0', 0, G_OPTION_ARG_NONE,
|
||||
&showversion, _( "Show version number and exit" ), NULL },
|
||||
{ "minimized", 'm', 0, G_OPTION_ARG_NONE,
|
||||
&startminimized,
|
||||
_( "Start minimized in notification area" ), NULL },
|
||||
{ "config-dir", 'g', 0, G_OPTION_ARG_FILENAME, &configDir,
|
||||
_( "Where to look for configuration files" ), NULL },
|
||||
GOptionEntry option_entries[] = {
|
||||
{ "config-dir", 'g', 0, G_OPTION_ARG_FILENAME, &cbdata.config_dir, _( "Where to look for configuration files" ), NULL },
|
||||
{ "paused", 'p', 0, G_OPTION_ARG_NONE, &cbdata.start_paused, _( "Start with all torrents paused" ), NULL },
|
||||
{ "minimized", 'm', 0, G_OPTION_ARG_NONE, &cbdata.is_iconified, _( "Start minimized in notification area" ), NULL },
|
||||
{ "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, _( "Show version number and exit" ), NULL },
|
||||
{ NULL, 0, 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/* bind the gettext domain */
|
||||
/* default settings */
|
||||
memset( &cbdata, 0, sizeof( struct cbdata ) );
|
||||
cbdata.config_dir = (char*) tr_getDefaultConfigDir( MY_CONFIG_NAME );
|
||||
|
||||
/* init i18n */
|
||||
setlocale( LC_ALL, "" );
|
||||
bindtextdomain( domain, TRANSMISSIONLOCALEDIR );
|
||||
bind_textdomain_codeset( domain, "UTF-8" );
|
||||
textdomain( domain );
|
||||
g_set_application_name( _( "Transmission" ) );
|
||||
tr_formatter_mem_init( mem_K, _(mem_K_str), _(mem_M_str), _(mem_G_str), _(mem_T_str) );
|
||||
tr_formatter_size_init( disk_K, _(disk_K_str), _(disk_M_str), _(disk_G_str), _(disk_T_str) );
|
||||
tr_formatter_speed_init( speed_K, _(speed_K_str), _(speed_M_str), _(speed_G_str), _(speed_T_str) );
|
||||
bindtextdomain( MY_READABLE_NAME, TRANSMISSIONLOCALEDIR );
|
||||
bind_textdomain_codeset( MY_READABLE_NAME, "UTF-8" );
|
||||
textdomain( MY_READABLE_NAME );
|
||||
|
||||
/* initialize gtk */
|
||||
if( !g_thread_supported( ) )
|
||||
g_thread_init( NULL );
|
||||
/* init glib/gtk */
|
||||
g_thread_init (NULL);
|
||||
g_type_init ();
|
||||
gtk_init (&argc, &argv);
|
||||
g_set_application_name (_( "Transmission" ));
|
||||
gtk_window_set_default_icon_name (MY_CONFIG_NAME);
|
||||
|
||||
gerr = NULL;
|
||||
if( !gtk_init_with_args( &argc, &argv, (char*)_( "[torrent files or urls]" ), entries,
|
||||
(char*)domain, &gerr ) )
|
||||
{
|
||||
fprintf( stderr, "%s\n", gerr->message );
|
||||
g_clear_error( &gerr );
|
||||
return 0;
|
||||
|
||||
/* parse the command line */
|
||||
option_context = g_option_context_new( _( "[torrent files or urls]" ) );
|
||||
g_option_context_add_main_entries( option_context, option_entries, GETTEXT_PACKAGE );
|
||||
g_option_context_set_translation_domain( option_context, GETTEXT_PACKAGE );
|
||||
if( !g_option_context_parse( option_context, &argc, &argv, &error ) ) {
|
||||
g_print (_("%s\nRun '%s --help' to see a full list of available command line options.\n"), error->message, argv[0]);
|
||||
g_error_free (error);
|
||||
g_option_context_free (option_context);
|
||||
return 1;
|
||||
}
|
||||
g_option_context_free (option_context);
|
||||
|
||||
if( showversion )
|
||||
{
|
||||
/* handle the trivial "version" option */
|
||||
if( show_version ) {
|
||||
fprintf( stderr, "%s %s\n", MY_READABLE_NAME, LONG_VERSION_STRING );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( configDir == NULL )
|
||||
configDir = (char*) tr_getDefaultConfigDir( MY_CONFIG_NAME );
|
||||
/* init the unit formatters */
|
||||
tr_formatter_mem_init( mem_K, _(mem_K_str), _(mem_M_str), _(mem_G_str), _(mem_T_str) );
|
||||
tr_formatter_size_init( disk_K, _(disk_K_str), _(disk_M_str), _(disk_G_str), _(disk_T_str) );
|
||||
tr_formatter_speed_init( speed_K, _(speed_K_str), _(speed_M_str), _(speed_G_str), _(speed_T_str) );
|
||||
|
||||
didinit = cf_init( configDir, NULL ); /* must come before actions_init */
|
||||
/* set up the config dir */
|
||||
gtr_pref_init( cbdata.config_dir );
|
||||
g_mkdir_with_parents( cbdata.config_dir, 0755 );
|
||||
|
||||
setupsighandlers( ); /* set up handlers for fatal signals */
|
||||
|
||||
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;
|
||||
const gboolean trash_originals = gtr_pref_flag_get( TR_PREFS_KEY_TRASH_ORIGINAL );
|
||||
|
||||
for( l=argfiles; l!=NULL; l=l->next )
|
||||
{
|
||||
const char * filename = l->data;
|
||||
const gboolean added = gtr_dbus_add_torrent( filename );
|
||||
|
||||
if( added && trash_originals )
|
||||
gtr_file_trash_or_remove( filename );
|
||||
|
||||
delegated |= added;
|
||||
}
|
||||
|
||||
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 == GTR_LOCKFILE_ELOCK ) )
|
||||
{
|
||||
/* There's already another copy of Transmission running,
|
||||
* so tell it to present its window to the user */
|
||||
err = NULL;
|
||||
if( !gtr_dbus_present_window( ) )
|
||||
err = g_strdup( _( "Transmission is already running, but is not responding. To start a new session, you must first close the existing Transmission process." ) );
|
||||
}
|
||||
|
||||
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;
|
||||
GtkUIManager * myUIManager;
|
||||
tr_session * session;
|
||||
struct cbdata * cbdata = g_new0( struct cbdata, 1 );
|
||||
|
||||
sighandler_cbdata = cbdata;
|
||||
|
||||
/* ensure the directories are created */
|
||||
if(( str = gtr_pref_string_get( TR_PREFS_KEY_DOWNLOAD_DIR )))
|
||||
g_mkdir_with_parents( str, 0777 );
|
||||
if(( str = gtr_pref_string_get( TR_PREFS_KEY_INCOMPLETE_DIR )))
|
||||
g_mkdir_with_parents( str, 0777 );
|
||||
|
||||
/* initialize the libtransmission session */
|
||||
session = tr_sessionInit( "gtk", configDir, TRUE, gtr_pref_get_all( ) );
|
||||
|
||||
gtr_pref_flag_set( TR_PREFS_KEY_ALT_SPEED_ENABLED, tr_sessionUsesAltSpeed( session ) );
|
||||
gtr_pref_int_set( TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( session ) );
|
||||
cbdata->core = gtr_core_new( session );
|
||||
|
||||
/* init the ui manager */
|
||||
myUIManager = gtk_ui_manager_new ( );
|
||||
gtr_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_CONFIG_NAME );
|
||||
|
||||
/* create main window now to be a parent to any error dialogs */
|
||||
win = GTK_WINDOW( gtr_window_new( myUIManager, cbdata->core ) );
|
||||
g_signal_connect( win, "size-allocate", G_CALLBACK( on_main_window_size_allocated ), cbdata );
|
||||
|
||||
app_setup( win, argfiles, cbdata, startpaused, startminimized );
|
||||
tr_sessionSetRPCCallback( session, on_rpc_changed, cbdata );
|
||||
|
||||
/* on startup, check & see if it's time to update the blocklist */
|
||||
if( gtr_pref_flag_get( TR_PREFS_KEY_BLOCKLIST_ENABLED ) ) {
|
||||
if( gtr_pref_flag_get( PREF_KEY_BLOCKLIST_UPDATES_ENABLED ) ) {
|
||||
const int64_t last_time = gtr_pref_int_get( "blocklist-date" );
|
||||
const int SECONDS_IN_A_WEEK = 7 * 24 * 60 * 60;
|
||||
const time_t now = time( NULL );
|
||||
if( last_time + SECONDS_IN_A_WEEK < now )
|
||||
gtr_core_blocklist_update( cbdata->core );
|
||||
}
|
||||
}
|
||||
|
||||
/* if there's no magnet link handler registered, register us */
|
||||
register_magnet_link_handler( );
|
||||
|
||||
gtk_main( );
|
||||
}
|
||||
else if( err )
|
||||
{
|
||||
const char * primary_text = _( "Transmission cannot be started." );
|
||||
GtkWidget * w = gtk_message_dialog_new( NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, primary_text, NULL );
|
||||
gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( w ), "%s", err );
|
||||
g_signal_connect( w, "response", G_CALLBACK(gtk_main_quit), NULL );
|
||||
gtk_widget_show( w );
|
||||
g_free( err );
|
||||
gtk_main( );
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* init the application for the specified config dir */
|
||||
stat( cbdata.config_dir, &sb );
|
||||
application_id = g_strdup_printf( "com.transmissionbt.transmission_%lu_%lu", (unsigned long)sb.st_dev, (unsigned long)sb.st_ino );
|
||||
app = g_application_new( application_id, G_APPLICATION_HANDLES_OPEN );
|
||||
g_signal_connect( app, "open", G_CALLBACK(on_open), &cbdata );
|
||||
g_signal_connect( app, "startup", G_CALLBACK(on_startup), &cbdata );
|
||||
g_signal_connect( app, "activate", G_CALLBACK(on_activate), &cbdata );
|
||||
ret = g_application_run (app, argc, argv);
|
||||
g_object_unref( app );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -803,19 +743,9 @@ on_core_busy( TrCore * core UNUSED, gboolean busy, struct cbdata * c )
|
||||
}
|
||||
|
||||
static void
|
||||
app_setup( TrWindow * wind,
|
||||
GSList * files,
|
||||
struct cbdata * cbdata,
|
||||
gboolean pause_all,
|
||||
gboolean is_iconified )
|
||||
app_setup( TrWindow * wind, struct cbdata * cbdata )
|
||||
{
|
||||
const gboolean do_start = gtr_pref_flag_get( TR_PREFS_KEY_START ) && !pause_all;
|
||||
const gboolean do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
|
||||
const gboolean do_notify = TRUE;
|
||||
|
||||
cbdata->is_iconified = is_iconified;
|
||||
|
||||
if( is_iconified )
|
||||
if( cbdata->is_iconified )
|
||||
gtr_pref_flag_set( PREF_KEY_SHOW_TRAY_ICON, TRUE );
|
||||
|
||||
gtr_actions_set_core( cbdata->core );
|
||||
@@ -827,9 +757,7 @@ app_setup( TrWindow * wind,
|
||||
g_signal_connect( cbdata->core, "prefs-changed", G_CALLBACK( on_prefs_changed ), cbdata );
|
||||
|
||||
/* add torrents from command-line and saved state */
|
||||
gtr_core_load( cbdata->core, pause_all );
|
||||
gtr_core_add_list( cbdata->core, files, do_start, do_prompt, do_notify );
|
||||
files = NULL;
|
||||
gtr_core_load( cbdata->core, cbdata->start_paused );
|
||||
gtr_core_torrents_added( cbdata->core );
|
||||
|
||||
/* set up main window */
|
||||
@@ -843,7 +771,7 @@ app_setup( TrWindow * wind,
|
||||
update_model_once( cbdata );
|
||||
|
||||
/* either show the window or iconify it */
|
||||
if( !is_iconified )
|
||||
if( !cbdata->is_iconified )
|
||||
gtk_widget_show( GTK_WIDGET( wind ) );
|
||||
else
|
||||
{
|
||||
@@ -954,40 +882,22 @@ on_drag_data_received( GtkWidget * widget UNUSED,
|
||||
guint time_,
|
||||
gpointer gdata )
|
||||
{
|
||||
int i;
|
||||
gboolean success = FALSE;
|
||||
GSList * files = NULL;
|
||||
struct cbdata * data = gdata;
|
||||
guint i;
|
||||
char ** uris = gtk_selection_data_get_uris( selection_data );
|
||||
const guint file_count = g_strv_length( uris );
|
||||
GSList * files = NULL;
|
||||
|
||||
/* try to add the filename URIs... */
|
||||
for( i=0; uris && uris[i]; ++i )
|
||||
{
|
||||
const char * uri = uris[i];
|
||||
char * filename = g_filename_from_uri( uri, NULL, NULL );
|
||||
for( i=0; i<file_count; ++i )
|
||||
files = g_slist_append( files, g_file_new_for_uri( uris[i] ) );
|
||||
|
||||
if( filename && g_file_test( filename, G_FILE_TEST_EXISTS ) )
|
||||
{
|
||||
files = g_slist_append( files, g_strdup( filename ) );
|
||||
success = TRUE;
|
||||
}
|
||||
else if( tr_urlIsValid( uri, -1 ) || gtr_is_magnet_link( uri ) )
|
||||
{
|
||||
gtr_core_add_from_url( data->core, uri );
|
||||
success = TRUE;
|
||||
}
|
||||
|
||||
g_free( filename );
|
||||
}
|
||||
|
||||
if( files )
|
||||
gtr_core_add_list_defaults( data->core, g_slist_reverse( files ), TRUE );
|
||||
|
||||
gtr_core_torrents_added( data->core );
|
||||
gtk_drag_finish( drag_context, success, FALSE, time_ );
|
||||
open_files( files, gdata );
|
||||
|
||||
/* cleanup */
|
||||
g_slist_foreach( files, (GFunc)g_object_unref, NULL );
|
||||
g_slist_free( files );
|
||||
g_strfreev( uris );
|
||||
|
||||
gtk_drag_finish( drag_context, true, FALSE, time_ );
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1037,9 +947,6 @@ on_session_closed( gpointer gdata )
|
||||
g_slist_free( cbdata->error_list );
|
||||
g_slist_foreach( cbdata->duplicates_list, (GFunc)g_free, NULL );
|
||||
g_slist_free( cbdata->duplicates_list );
|
||||
g_free( cbdata );
|
||||
|
||||
gtk_main_quit( );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+14
-22
@@ -23,6 +23,7 @@
|
||||
#include "hig.h"
|
||||
#include "open-dialog.h"
|
||||
#include "tr-prefs.h"
|
||||
#include "util.h" /* gtr_priority_combo_get_value() */
|
||||
|
||||
/****
|
||||
*****
|
||||
@@ -403,12 +404,14 @@ onOpenDialogResponse( GtkDialog * dialog, int response, gpointer core )
|
||||
GtkFileChooser * chooser = GTK_FILE_CHOOSER( dialog );
|
||||
GtkWidget * w = gtk_file_chooser_get_extra_widget( chooser );
|
||||
GtkToggleButton * tb = GTK_TOGGLE_BUTTON( w );
|
||||
const gboolean doStart = gtr_pref_flag_get( TR_PREFS_KEY_START );
|
||||
const gboolean doPrompt = gtk_toggle_button_get_active( tb );
|
||||
const gboolean doNotify = FALSE;
|
||||
GSList * l = gtk_file_chooser_get_filenames( chooser );
|
||||
const gboolean do_start = gtr_pref_flag_get( TR_PREFS_KEY_START );
|
||||
const gboolean do_prompt = gtk_toggle_button_get_active( tb );
|
||||
const gboolean do_notify = FALSE;
|
||||
GSList * files = gtk_file_chooser_get_files( chooser );
|
||||
|
||||
gtr_core_add_list( core, l, doStart, doPrompt, doNotify );
|
||||
gtr_core_add_files( core, files, do_start, do_prompt, do_notify );
|
||||
g_slist_foreach( files, (GFunc)g_object_unref, NULL );
|
||||
g_slist_free( files );
|
||||
}
|
||||
|
||||
gtk_widget_destroy( GTK_WIDGET( dialog ) );
|
||||
@@ -453,7 +456,7 @@ gtr_torrent_open_from_file_dialog_new( GtkWindow * parent, TrCore * core )
|
||||
static void
|
||||
onOpenURLResponse( GtkDialog * dialog, int response, gpointer user_data )
|
||||
{
|
||||
gboolean destroy = TRUE;
|
||||
bool handled = false;
|
||||
|
||||
if( response == GTK_RESPONSE_ACCEPT )
|
||||
{
|
||||
@@ -461,26 +464,15 @@ onOpenURLResponse( GtkDialog * dialog, int response, gpointer user_data )
|
||||
char * url = g_strdup( gtk_entry_get_text( GTK_ENTRY( e ) ) );
|
||||
g_strstrip( url );
|
||||
|
||||
if( url && *url )
|
||||
{
|
||||
TrCore * core = user_data;
|
||||
|
||||
if( gtr_is_supported_url( url ) || gtr_is_magnet_link( url )
|
||||
|| gtr_is_hex_hashcode( url ) )
|
||||
{
|
||||
gtr_core_add_from_url( core, url );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( url ) {
|
||||
handled = gtr_core_add_from_url( user_data, url );
|
||||
if( !handled )
|
||||
gtr_unrecognized_url_dialog( GTK_WIDGET( dialog ), url );
|
||||
destroy = FALSE;
|
||||
}
|
||||
g_free( url );
|
||||
}
|
||||
|
||||
g_free( url );
|
||||
}
|
||||
|
||||
if( destroy )
|
||||
if( handled )
|
||||
gtk_widget_destroy( GTK_WIDGET( dialog ) );
|
||||
}
|
||||
|
||||
|
||||
+117
-255
@@ -78,8 +78,6 @@ struct TrCorePrivate
|
||||
gboolean have_inhibit_cookie;
|
||||
gboolean dbus_error;
|
||||
guint inhibit_cookie;
|
||||
guint dbus_session_owner_id;
|
||||
guint dbus_display_owner_id;
|
||||
gint busy_count;
|
||||
GtkTreeModel * raw_model;
|
||||
GtkTreeModel * sorted_model;
|
||||
@@ -192,108 +190,6 @@ gtr_core_class_init( gpointer g_class, gpointer g_class_data UNUSED )
|
||||
1, G_TYPE_STRING );
|
||||
}
|
||||
|
||||
static void
|
||||
handle_dbus_method( GDBusConnection * connection UNUSED,
|
||||
const gchar * sender UNUSED,
|
||||
const gchar * object_path,
|
||||
const gchar * interface_name,
|
||||
const gchar * method_name,
|
||||
GVariant * parameters,
|
||||
GDBusMethodInvocation * invocation,
|
||||
gpointer core )
|
||||
{
|
||||
gboolean handled = false;
|
||||
|
||||
if( !g_strcmp0( interface_name, TR_DBUS_SESSION_INTERFACE ) )
|
||||
{
|
||||
if( !g_strcmp0( method_name, "TorrentAdd" ) )
|
||||
{
|
||||
GVariant * args = g_variant_get_child_value( parameters, 0 );
|
||||
GVariant * filename_variant = g_variant_lookup_value ( args, "filename", G_VARIANT_TYPE_STRING );
|
||||
char * filename = g_variant_dup_string( filename_variant, NULL );
|
||||
GSList * files = g_slist_append( NULL, filename );
|
||||
gtr_core_add_list_defaults( TR_CORE( core ), files, TRUE );
|
||||
g_dbus_method_invocation_return_value( invocation, g_variant_new( "(b)", true ) );
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
else if( !g_strcmp0( interface_name, TR_DBUS_DISPLAY_INTERFACE ) )
|
||||
{
|
||||
if( !g_strcmp0( method_name, "PresentWindow" ) )
|
||||
{
|
||||
gtr_action_activate( "present-main-window" );
|
||||
g_dbus_method_invocation_return_value( invocation, NULL );
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( !handled )
|
||||
g_warning( "Unhandled method call:\n\tObject Path: %s\n\tInterface Name: %s\n\tMethod Name: %s",
|
||||
object_path, interface_name, method_name );
|
||||
};
|
||||
|
||||
static void
|
||||
on_session_registered_in_dbus( GDBusConnection *connection, const gchar *name UNUSED, gpointer core )
|
||||
{
|
||||
GError * err = NULL;
|
||||
GDBusNodeInfo * node_info;
|
||||
GDBusInterfaceVTable vtable;
|
||||
const char * interface_xml = "<node>"
|
||||
" <interface name='" TR_DBUS_SESSION_INTERFACE "'>"
|
||||
" <method name='TorrentAdd'>"
|
||||
" <arg type='a{sv}' name='args' direction='in'/>"
|
||||
" <arg type='b' name='response' direction='out'/>"
|
||||
" </method>"
|
||||
" </interface>"
|
||||
"</node>";
|
||||
|
||||
node_info = g_dbus_node_info_new_for_xml( interface_xml, &err );
|
||||
|
||||
vtable.method_call = handle_dbus_method;
|
||||
vtable.get_property = NULL;
|
||||
vtable.set_property = NULL;
|
||||
|
||||
g_dbus_connection_register_object ( connection,
|
||||
TR_DBUS_SESSION_OBJECT_PATH,
|
||||
node_info->interfaces[0],
|
||||
&vtable,
|
||||
core,
|
||||
NULL,
|
||||
&err );
|
||||
|
||||
if( err != NULL ) {
|
||||
g_warning( "%s:%d Error registering object: %s", __FILE__, __LINE__, err->message );
|
||||
g_error_free( err );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_registered_in_dbus( GDBusConnection *connection, const gchar *name UNUSED, gpointer core )
|
||||
{
|
||||
GError * err = NULL;
|
||||
const char * interface_xml = "<node>"
|
||||
" <interface name='" TR_DBUS_DISPLAY_INTERFACE "'>"
|
||||
" <method name='PresentWindow'>"
|
||||
" </method>"
|
||||
" </interface>"
|
||||
"</node>";
|
||||
GDBusInterfaceVTable vtable = { .method_call=handle_dbus_method };
|
||||
GDBusNodeInfo * node_info = g_dbus_node_info_new_for_xml( interface_xml, &err );
|
||||
|
||||
g_dbus_connection_register_object ( connection,
|
||||
TR_DBUS_DISPLAY_OBJECT_PATH,
|
||||
node_info->interfaces[0],
|
||||
&vtable,
|
||||
core,
|
||||
NULL,
|
||||
&err );
|
||||
|
||||
if( err != NULL ) {
|
||||
g_warning( "%s:%d Error registering object: %s", __FILE__, __LINE__, err->message );
|
||||
g_error_free( err );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
core_init( GTypeInstance * instance, gpointer g_class UNUSED )
|
||||
{
|
||||
@@ -330,24 +226,6 @@ core_init( GTypeInstance * instance, gpointer g_class UNUSED )
|
||||
p->sorted_model = gtk_tree_model_sort_new_with_model( p->raw_model );
|
||||
p->string_chunk = g_string_chunk_new( 2048 );
|
||||
g_object_unref( p->raw_model );
|
||||
|
||||
p->dbus_session_owner_id = g_bus_own_name( G_BUS_TYPE_SESSION,
|
||||
TR_DBUS_SESSION_SERVICE_NAME,
|
||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||
NULL,
|
||||
on_session_registered_in_dbus,
|
||||
NULL,
|
||||
self,
|
||||
NULL );
|
||||
|
||||
p->dbus_display_owner_id = g_bus_own_name( G_BUS_TYPE_SESSION,
|
||||
TR_DBUS_DISPLAY_SERVICE_NAME,
|
||||
G_BUS_NAME_OWNER_FLAGS_NONE,
|
||||
NULL,
|
||||
on_display_registered_in_dbus,
|
||||
NULL,
|
||||
self,
|
||||
NULL );
|
||||
}
|
||||
|
||||
GType
|
||||
@@ -755,6 +633,8 @@ core_watchdir_idle( gpointer gcore )
|
||||
TrCore * core = TR_CORE( gcore );
|
||||
const time_t now = tr_time( );
|
||||
struct TrCorePrivate * p = core->priv;
|
||||
const gboolean do_start = gtr_pref_flag_get( TR_PREFS_KEY_START );
|
||||
const gboolean do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
|
||||
|
||||
/* of the monitor_files, make a list of those that haven't
|
||||
* changed lately, since they should be ready to add */
|
||||
@@ -764,14 +644,16 @@ core_watchdir_idle( gpointer gcore )
|
||||
if( f->mtime + 2 >= now )
|
||||
monitor_files = g_slist_prepend( monitor_files, f );
|
||||
else {
|
||||
addme = g_slist_prepend( addme, g_strdup( f->filename ) );
|
||||
addme = g_slist_prepend( addme, g_file_new_for_commandline_arg( f->filename ) );
|
||||
watchdir_file_free( f );
|
||||
}
|
||||
}
|
||||
|
||||
/* add the torrents from that list */
|
||||
core->priv->adding_from_watch_dir = TRUE;
|
||||
gtr_core_add_list_defaults( core, addme, TRUE );
|
||||
gtr_core_add_files( core, addme, do_start, do_prompt, TRUE );
|
||||
g_slist_foreach( addme, (GFunc)g_object_unref, NULL );
|
||||
g_slist_free( addme );
|
||||
core->priv->adding_from_watch_dir = FALSE;
|
||||
|
||||
/* update the monitor_files list */
|
||||
@@ -941,9 +823,6 @@ gtr_core_close( TrCore * core )
|
||||
gtr_pref_save( session );
|
||||
tr_sessionClose( session );
|
||||
}
|
||||
|
||||
g_bus_unown_name( core->priv->dbus_display_owner_id );
|
||||
g_bus_unown_name( core->priv->dbus_session_owner_id );
|
||||
}
|
||||
|
||||
/***
|
||||
@@ -1221,169 +1100,152 @@ gtr_core_add_ctor( TrCore * core, tr_ctor * ctor )
|
||||
****
|
||||
***/
|
||||
|
||||
struct url_dialog_data
|
||||
struct add_from_url_data
|
||||
{
|
||||
TrCore * core;
|
||||
tr_ctor * ctor;
|
||||
char * url;
|
||||
|
||||
bool did_connect;
|
||||
bool did_timeout;
|
||||
long response_code;
|
||||
bool do_prompt;
|
||||
bool do_notify;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
on_url_done_idle( gpointer vdata )
|
||||
static void
|
||||
add_file_async_callback( GObject * file, GAsyncResult * result, gpointer gdata )
|
||||
{
|
||||
struct url_dialog_data * data = vdata;
|
||||
gsize length;
|
||||
char * contents;
|
||||
GError * error = NULL;
|
||||
struct add_from_url_data * data = gdata;
|
||||
|
||||
if( data->response_code != 200 )
|
||||
if( !g_file_load_contents_finish( G_FILE( file ), result, &contents, &length, NULL, &error ) )
|
||||
{
|
||||
gtr_http_failure_dialog( NULL, data->url, data->response_code );
|
||||
g_message( _( "Couldn't read \"%s\": %s" ), g_file_get_parse_name( G_FILE( file ) ), error->message );
|
||||
g_error_free( error );
|
||||
}
|
||||
else if( !tr_ctorSetMetainfo( data->ctor, (const uint8_t*)contents, length ) )
|
||||
{
|
||||
core_add_ctor( data->core, data->ctor, data->do_prompt, data->do_notify );
|
||||
}
|
||||
else
|
||||
{
|
||||
const gboolean do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
|
||||
const gboolean do_notify = FALSE;
|
||||
const int err = core_add_ctor( data->core, data->ctor, do_prompt, do_notify );
|
||||
|
||||
if( err == TR_PARSE_ERR )
|
||||
core_emit_err( data->core, TR_PARSE_ERR, data->url );
|
||||
|
||||
gtr_core_torrents_added( data->core );
|
||||
tr_ctorFree( data->ctor );
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
core_dec_busy( data->core );
|
||||
g_free( data->url );
|
||||
g_free( data );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_url_done( tr_session * session,
|
||||
bool did_connect,
|
||||
bool did_timeout,
|
||||
long response_code,
|
||||
const void * response,
|
||||
size_t response_byte_count,
|
||||
void * vdata )
|
||||
{
|
||||
struct url_dialog_data * data = vdata;
|
||||
|
||||
data->did_connect = did_connect;
|
||||
data->did_timeout = did_timeout;
|
||||
data->response_code = response_code;
|
||||
data->ctor = tr_ctorNew( session );
|
||||
core_apply_defaults( data->ctor );
|
||||
tr_ctorSetMetainfo( data->ctor, response, response_byte_count );
|
||||
|
||||
gdk_threads_add_idle( on_url_done_idle, data );
|
||||
}
|
||||
|
||||
void
|
||||
gtr_core_add_from_url( TrCore * core, const char * url )
|
||||
{
|
||||
tr_session * session = gtr_core_session( core );
|
||||
const gboolean is_magnet_link = gtr_is_magnet_link( url );
|
||||
|
||||
if( is_magnet_link || gtr_is_hex_hashcode( url ) )
|
||||
{
|
||||
int err;
|
||||
char * tmp = NULL;
|
||||
tr_ctor * ctor = tr_ctorNew( session );
|
||||
|
||||
if( gtr_is_hex_hashcode( url ) )
|
||||
url = tmp = g_strdup_printf( "magnet:?xt=urn:btih:%s", url );
|
||||
|
||||
err = tr_ctorSetMetainfoFromMagnetLink( ctor, url );
|
||||
|
||||
if( !err )
|
||||
gtr_core_add_ctor( core, ctor );
|
||||
else {
|
||||
gtr_unrecognized_url_dialog( NULL, url );
|
||||
tr_ctorFree( ctor );
|
||||
}
|
||||
|
||||
g_free( tmp );
|
||||
}
|
||||
else
|
||||
{
|
||||
struct url_dialog_data * data = g_new( struct url_dialog_data, 1 );
|
||||
data->core = core;
|
||||
data->url = g_strdup( url );
|
||||
core_inc_busy( data->core );
|
||||
tr_webRun( session, url, NULL, NULL, on_url_done, data );
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void
|
||||
add_filename( TrCore * core,
|
||||
const char * filename,
|
||||
gboolean do_start,
|
||||
gboolean do_prompt,
|
||||
gboolean do_notify )
|
||||
static bool
|
||||
add_file( TrCore * core,
|
||||
GFile * file,
|
||||
gboolean do_start,
|
||||
gboolean do_prompt,
|
||||
gboolean do_notify )
|
||||
{
|
||||
bool handled = false;
|
||||
tr_session * session = gtr_core_session( core );
|
||||
|
||||
if( session == NULL )
|
||||
return;
|
||||
|
||||
if( gtr_is_supported_url( filename ) || gtr_is_magnet_link( filename ) )
|
||||
if( session != NULL )
|
||||
{
|
||||
gtr_core_add_from_url( core, filename );
|
||||
}
|
||||
else if( g_file_test( filename, G_FILE_TEST_EXISTS ) )
|
||||
{
|
||||
int err;
|
||||
tr_ctor * ctor;
|
||||
bool tried = false;
|
||||
bool loaded = false;
|
||||
|
||||
tr_ctor * ctor = tr_ctorNew( session );
|
||||
tr_ctorSetMetainfoFromFile( ctor, filename );
|
||||
ctor = tr_ctorNew( session );
|
||||
core_apply_defaults( ctor );
|
||||
tr_ctorSetPaused( ctor, TR_FORCE, !do_start );
|
||||
|
||||
err = core_add_ctor( core, ctor, do_prompt, do_notify );
|
||||
if( err == TR_PARSE_ERR )
|
||||
core_emit_err( core, TR_PARSE_ERR, filename );
|
||||
}
|
||||
else if( gtr_is_hex_hashcode( filename ) )
|
||||
{
|
||||
gtr_core_add_from_url( core, filename );
|
||||
/* local files... */
|
||||
if( !tried ) {
|
||||
char * str = g_file_get_path( file );
|
||||
if(( tried = g_file_test( str, G_FILE_TEST_EXISTS )))
|
||||
loaded = !tr_ctorSetMetainfoFromFile( ctor, str );
|
||||
g_free( str );
|
||||
}
|
||||
|
||||
/* magnet links... */
|
||||
if( !tried && g_file_has_uri_scheme( file, "magnet" ) ) {
|
||||
/* GFile mangles the original string with /// so we have to un-mangle */
|
||||
char * str = g_file_get_parse_name( file );
|
||||
char * magnet = g_strdup_printf( "magnet:%s", strchr( str, '?' ) );
|
||||
tried = true;
|
||||
loaded = !tr_ctorSetMetainfoFromMagnetLink( ctor, magnet );
|
||||
g_free( magnet );
|
||||
g_free( str );
|
||||
}
|
||||
|
||||
/* hashcodes that we can turn into magnet links... */
|
||||
if( !tried ) {
|
||||
char * str = g_file_get_basename( file );
|
||||
if( gtr_is_hex_hashcode( str ) ) {
|
||||
char * magnet = g_strdup_printf( "magnet:?xt=urn:btih:%s", str );
|
||||
tried = true;
|
||||
loaded = !tr_ctorSetMetainfoFromMagnetLink( ctor, magnet );
|
||||
g_free( magnet );
|
||||
}
|
||||
g_free( str );
|
||||
}
|
||||
|
||||
/* if we were able to load the metainfo, add the torrent */
|
||||
if( loaded )
|
||||
{
|
||||
handled = true;
|
||||
core_add_ctor( core, ctor, do_prompt, do_notify );
|
||||
}
|
||||
else if( g_file_has_uri_scheme( file, "http" ) ||
|
||||
g_file_has_uri_scheme( file, "https" ) ||
|
||||
g_file_has_uri_scheme( file, "ftp" ) )
|
||||
{
|
||||
struct add_from_url_data * data;
|
||||
|
||||
data = g_new0( struct add_from_url_data, 1 );
|
||||
data->core = core;
|
||||
data->ctor = ctor;
|
||||
data->do_prompt = do_prompt;
|
||||
data->do_notify = do_notify;
|
||||
|
||||
handled = true;
|
||||
core_inc_busy( core );
|
||||
g_file_load_contents_async( file, NULL, add_file_async_callback, data );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_ctorFree( ctor );
|
||||
g_message( _( "Skipping unknown torrent \"%s\"" ), g_file_get_parse_name( file ) );
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
bool
|
||||
gtr_core_add_from_url( TrCore * core, const char * uri )
|
||||
{
|
||||
bool handled;
|
||||
const bool do_start = gtr_pref_flag_get( TR_PREFS_KEY_START );
|
||||
const bool do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
|
||||
const bool do_notify = false;
|
||||
|
||||
GFile * file = g_file_new_for_uri( uri );
|
||||
handled = add_file( core, file, do_start, do_prompt, do_notify );
|
||||
g_object_unref( file );
|
||||
gtr_core_torrents_added( core );
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void
|
||||
gtr_core_add_list( TrCore * core,
|
||||
GSList * files,
|
||||
gboolean do_start,
|
||||
gboolean do_prompt,
|
||||
gboolean do_notify )
|
||||
gtr_core_add_files( TrCore * core,
|
||||
GSList * files,
|
||||
gboolean do_start,
|
||||
gboolean do_prompt,
|
||||
gboolean do_notify )
|
||||
{
|
||||
GSList * l;
|
||||
|
||||
for( l=files; l!=NULL; l=l->next )
|
||||
{
|
||||
char * filename = l->data;
|
||||
add_filename( core, filename, do_start, do_prompt, do_notify );
|
||||
g_free( filename );
|
||||
}
|
||||
add_file( core, l->data, do_start, do_prompt, do_notify );
|
||||
|
||||
gtr_core_torrents_added( core );
|
||||
|
||||
g_slist_free( files );
|
||||
}
|
||||
|
||||
void
|
||||
gtr_core_add_list_defaults( TrCore * core, GSList * files, gboolean do_notify )
|
||||
{
|
||||
const gboolean do_start = gtr_pref_flag_get( TR_PREFS_KEY_START );
|
||||
const gboolean do_prompt = gtr_pref_flag_get( PREF_KEY_OPTIONS_PROMPT );
|
||||
|
||||
gtr_core_add_list( core, files, do_start, do_prompt, do_notify );
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+6
-20
@@ -106,19 +106,14 @@ void gtr_core_load( TrCore * self, gboolean forcepaused );
|
||||
* May pop up dialogs for each torrent if that preference is enabled.
|
||||
* May trigger one or more "error" signals with TR_CORE_ERR_ADD_TORRENT
|
||||
*/
|
||||
void gtr_core_add_list( TrCore * self,
|
||||
GSList * torrentFiles,
|
||||
gboolean do_start,
|
||||
gboolean do_prompt,
|
||||
gboolean do_notify );
|
||||
|
||||
void gtr_core_add_list_defaults( TrCore * core,
|
||||
GSList * torrentFiles,
|
||||
gboolean do_notify );
|
||||
|
||||
void gtr_core_add_files( TrCore * core,
|
||||
GSList * files,
|
||||
gboolean do_start,
|
||||
gboolean do_prompt,
|
||||
gboolean do_notify );
|
||||
|
||||
/** @brief Add a torrent from a URL */
|
||||
void gtr_core_add_from_url( TrCore * core, const char * url );
|
||||
bool gtr_core_add_from_url( TrCore * core, const char * url );
|
||||
|
||||
/** @brief Add a torrent.
|
||||
@param ctor this function assumes ownership of the ctor */
|
||||
@@ -200,13 +195,4 @@ enum
|
||||
};
|
||||
|
||||
|
||||
#define TR_DBUS_SESSION_SERVICE_NAME "com.transmissionbt.transmission.Session"
|
||||
#define TR_DBUS_SESSION_INTERFACE "com.transmissionbt.transmission.Session"
|
||||
#define TR_DBUS_SESSION_OBJECT_PATH "/com/transmissionbt/transmission/Session"
|
||||
|
||||
#define TR_DBUS_DISPLAY_SERVICE_NAME "com.transmissionbt.transmission.Display"
|
||||
#define TR_DBUS_DISPLAY_INTERFACE "com.transmissionbt.transmission.Display"
|
||||
#define TR_DBUS_DISPLAY_OBJECT_PATH "/com/transmissionbt/transmission/Display"
|
||||
|
||||
|
||||
#endif /* GTR_CORE_H */
|
||||
|
||||
+1
-120
@@ -15,10 +15,6 @@
|
||||
#include <stdarg.h>
|
||||
#include <string.h> /* strchr(), strrchr(), strlen(), strncmp(), strstr() */
|
||||
|
||||
#include <sys/types.h> /* for gtr_lockfile()'s open() */
|
||||
#include <sys/stat.h> /* for gtr_lockfile()'s open() */
|
||||
#include <fcntl.h> /* for gtr_lockfile()'s open() */
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h> /* g_unlink() */
|
||||
@@ -59,54 +55,6 @@ const char * speed_T_str = N_("TiB/s");
|
||||
****
|
||||
***/
|
||||
|
||||
gtr_lockfile_state_t
|
||||
gtr_lockfile( const char * filename )
|
||||
{
|
||||
gtr_lockfile_state_t ret;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
HANDLE file = CreateFile( filename,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL );
|
||||
if( file == INVALID_HANDLE_VALUE )
|
||||
ret = GTR_LOCKFILE_EOPEN;
|
||||
else if( !LockFile( file, 0, 0, 1, 1 ) )
|
||||
ret = GTR_LOCKFILE_ELOCK;
|
||||
else
|
||||
ret = GTR_LOCKFILE_SUCCESS;
|
||||
|
||||
#else
|
||||
|
||||
int fd = open( filename, O_RDWR | O_CREAT, 0666 );
|
||||
if( fd < 0 )
|
||||
ret = GTR_LOCKFILE_EOPEN;
|
||||
else {
|
||||
struct flock lk;
|
||||
memset( &lk, 0, sizeof( lk ) );
|
||||
lk.l_start = 0;
|
||||
lk.l_len = 0;
|
||||
lk.l_type = F_WRLCK;
|
||||
lk.l_whence = SEEK_SET;
|
||||
if( -1 == fcntl( fd, F_SETLK, &lk ) )
|
||||
ret = GTR_LOCKFILE_ELOCK;
|
||||
else
|
||||
ret = GTR_LOCKFILE_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
const char*
|
||||
gtr_get_unicode_string( int i )
|
||||
{
|
||||
@@ -218,7 +166,7 @@ gtr_get_host_from_url( char * buf, size_t buflen, const char * url )
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
gtr_is_supported_url( const char * str )
|
||||
{
|
||||
return !strncmp( str, "ftp://", 6 )
|
||||
@@ -432,73 +380,6 @@ gtr_open_uri( const char * uri )
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtr_dbus_add_torrent( const char * filename )
|
||||
{
|
||||
GVariant * response;
|
||||
GVariant * args;
|
||||
GVariant * parameters;
|
||||
GVariantBuilder * builder;
|
||||
GDBusConnection * connection;
|
||||
GError * err = NULL;
|
||||
gboolean handled = FALSE;
|
||||
|
||||
/* "args" is a dict as described in the RPC spec's "torrent-add" section */
|
||||
builder = g_variant_builder_new( G_VARIANT_TYPE( "a{sv}" ) );
|
||||
g_variant_builder_add( builder, "{sv}", "filename", g_variant_new_string( filename ) );
|
||||
args = g_variant_builder_end( builder );
|
||||
parameters = g_variant_new_tuple( &args, 1 );
|
||||
g_variant_builder_unref( builder );
|
||||
|
||||
connection = g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, &err );
|
||||
|
||||
response = g_dbus_connection_call_sync( connection,
|
||||
TR_DBUS_SESSION_SERVICE_NAME,
|
||||
TR_DBUS_SESSION_OBJECT_PATH,
|
||||
TR_DBUS_SESSION_INTERFACE,
|
||||
"TorrentAdd",
|
||||
parameters,
|
||||
G_VARIANT_TYPE_TUPLE,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
10000, /* wait 10 sec */
|
||||
NULL,
|
||||
&err );
|
||||
|
||||
|
||||
handled = g_variant_get_boolean( g_variant_get_child_value( response, 0 ) );
|
||||
|
||||
g_object_unref( connection );
|
||||
g_variant_unref( response );
|
||||
return handled;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtr_dbus_present_window( void )
|
||||
{
|
||||
gboolean success;
|
||||
GDBusConnection * connection;
|
||||
GError * err = NULL;
|
||||
|
||||
connection = g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, &err );
|
||||
|
||||
g_dbus_connection_call_sync( connection,
|
||||
TR_DBUS_DISPLAY_SERVICE_NAME,
|
||||
TR_DBUS_DISPLAY_OBJECT_PATH,
|
||||
TR_DBUS_DISPLAY_INTERFACE,
|
||||
"PresentWindow",
|
||||
NULL,
|
||||
NULL, G_DBUS_CALL_FLAGS_NONE,
|
||||
1000, NULL, &err );
|
||||
|
||||
success = err == NULL;
|
||||
|
||||
/* cleanup */
|
||||
if( err != NULL )
|
||||
g_error_free( err );
|
||||
g_object_unref( connection );
|
||||
return success;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
-20
@@ -70,8 +70,6 @@ char* tr_strltime( char * buf, int secs, size_t buflen );
|
||||
/* http://www.legaltorrents.com/some/announce/url --> legaltorrents.com */
|
||||
void gtr_get_host_from_url( char * buf, size_t buflen, const char * url );
|
||||
|
||||
gboolean gtr_is_supported_url( const char * str );
|
||||
|
||||
gboolean gtr_is_magnet_link( const char * str );
|
||||
|
||||
gboolean gtr_is_hex_hashcode( const char * str );
|
||||
@@ -80,28 +78,10 @@ gboolean gtr_is_hex_hashcode( const char * str );
|
||||
****
|
||||
***/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GTR_LOCKFILE_SUCCESS = 0,
|
||||
GTR_LOCKFILE_EOPEN,
|
||||
GTR_LOCKFILE_ELOCK
|
||||
}
|
||||
gtr_lockfile_state_t;
|
||||
|
||||
gtr_lockfile_state_t gtr_lockfile( const char * filename );
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
void gtr_open_uri( const char * uri );
|
||||
|
||||
void gtr_open_file( const char * path );
|
||||
|
||||
gboolean gtr_dbus_add_torrent( const char * filename );
|
||||
|
||||
gboolean gtr_dbus_present_window( void );
|
||||
|
||||
const char* gtr_get_help_uri( void );
|
||||
|
||||
/***
|
||||
|
||||
Reference in New Issue
Block a user