(trunk) #671 "torrent queuing" -- Preliminary implementation. Covers libtransmission; GTK+ and Qt clients, and rudimentary web client support.
This commit is contained in:
parent
56525f4b80
commit
61174b007e
|
@ -65,6 +65,7 @@
|
|||
Method name | libtransmission function
|
||||
---------------------+-------------------------------------------------
|
||||
"torrent-start" | tr_torrentStart
|
||||
"torrent-start-now" | tr_torrentStartNow
|
||||
"torrent-stop" | tr_torrentStop
|
||||
"torrent-verify" | tr_torrentVerify
|
||||
"torrent-reannounce" | tr_torrentManualUpdate ("ask tracker for more peers")
|
||||
|
@ -98,6 +99,7 @@
|
|||
"priority-high" | array indices of high-priority file(s)
|
||||
"priority-low" | array indices of low-priority file(s)
|
||||
"priority-normal" | array indices of normal-priority file(s)
|
||||
"queuePosition" | number position of this torrent in its queue [0...n)
|
||||
"seedIdleLimit" | number torrent-level number of minutes of seeding inactivity
|
||||
"seedIdleMode" | number which seeding inactivity to use. See tr_inactvelimit
|
||||
"seedRatioLimit" | double torrent-level seeding ratio
|
||||
|
@ -179,6 +181,7 @@
|
|||
pieceCount | number | tr_info
|
||||
pieceSize | number | tr_info
|
||||
priorities | array (see below) | n/a
|
||||
queuePosition | number | tr_stat
|
||||
rateDownload (B/s) | number | tr_stat
|
||||
rateUpload (B/s) | number | tr_stat
|
||||
recheckProgress | double | tr_stat
|
||||
|
@ -423,6 +426,8 @@
|
|||
"config-dir" | string | location of transmission's configuration directory
|
||||
"download-dir" | string | default path to download torrents
|
||||
"download-dir-free-space" | number | number of free bytes available in download-dir, or -1 if it can't be calculated
|
||||
"download-queue-size" | number | max number of torrents to download at once (see download-queue-enabled)
|
||||
"download-queue-enabled" | boolean | if true, limit how many torrents can be downloaded at once
|
||||
"dht-enabled" | boolean | true means allow dht in public torrents
|
||||
"encryption" | string | "required", "preferred", "tolerated"
|
||||
"idle-seeding-limit" | number | torrents we're seeding will be stopped if they're idle for this long
|
||||
|
@ -436,6 +441,7 @@
|
|||
"peer-port" | number | port number
|
||||
"peer-port-random-on-start" | boolean | true means pick a random peer port on launch
|
||||
"port-forwarding-enabled" | boolean | true means enabled
|
||||
"queue-stalled-minutes" | number | torrents that are idle for N minuets aren't counted toward seed-queue-size or download-queue-size
|
||||
"rename-partial-files" | boolean | true means append ".part" to incomplete files
|
||||
"rpc-version" | number | the current RPC API version
|
||||
"rpc-version-minimum" | number | the minimum RPC API version supported
|
||||
|
@ -443,6 +449,8 @@
|
|||
"script-torrent-done-enabled" | boolean | whether or not to call the "done" script
|
||||
"seedRatioLimit" | double | the default seed ratio for torrents to use
|
||||
"seedRatioLimited" | boolean | true if seedRatioLimit is honored by default
|
||||
"seed-queue-size" | number | max number of torrents to uploaded at once (see seed-queue-enabled)
|
||||
"seed-queue-enabled" | boolean | if true, limit how many torrents can be uploaded at once
|
||||
"speed-limit-down" | number | max global download speed (KBps)
|
||||
"speed-limit-down-enabled" | boolean | true means enabled
|
||||
"speed-limit-up" | number | max global upload speed (KBps)
|
||||
|
@ -536,10 +544,27 @@
|
|||
|
||||
This method tells the transmission session to shut down.
|
||||
|
||||
Method-name: "session-close"
|
||||
Method name: "session-close"
|
||||
Request arguments: none
|
||||
Response arguments: none
|
||||
|
||||
4.6. Queue Movement Requests
|
||||
|
||||
Method name | libtransmission function
|
||||
---------------------+-------------------------------------------------
|
||||
"queue-move-top" | tr_torrentQueueMoveTop()
|
||||
"queue-move-up" | tr_torrentQueueMoveUp()
|
||||
"queue-move-down" | tr_torrentQueueMoveDown()
|
||||
"queue-move-bottom" | tr_torrentQueueMoveBottom()
|
||||
|
||||
Request arguments:
|
||||
|
||||
string | value type & description
|
||||
------------+----------------------------------------------------------
|
||||
"ids" | array torrent list, as described in 3.1.
|
||||
|
||||
Response arguments: none
|
||||
|
||||
5.0. Protocol Versions
|
||||
|
||||
The following changes have been made to the RPC interface:
|
||||
|
@ -662,3 +687,17 @@
|
|||
13 | 2.30 | yes | session-get | new arg "isUTP" to the "peers" list
|
||||
| | yes | torrent-add | new arg "cookies"
|
||||
| | NO | torrent-get | removed arg "peersKnown"
|
||||
------+---------+-----------+----------------+-------------------------------
|
||||
14 | 2.40 | NO | torrent-get | values of "status" field changed
|
||||
| | yes | torrent-get | new arg "queuePosition"
|
||||
| | yes | torrent-set | new arg "queuePosition"
|
||||
| | yes | session-set | new arg "download-queue-size"
|
||||
| | yes | session-set | new arg "download-queue-enabled"
|
||||
| | yes | session-set | new arg "seed-queue-size"
|
||||
| | yes | session-set | new arg "seed-queue-enabled"
|
||||
| | yes | session-set | new arg "queue-stalled-minutes"
|
||||
| | yes | | new method "queue-move-top"
|
||||
| | yes | | new method "queue-move-up"
|
||||
| | yes | | new method "queue-move-down"
|
||||
| | yes | | new method "queue-move-bottom"
|
||||
| | yes | | new method "torrent-start-now"
|
||||
|
|
|
@ -100,17 +100,19 @@ static GtkActionEntry entries[] =
|
|||
{ "torrent-menu", NULL, N_( "_Torrent" ), NULL, NULL, NULL },
|
||||
{ "view-menu", NULL, N_( "_View" ), NULL, NULL, NULL },
|
||||
{ "sort-menu", NULL, N_( "_Sort Torrents By" ), NULL, NULL, NULL },
|
||||
{ "queue-menu", NULL, N_( "_Queue" ), NULL, NULL, NULL },
|
||||
{ "edit-menu", NULL, N_( "_Edit" ), NULL, NULL, NULL },
|
||||
{ "help-menu", NULL, N_( "_Help" ), NULL, NULL, NULL },
|
||||
{ "copy-magnet-link-to-clipboard", GTK_STOCK_COPY, N_("Copy _Magnet Link to Clipboard" ), "", NULL, G_CALLBACK( action_cb ) },
|
||||
{ "open-torrent-from-url", GTK_STOCK_OPEN, N_("Open _URL..." ), "<control>U", N_( "Open URL..." ), G_CALLBACK( action_cb ) },
|
||||
{ "open-torrent-toolbar", GTK_STOCK_OPEN, NULL, NULL, N_( "Open a torrent" ), G_CALLBACK( action_cb ) },
|
||||
{ "open-torrent-menu", GTK_STOCK_OPEN, NULL, NULL, N_( "Open a torrent" ), G_CALLBACK( action_cb ) },
|
||||
{ "start-torrent", GTK_STOCK_MEDIA_PLAY, N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK( action_cb ) },
|
||||
{ "torrent-start", GTK_STOCK_MEDIA_PLAY, N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK( action_cb ) },
|
||||
{ "torrent-start-now", GTK_STOCK_MEDIA_PLAY, N_( "Start _Now" ), "<shift><control>S", N_( "Start torrent now" ), G_CALLBACK( action_cb ) },
|
||||
{ "show-stats", NULL, N_( "_Statistics" ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "donate", NULL, N_( "_Donate" ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "verify-torrent", NULL, N_( "_Verify Local Data" ), "<control>V", NULL, G_CALLBACK( action_cb ) },
|
||||
{ "pause-torrent", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK( action_cb ) },
|
||||
{ "torrent-verify", NULL, N_( "_Verify Local Data" ), "<control>V", NULL, G_CALLBACK( action_cb ) },
|
||||
{ "torrent-stop", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK( action_cb ) },
|
||||
{ "pause-all-torrents", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause All" ), NULL, N_( "Pause all torrents" ), G_CALLBACK( action_cb ) },
|
||||
{ "start-all-torrents", GTK_STOCK_MEDIA_PLAY, N_( "_Start All" ), NULL, N_( "Start all torrents" ), G_CALLBACK( action_cb ) },
|
||||
{ "relocate-torrent", NULL, N_("Set _Location..." ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
|
@ -125,7 +127,11 @@ static GtkActionEntry entries[] =
|
|||
{ "open-torrent-folder", GTK_STOCK_OPEN, N_( "Open Fold_er" ), "<control>E", NULL, G_CALLBACK( action_cb ) },
|
||||
{ "show-about-dialog", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "help", GTK_STOCK_HELP, N_( "_Contents" ), "F1", NULL, G_CALLBACK( action_cb ) },
|
||||
{ "update-tracker", GTK_STOCK_NETWORK, N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "torrent-reannounce", GTK_STOCK_NETWORK, N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "queue-move-top", GTK_STOCK_GOTO_TOP, N_( "Move to _Top" ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "queue-move-up", GTK_STOCK_GO_UP, N_( "Move _Up" ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "queue-move-down", GTK_STOCK_GO_DOWN, N_( "Move _Down" ), NULL, NULL, G_CALLBACK( action_cb ) },
|
||||
{ "queue-move-bottom", GTK_STOCK_GOTO_BOTTOM, N_( "Move to _Bottom" ), NULL, NULL, G_CALLBACK( action_cb ) }
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -557,11 +557,13 @@ activityString( int activity, bool finished )
|
|||
{
|
||||
switch( activity )
|
||||
{
|
||||
case TR_STATUS_CHECK_WAIT: return _( "Waiting to verify local data" );
|
||||
case TR_STATUS_CHECK: return _( "Verifying local data" );
|
||||
case TR_STATUS_DOWNLOAD: return _( "Downloading" );
|
||||
case TR_STATUS_SEED: return _( "Seeding" );
|
||||
case TR_STATUS_STOPPED: return finished ? _( "Finished" ) : _( "Paused" );
|
||||
case TR_STATUS_CHECK_WAIT: return _( "Waiting to verify local data" );
|
||||
case TR_STATUS_CHECK: return _( "Verifying local data" );
|
||||
case TR_STATUS_DOWNLOAD_WAIT: return _( "Queued to download" );
|
||||
case TR_STATUS_DOWNLOAD: return _( "Downloading" );
|
||||
case TR_STATUS_SEED_WAIT: return _( "Queued to seed" );
|
||||
case TR_STATUS_SEED: return _( "Seeding" );
|
||||
case TR_STATUS_STOPPED: return finished ? _( "Finished" ) : _( "Paused" );
|
||||
}
|
||||
|
||||
return "";
|
||||
|
|
14
gtk/filter.c
14
gtk/filter.c
|
@ -581,7 +581,6 @@ enum
|
|||
ACTIVITY_FILTER_ACTIVE,
|
||||
ACTIVITY_FILTER_PAUSED,
|
||||
ACTIVITY_FILTER_FINISHED,
|
||||
ACTIVITY_FILTER_QUEUED,
|
||||
ACTIVITY_FILTER_VERIFYING,
|
||||
ACTIVITY_FILTER_ERROR,
|
||||
ACTIVITY_FILTER_SEPARATOR
|
||||
|
@ -612,10 +611,12 @@ test_torrent_activity( tr_torrent * tor, int type )
|
|||
switch( type )
|
||||
{
|
||||
case ACTIVITY_FILTER_DOWNLOADING:
|
||||
return st->activity == TR_STATUS_DOWNLOAD;
|
||||
return ( st->activity == TR_STATUS_DOWNLOAD )
|
||||
|| ( st->activity == TR_STATUS_DOWNLOAD_WAIT );
|
||||
|
||||
case ACTIVITY_FILTER_SEEDING:
|
||||
return st->activity == TR_STATUS_SEED;
|
||||
return ( st->activity == TR_STATUS_SEED )
|
||||
|| ( st->activity == TR_STATUS_SEED_WAIT );
|
||||
|
||||
case ACTIVITY_FILTER_ACTIVE:
|
||||
return ( st->peersSendingToUs > 0 )
|
||||
|
@ -629,11 +630,9 @@ test_torrent_activity( tr_torrent * tor, int type )
|
|||
case ACTIVITY_FILTER_FINISHED:
|
||||
return st->finished == TRUE;
|
||||
|
||||
case ACTIVITY_FILTER_QUEUED:
|
||||
return st->activity == TR_STATUS_CHECK_WAIT;
|
||||
|
||||
case ACTIVITY_FILTER_VERIFYING:
|
||||
return ( st->activity == TR_STATUS_CHECK ) || ( st->activity == TR_STATUS_CHECK_WAIT );
|
||||
return ( st->activity == TR_STATUS_CHECK )
|
||||
|| ( st->activity == TR_STATUS_CHECK_WAIT );
|
||||
|
||||
case ACTIVITY_FILTER_ERROR:
|
||||
return st->error != 0;
|
||||
|
@ -700,7 +699,6 @@ activity_filter_model_new( GtkTreeModel * tmodel )
|
|||
{ ACTIVITY_FILTER_SEEDING, N_( "Seeding" ), GTK_STOCK_GO_UP },
|
||||
{ ACTIVITY_FILTER_PAUSED, N_( "Paused" ), GTK_STOCK_MEDIA_PAUSE },
|
||||
{ ACTIVITY_FILTER_FINISHED, N_( "Finished" ), NULL },
|
||||
{ ACTIVITY_FILTER_QUEUED, N_( "Queued" ), NULL },
|
||||
{ ACTIVITY_FILTER_VERIFYING, N_( "Verifying" ), GTK_STOCK_REFRESH },
|
||||
{ ACTIVITY_FILTER_ERROR, N_( "Error" ), GTK_STOCK_DIALOG_ERROR }
|
||||
};
|
||||
|
|
64
gtk/main.c
64
gtk/main.c
|
@ -248,7 +248,8 @@ struct counts_data
|
|||
{
|
||||
int total_count;
|
||||
int active_count;
|
||||
int inactive_count;
|
||||
int queued_count;
|
||||
int stopped_count;
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -256,14 +257,18 @@ get_selected_torrent_counts_foreach( GtkTreeModel * model, GtkTreePath * path UN
|
|||
GtkTreeIter * iter, gpointer user_data )
|
||||
{
|
||||
int activity = 0;
|
||||
int queuePosition = -1;
|
||||
struct counts_data * counts = user_data;
|
||||
|
||||
++counts->total_count;
|
||||
|
||||
gtk_tree_model_get( model, iter, MC_ACTIVITY, &activity, -1 );
|
||||
|
||||
if( activity == TR_STATUS_STOPPED )
|
||||
++counts->inactive_count;
|
||||
if( activity == TR_STATUS_DOWNLOAD_WAIT )
|
||||
++counts->queued_count;
|
||||
|
||||
if( ( activity == TR_STATUS_STOPPED ) && ( queuePosition < 0 ) )
|
||||
++counts->stopped_count;
|
||||
else
|
||||
++counts->active_count;
|
||||
}
|
||||
|
@ -271,9 +276,10 @@ get_selected_torrent_counts_foreach( GtkTreeModel * model, GtkTreePath * path UN
|
|||
static void
|
||||
get_selected_torrent_counts( struct cbdata * data, struct counts_data * counts )
|
||||
{
|
||||
counts->active_count = 0;
|
||||
counts->inactive_count = 0;
|
||||
counts->total_count = 0;
|
||||
counts->active_count = 0;
|
||||
counts->queued_count = 0;
|
||||
counts->stopped_count = 0;
|
||||
|
||||
gtk_tree_selection_selected_foreach( data->sel, get_selected_torrent_counts_foreach, counts );
|
||||
}
|
||||
|
@ -296,6 +302,9 @@ refresh_actions( gpointer gdata )
|
|||
const size_t total = gtr_core_get_torrent_count( data->core );
|
||||
const size_t active = gtr_core_get_active_torrent_count( data->core );
|
||||
const int torrent_count = gtk_tree_model_iter_n_children( gtr_core_model( data->core ), NULL );
|
||||
const tr_session * session = gtr_core_session( data->core );
|
||||
const bool queue_enabled = tr_sessionGetQueueEnabled( session, TR_DOWN )
|
||||
|| tr_sessionGetQueueEnabled( session, TR_UP );
|
||||
|
||||
gtr_action_set_sensitive( "select-all", torrent_count != 0 );
|
||||
gtr_action_set_sensitive( "deselect-all", torrent_count != 0 );
|
||||
|
@ -303,19 +312,24 @@ refresh_actions( gpointer gdata )
|
|||
gtr_action_set_sensitive( "start-all-torrents", active != total );
|
||||
|
||||
get_selected_torrent_counts( data, &sel_counts );
|
||||
gtr_action_set_sensitive( "pause-torrent", sel_counts.active_count != 0 );
|
||||
gtr_action_set_sensitive( "start-torrent", sel_counts.inactive_count != 0 );
|
||||
gtr_action_set_sensitive( "torrent-stop", ( sel_counts.active_count + sel_counts.queued_count ) > 0 );
|
||||
gtr_action_set_sensitive( "torrent-start", ( sel_counts.stopped_count ) > 0 );
|
||||
gtr_action_set_sensitive( "torrent-start-now", ( sel_counts.stopped_count + sel_counts.queued_count ) > 0 );
|
||||
gtr_action_set_sensitive( "torrent-verify", sel_counts.total_count != 0 );
|
||||
gtr_action_set_sensitive( "remove-torrent", sel_counts.total_count != 0 );
|
||||
gtr_action_set_sensitive( "delete-torrent", sel_counts.total_count != 0 );
|
||||
gtr_action_set_sensitive( "verify-torrent", sel_counts.total_count != 0 );
|
||||
gtr_action_set_sensitive( "relocate-torrent", sel_counts.total_count != 0 );
|
||||
gtr_action_set_sensitive( "show-torrent-properties", sel_counts.total_count != 0 );
|
||||
gtr_action_set_sensitive( "open-torrent-folder", sel_counts.total_count == 1 );
|
||||
gtr_action_set_sensitive( "copy-magnet-link-to-clipboard", sel_counts.total_count == 1 );
|
||||
gtr_action_set_sensitive( "queue-move-top", queue_enabled && ( sel_counts.queued_count > 0 ) );
|
||||
gtr_action_set_sensitive( "queue-move-up", queue_enabled && ( sel_counts.queued_count > 0 ) );
|
||||
gtr_action_set_sensitive( "queue-move-down", queue_enabled && ( sel_counts.queued_count > 0 ) );
|
||||
gtr_action_set_sensitive( "queue-move-bottom", queue_enabled && ( sel_counts.queued_count > 0 ) );
|
||||
|
||||
canUpdate = 0;
|
||||
gtk_tree_selection_selected_foreach( data->sel, count_updatable_foreach, &canUpdate );
|
||||
gtr_action_set_sensitive( "update-tracker", canUpdate != 0 );
|
||||
gtr_action_set_sensitive( "torrent-reannounce", canUpdate != 0 );
|
||||
|
||||
data->refresh_actions_tag = 0;
|
||||
return FALSE;
|
||||
|
@ -1286,6 +1300,14 @@ on_prefs_changed( TrCore * core UNUSED, const char * key, gpointer data )
|
|||
{
|
||||
tr_sessionSetIncompleteFileNamingEnabled( tr, gtr_pref_flag_get( key ) );
|
||||
}
|
||||
else if( !strcmp( key, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE ) )
|
||||
{
|
||||
tr_sessionSetQueueSize( tr, TR_DOWN, gtr_pref_int_get( key ) );
|
||||
}
|
||||
else if( !strcmp( key, TR_PREFS_KEY_QUEUE_STALLED_MINUTES ) )
|
||||
{
|
||||
tr_sessionSetQueueStalledMinutes( tr, gtr_pref_int_get( key ) );
|
||||
}
|
||||
else if( !strcmp( key, TR_PREFS_KEY_DHT_ENABLED ) )
|
||||
{
|
||||
tr_sessionSetDHTEnabled( tr, gtr_pref_flag_get( key ) );
|
||||
|
@ -1661,21 +1683,17 @@ gtr_actions_handler( const char * action_name, gpointer user_data )
|
|||
gtk_widget_show( w );
|
||||
}
|
||||
}
|
||||
else if( !strcmp( action_name, "start-torrent" ) )
|
||||
else if( !strcmp( action_name, "torrent-start" )
|
||||
|| !strcmp( action_name, "torrent-start-now" )
|
||||
|| !strcmp( action_name, "torrent-stop" )
|
||||
|| !strcmp( action_name, "torrent-reannounce" )
|
||||
|| !strcmp( action_name, "torrent-verify" )
|
||||
|| !strcmp( action_name, "queue-move-top" )
|
||||
|| !strcmp( action_name, "queue-move-up" )
|
||||
|| !strcmp( action_name, "queue-move-down" )
|
||||
|| !strcmp( action_name, "queue-move-bottom" ) )
|
||||
{
|
||||
changed |= call_rpc_for_selected_torrents( data, "torrent-start" );
|
||||
}
|
||||
else if( !strcmp( action_name, "pause-torrent" ) )
|
||||
{
|
||||
changed |= call_rpc_for_selected_torrents( data, "torrent-stop" );
|
||||
}
|
||||
else if( !strcmp( action_name, "verify-torrent" ) )
|
||||
{
|
||||
changed |= call_rpc_for_selected_torrents( data, "torrent-verify" );
|
||||
}
|
||||
else if( !strcmp( action_name, "update-tracker" ) )
|
||||
{
|
||||
changed |= call_rpc_for_selected_torrents( data, "torrent-reannounce" );
|
||||
changed |= call_rpc_for_selected_torrents( data, action_name );
|
||||
}
|
||||
else if( !strcmp( action_name, "open-torrent-folder" ) )
|
||||
{
|
||||
|
|
|
@ -226,6 +226,14 @@ getShortStatusString( GString * gstr,
|
|||
tr_truncd( st->recheckProgress * 100.0, 1 ) );
|
||||
break;
|
||||
|
||||
case TR_STATUS_DOWNLOAD_WAIT:
|
||||
g_string_append_printf( gstr, _( "Download queue #%d" ), st->queuePosition + 1 );
|
||||
break;
|
||||
|
||||
case TR_STATUS_SEED_WAIT:
|
||||
g_string_append_printf( gstr, _( "Seed queue #%d" ), st->queuePosition + 1 );
|
||||
break;
|
||||
|
||||
case TR_STATUS_DOWNLOAD:
|
||||
case TR_STATUS_SEED:
|
||||
{
|
||||
|
@ -253,10 +261,6 @@ getStatusString( GString * gstr,
|
|||
const double uploadSpeed_KBps,
|
||||
const double downloadSpeed_KBps )
|
||||
{
|
||||
const int isActive = st->activity != TR_STATUS_STOPPED;
|
||||
const int isChecking = st->activity == TR_STATUS_CHECK
|
||||
|| st->activity == TR_STATUS_CHECK_WAIT;
|
||||
|
||||
if( st->error )
|
||||
{
|
||||
const char * fmt[] = { NULL, N_( "Tracker gave a warning: \"%s\"" ),
|
||||
|
@ -269,6 +273,8 @@ getStatusString( GString * gstr,
|
|||
case TR_STATUS_STOPPED:
|
||||
case TR_STATUS_CHECK_WAIT:
|
||||
case TR_STATUS_CHECK:
|
||||
case TR_STATUS_DOWNLOAD_WAIT:
|
||||
case TR_STATUS_SEED_WAIT:
|
||||
{
|
||||
getShortStatusString( gstr, tor, st, uploadSpeed_KBps, downloadSpeed_KBps );
|
||||
break;
|
||||
|
@ -307,7 +313,11 @@ getStatusString( GString * gstr,
|
|||
break;
|
||||
}
|
||||
|
||||
if( isActive && !isChecking )
|
||||
if( ( st->activity != TR_STATUS_CHECK_WAIT ) &&
|
||||
( st->activity != TR_STATUS_CHECK ) &&
|
||||
( st->activity != TR_STATUS_DOWNLOAD_WAIT ) &&
|
||||
( st->activity != TR_STATUS_SEED_WAIT ) &&
|
||||
( st->activity != TR_STATUS_STOPPED ) )
|
||||
{
|
||||
char buf[256];
|
||||
getShortTransferString( tor, st, uploadSpeed_KBps, downloadSpeed_KBps, buf, sizeof( buf ) );
|
||||
|
@ -630,7 +640,7 @@ render_compact( TorrentCellRenderer * cell,
|
|||
struct TorrentCellRendererPrivate * p = cell->priv;
|
||||
const tr_torrent * tor = p->tor;
|
||||
const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );
|
||||
const gboolean active = st->activity != TR_STATUS_STOPPED;
|
||||
const gboolean active = ( st->activity != TR_STATUS_STOPPED ) && ( st->activity != TR_STATUS_DOWNLOAD_WAIT ) && ( st->activity != TR_STATUS_SEED_WAIT );
|
||||
const double percentDone = get_percent_done( tor, st, &seed );
|
||||
const gboolean sensitive = active || st->error;
|
||||
GString * gstr_stat = p->gstr1;
|
||||
|
@ -673,7 +683,8 @@ render_compact( TorrentCellRenderer * cell,
|
|||
|
||||
g_object_set( p->icon_renderer, "pixbuf", icon, "sensitive", sensitive, NULL );
|
||||
gtr_cell_renderer_render( p->icon_renderer, window, widget, &icon_area, flags );
|
||||
g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", NULL, "sensitive", sensitive,
|
||||
g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", NULL,
|
||||
"sensitive", sensitive || ( st->queuePosition >= 0 ),
|
||||
#if GTK_CHECK_VERSION( 3,0,0 )
|
||||
"inverted", seed,
|
||||
#elif GTK_CHECK_VERSION( 2,6,0 )
|
||||
|
@ -683,7 +694,7 @@ render_compact( TorrentCellRenderer * cell,
|
|||
gtr_cell_renderer_render( p->progress_renderer, window, widget, &prog_area, flags );
|
||||
g_object_set( p->text_renderer, "text", gstr_stat->str, "scale", SMALL_SCALE, "ellipsize", PANGO_ELLIPSIZE_END, FOREGROUND_COLOR_KEY, &text_color, NULL );
|
||||
gtr_cell_renderer_render( p->text_renderer, window, widget, &stat_area, flags );
|
||||
g_object_set( p->text_renderer, "text", name, "scale", 1.0, NULL );
|
||||
g_object_set( p->text_renderer, "text", name, "scale", 1.0, FOREGROUND_COLOR_KEY, &text_color, NULL );
|
||||
gtr_cell_renderer_render( p->text_renderer, window, widget, &name_area, flags );
|
||||
|
||||
/* cleanup */
|
||||
|
@ -715,7 +726,7 @@ render_full( TorrentCellRenderer * cell,
|
|||
const tr_torrent * tor = p->tor;
|
||||
const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );
|
||||
const tr_info * inf = tr_torrentInfo( tor );
|
||||
const gboolean active = st->activity != TR_STATUS_STOPPED;
|
||||
const gboolean active = ( st->activity != TR_STATUS_STOPPED ) && ( st->activity != TR_STATUS_DOWNLOAD_WAIT ) && ( st->activity != TR_STATUS_SEED_WAIT );
|
||||
const double percentDone = get_percent_done( tor, st, &seed );
|
||||
const gboolean sensitive = active || st->error;
|
||||
GString * gstr_prog = p->gstr1;
|
||||
|
@ -793,7 +804,7 @@ render_full( TorrentCellRenderer * cell,
|
|||
gtr_cell_renderer_render( p->text_renderer, window, widget, &name_area, flags );
|
||||
g_object_set( p->text_renderer, "text", gstr_prog->str, "scale", SMALL_SCALE, "weight", PANGO_WEIGHT_NORMAL, NULL );
|
||||
gtr_cell_renderer_render( p->text_renderer, window, widget, &prog_area, flags );
|
||||
g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", "", "sensitive", sensitive,
|
||||
g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", "", "sensitive", ( sensitive || st->queuePosition >= 0 ),
|
||||
#if GTK_CHECK_VERSION( 3,0,0 )
|
||||
"inverted", seed,
|
||||
#elif GTK_CHECK_VERSION( 2,6,0 )
|
||||
|
@ -801,7 +812,7 @@ render_full( TorrentCellRenderer * cell,
|
|||
#endif
|
||||
NULL );
|
||||
gtr_cell_renderer_render( p->progress_renderer, window, widget, &prct_area, flags );
|
||||
g_object_set( p->text_renderer, "text", gstr_stat->str, NULL );
|
||||
g_object_set( p->text_renderer, "text", gstr_stat->str, FOREGROUND_COLOR_KEY, &text_color, NULL );
|
||||
gtr_cell_renderer_render( p->text_renderer, window, widget, &stat_area, flags );
|
||||
|
||||
/* cleanup */
|
||||
|
|
|
@ -247,6 +247,7 @@ core_init( GTypeInstance * instance, gpointer g_class UNUSED )
|
|||
G_TYPE_INT, /* tr_stat.activity */
|
||||
G_TYPE_UCHAR, /* tr_stat.finished */
|
||||
G_TYPE_CHAR, /* tr_priority_t */
|
||||
G_TYPE_INT, /* tr_stat.queuePosition */
|
||||
G_TYPE_UINT, /* build_torrent_trackers_hash() */
|
||||
G_TYPE_INT, /* MC_ERROR */
|
||||
G_TYPE_INT }; /* MC_ACTIVE_PEER_COUNT */
|
||||
|
@ -457,6 +458,15 @@ compare_by_name( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointer us
|
|||
return tr_strcmp0( ca, cb );
|
||||
}
|
||||
|
||||
static int
|
||||
compare_by_queue( const tr_stat * a, const tr_stat * b )
|
||||
{
|
||||
const bool a_is_queued = a->queuePosition >= 0;
|
||||
const bool b_is_queued = b->queuePosition >= 0;
|
||||
if( a_is_queued != b_is_queued ) return a_is_queued ? -1 : 1;
|
||||
return b->queuePosition - a->queuePosition;
|
||||
}
|
||||
|
||||
static int
|
||||
compare_by_ratio( GtkTreeModel* m, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data )
|
||||
{
|
||||
|
@ -470,6 +480,7 @@ compare_by_ratio( GtkTreeModel* m, GtkTreeIter * a, GtkTreeIter * b, gpointer us
|
|||
sb = tr_torrentStatCached( tb );
|
||||
|
||||
if( !ret ) ret = compare_ratio( sa->ratio, sb->ratio );
|
||||
if( !ret ) ret = compare_by_queue( sa, sb );
|
||||
if( !ret ) ret = compare_by_name( m, a, b, user_data );
|
||||
return ret;
|
||||
}
|
||||
|
@ -495,6 +506,7 @@ compare_by_activity( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointe
|
|||
|
||||
if( !ret ) ret = compare_double( aUp+aDown, bUp+bDown );
|
||||
if( !ret ) ret = compare_uint64( sa->uploadedEver, sb->uploadedEver );
|
||||
if( !ret ) ret = compare_by_queue( sa, sb );
|
||||
if( !ret ) ret = compare_by_name( m, a, b, user_data );
|
||||
return ret;
|
||||
}
|
||||
|
@ -569,11 +581,13 @@ compare_by_state( GtkTreeModel * m, GtkTreeIter * a, GtkTreeIter * b, gpointer u
|
|||
{
|
||||
int ret = 0;
|
||||
int sa, sb;
|
||||
tr_torrent *ta, *tb;
|
||||
|
||||
gtk_tree_model_get( m, a, MC_ACTIVITY, &sa, -1 );
|
||||
gtk_tree_model_get( m, b, MC_ACTIVITY, &sb, -1 );
|
||||
gtk_tree_model_get( m, a, MC_ACTIVITY, &sa, MC_TORRENT, &ta, -1 );
|
||||
gtk_tree_model_get( m, b, MC_ACTIVITY, &sb, MC_TORRENT, &tb, -1 );
|
||||
|
||||
if( !ret ) ret = compare_int( sa, sb );
|
||||
if( !ret ) ret = compare_by_queue( tr_torrentStatCached( ta ), tr_torrentStatCached( tb ) );
|
||||
if( !ret ) ret = compare_by_progress( m, a, b, u );
|
||||
return ret;
|
||||
}
|
||||
|
@ -1026,6 +1040,7 @@ gtr_core_add_torrent( TrCore * core, tr_torrent * tor, gboolean do_notify )
|
|||
MC_ACTIVITY, st->activity,
|
||||
MC_FINISHED, st->finished,
|
||||
MC_PRIORITY, tr_torrentGetPriority( tor ),
|
||||
MC_QUEUE_POSITION, st->queuePosition,
|
||||
MC_TRACKERS, trackers_hash,
|
||||
-1 );
|
||||
|
||||
|
@ -1412,6 +1427,7 @@ update_foreach( GtkTreeModel * model, GtkTreeIter * iter )
|
|||
int oldActivePeerCount, newActivePeerCount;
|
||||
int oldError, newError;
|
||||
bool oldFinished, newFinished;
|
||||
int oldQueuePosition, newQueuePosition;
|
||||
tr_priority_t oldPriority, newPriority;
|
||||
unsigned int oldTrackers, newTrackers;
|
||||
double oldUpSpeed, newUpSpeed;
|
||||
|
@ -1430,6 +1446,7 @@ update_foreach( GtkTreeModel * model, GtkTreeIter * iter )
|
|||
MC_ACTIVITY, &oldActivity,
|
||||
MC_FINISHED, &oldFinished,
|
||||
MC_PRIORITY, &oldPriority,
|
||||
MC_QUEUE_POSITION, &oldQueuePosition,
|
||||
MC_TRACKERS, &oldTrackers,
|
||||
MC_SPEED_UP, &oldUpSpeed,
|
||||
MC_RECHECK_PROGRESS, &oldRecheckProgress,
|
||||
|
@ -1442,6 +1459,7 @@ update_foreach( GtkTreeModel * model, GtkTreeIter * iter )
|
|||
newActivity = st->activity;
|
||||
newFinished = st->finished;
|
||||
newPriority = tr_torrentGetPriority( tor );
|
||||
newQueuePosition = st->queuePosition;
|
||||
newTrackers = build_torrent_trackers_hash( tor );
|
||||
newUpSpeed = st->pieceUploadSpeed_KBps;
|
||||
newDownSpeed = st->pieceDownloadSpeed_KBps;
|
||||
|
@ -1455,6 +1473,7 @@ update_foreach( GtkTreeModel * model, GtkTreeIter * iter )
|
|||
|| ( newActivity != oldActivity )
|
||||
|| ( newFinished != oldFinished )
|
||||
|| ( newPriority != oldPriority )
|
||||
|| ( newQueuePosition != oldQueuePosition )
|
||||
|| ( newError != oldError )
|
||||
|| ( newActivePeerCount != oldActivePeerCount )
|
||||
|| ( newTrackers != oldTrackers )
|
||||
|
@ -1469,6 +1488,7 @@ update_foreach( GtkTreeModel * model, GtkTreeIter * iter )
|
|||
MC_ACTIVITY, newActivity,
|
||||
MC_FINISHED, newFinished,
|
||||
MC_PRIORITY, newPriority,
|
||||
MC_QUEUE_POSITION, newQueuePosition,
|
||||
MC_TRACKERS, newTrackers,
|
||||
MC_SPEED_UP, newUpSpeed,
|
||||
MC_SPEED_DOWN, newDownSpeed,
|
||||
|
|
|
@ -193,6 +193,7 @@ enum
|
|||
MC_ACTIVITY,
|
||||
MC_FINISHED,
|
||||
MC_PRIORITY,
|
||||
MC_QUEUE_POSITION,
|
||||
MC_TRACKERS,
|
||||
|
||||
/* tr_stat.error
|
||||
|
|
|
@ -252,6 +252,62 @@ target_cb( GtkWidget * tb, gpointer target )
|
|||
gtk_widget_set_sensitive( GTK_WIDGET( target ), b );
|
||||
}
|
||||
|
||||
/****
|
||||
***** Download Tab
|
||||
****/
|
||||
|
||||
static GtkWidget*
|
||||
downloadPage( GObject * core )
|
||||
{
|
||||
GtkWidget * t;
|
||||
GtkWidget * w;
|
||||
GtkWidget * l;
|
||||
const char * s;
|
||||
int row = 0;
|
||||
|
||||
t = hig_workarea_create( );
|
||||
|
||||
hig_workarea_add_section_title( t, &row, _( "Location" ) );
|
||||
|
||||
w = new_path_chooser_button( TR_PREFS_KEY_DOWNLOAD_DIR, core );
|
||||
hig_workarea_add_row( t, &row, _( "Save to _Location:" ), w, NULL );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Queue" ) );
|
||||
|
||||
s = _( "Maximum active _downloads:" );
|
||||
w = new_spin_button( TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, core, 0, INT_MAX, 1 );
|
||||
hig_workarea_add_row( t, &row, s, w, NULL );
|
||||
|
||||
s = _( "E_xempt torrents if idle for N minutes:" );
|
||||
w = new_spin_button( TR_PREFS_KEY_QUEUE_STALLED_MINUTES, core, 1, INT_MAX, 1 );
|
||||
hig_workarea_add_row( t, &row, s, w, NULL );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Incomplete" ) );
|
||||
|
||||
s = _( "Append \"._part\" to incomplete files' names" );
|
||||
w = new_check_button( s, TR_PREFS_KEY_RENAME_PARTIAL_FILES, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
s = _( "Keep _incomplete torrents in:" );
|
||||
l = new_check_button( s, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, core );
|
||||
w = new_path_chooser_button( TR_PREFS_KEY_INCOMPLETE_DIR, core );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED ) );
|
||||
g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
|
||||
hig_workarea_add_row_w( t, &row, l, w, NULL );
|
||||
|
||||
s = _( "Call _script when torrent is completed:" );
|
||||
l = new_check_button( s, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, core );
|
||||
w = new_file_chooser_button( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, core );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED ) );
|
||||
g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
|
||||
hig_workarea_add_row_w( t, &row, l, w, NULL );
|
||||
|
||||
hig_workarea_finish( t, &row );
|
||||
return t;
|
||||
}
|
||||
|
||||
/****
|
||||
***** Torrent Tab
|
||||
****/
|
||||
|
@ -291,30 +347,6 @@ torrentPage( GObject * core )
|
|||
hig_workarea_add_row_w( t, &row, l, w, NULL );
|
||||
#endif
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Downloading" ) );
|
||||
|
||||
s = _( "Append \"._part\" to incomplete files' names" );
|
||||
w = new_check_button( s, TR_PREFS_KEY_RENAME_PARTIAL_FILES, core );
|
||||
hig_workarea_add_wide_control( t, &row, w );
|
||||
|
||||
w = new_path_chooser_button( TR_PREFS_KEY_DOWNLOAD_DIR, core );
|
||||
hig_workarea_add_row( t, &row, _( "Save to _Location:" ), w, NULL );
|
||||
|
||||
s = _( "Keep _incomplete torrents in:" );
|
||||
l = new_check_button( s, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, core );
|
||||
w = new_path_chooser_button( TR_PREFS_KEY_INCOMPLETE_DIR, core );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED ) );
|
||||
g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
|
||||
hig_workarea_add_row_w( t, &row, l, w, NULL );
|
||||
|
||||
s = _( "Call scrip_t when torrent is completed:" );
|
||||
l = new_check_button( s, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, core );
|
||||
w = new_file_chooser_button( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, core );
|
||||
gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED ) );
|
||||
g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
|
||||
hig_workarea_add_row_w( t, &row, l, w, NULL );
|
||||
|
||||
hig_workarea_add_section_divider( t, &row );
|
||||
hig_workarea_add_section_title( t, &row, _( "Seeding" ) );
|
||||
|
||||
|
@ -1251,6 +1283,9 @@ gtr_prefs_dialog_new( GtkWindow * parent, GObject * core )
|
|||
gtk_notebook_append_page( GTK_NOTEBOOK( n ),
|
||||
torrentPage( core ),
|
||||
gtk_label_new ( _( "Torrents" ) ) );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( n ),
|
||||
downloadPage( core ),
|
||||
gtk_label_new ( _( "Downloading" ) ) );
|
||||
gtk_notebook_append_page( GTK_NOTEBOOK( n ),
|
||||
bandwidthPage( core ),
|
||||
gtk_label_new ( _( "Speed" ) ) );
|
||||
|
|
|
@ -596,7 +596,7 @@ gtr_window_new( GtkUIManager * ui_mgr, TrCore * core )
|
|||
|
||||
/* main menu */
|
||||
mainmenu = gtr_action_get_widget( "/main-window-menu" );
|
||||
w = gtr_action_get_widget( "/main-window-menu/torrent-menu/update-tracker" );
|
||||
w = gtr_action_get_widget( "/main-window-menu/torrent-menu/torrent-reannounce" );
|
||||
#if GTK_CHECK_VERSION( 2, 12, 0 )
|
||||
g_signal_connect( w, "query-tooltip",
|
||||
G_CALLBACK( onAskTrackerQueryTooltip ), p );
|
||||
|
|
38
gtk/ui.h
38
gtk/ui.h
|
@ -21,13 +21,20 @@ static const char * fallback_ui_file =
|
|||
" <menuitem action='show-torrent-properties'/>\n"
|
||||
" <menuitem action='open-torrent-folder'/>\n"
|
||||
" <separator/>\n"
|
||||
" <menuitem action='start-torrent'/>\n"
|
||||
" <menuitem action='update-tracker'/>\n"
|
||||
" <menuitem action='pause-torrent'/>\n"
|
||||
" <menuitem action='copy-magnet-link-to-clipboard'/>\n"
|
||||
" <menuitem action='torrent-start'/>\n"
|
||||
" <menuitem action='torrent-start-now'/>\n"
|
||||
" <menuitem action='torrent-reannounce'/>\n"
|
||||
" <menu action='queue-menu'>\n"
|
||||
" <menuitem action='queue-move-top'/>\n"
|
||||
" <menuitem action='queue-move-up'/>\n"
|
||||
" <menuitem action='queue-move-down'/>\n"
|
||||
" <menuitem action='queue-move-bottom'/>\n"
|
||||
" </menu>\n"
|
||||
" <menuitem action='torrent-stop'/>\n"
|
||||
" <separator/>\n"
|
||||
" <menuitem action='relocate-torrent'/>\n"
|
||||
" <menuitem action='verify-torrent'/>\n"
|
||||
" <menuitem action='torrent-verify'/>\n"
|
||||
" <menuitem action='copy-magnet-link-to-clipboard'/>\n"
|
||||
" <separator/>\n"
|
||||
" <menuitem action='remove-torrent'/>\n"
|
||||
" <menuitem action='delete-torrent'/>\n"
|
||||
|
@ -63,8 +70,8 @@ static const char * fallback_ui_file =
|
|||
"\n"
|
||||
" <toolbar name='main-window-toolbar'>\n"
|
||||
" <toolitem action='open-torrent-toolbar'/>\n"
|
||||
" <toolitem action='start-torrent'/>\n"
|
||||
" <toolitem action='pause-torrent'/>\n"
|
||||
" <toolitem action='torrent-start'/>\n"
|
||||
" <toolitem action='torrent-stop'/>\n"
|
||||
" <toolitem action='remove-torrent'/>\n"
|
||||
" <separator/>\n"
|
||||
" <toolitem action='show-torrent-properties'/>\n"
|
||||
|
@ -87,13 +94,20 @@ static const char * fallback_ui_file =
|
|||
" <menuitem action='sort-reversed'/>\n"
|
||||
" </menu>\n"
|
||||
" <separator/>\n"
|
||||
" <menuitem action='start-torrent'/>\n"
|
||||
" <menuitem action='update-tracker'/>\n"
|
||||
" <menuitem action='pause-torrent'/>\n"
|
||||
" <menuitem action='copy-magnet-link-to-clipboard'/>\n"
|
||||
" <menuitem action='torrent-start'/>\n"
|
||||
" <menuitem action='torrent-start-now'/>\n"
|
||||
" <menuitem action='torrent-reannounce'/>\n"
|
||||
" <menu action='queue-menu'>\n"
|
||||
" <menuitem action='queue-move-top'/>\n"
|
||||
" <menuitem action='queue-move-up'/>\n"
|
||||
" <menuitem action='queue-move-down'/>\n"
|
||||
" <menuitem action='queue-move-bottom'/>\n"
|
||||
" </menu>\n"
|
||||
" <menuitem action='torrent-stop'/>\n"
|
||||
" <separator/>\n"
|
||||
" <menuitem action='verify-torrent'/>\n"
|
||||
" <menuitem action='relocate-torrent'/>\n"
|
||||
" <menuitem action='torrent-verify'/>\n"
|
||||
" <menuitem action='copy-magnet-link-to-clipboard'/>\n"
|
||||
" <separator/>\n"
|
||||
" <menuitem action='remove-torrent'/>\n"
|
||||
" <menuitem action='delete-torrent'/>\n"
|
||||
|
|
|
@ -530,12 +530,15 @@ torrentNew( tr_peerMgr * manager, tr_torrent * tor )
|
|||
return t;
|
||||
}
|
||||
|
||||
static void ensureMgrTimersExist( struct tr_peerMgr * m );
|
||||
|
||||
tr_peerMgr*
|
||||
tr_peerMgrNew( tr_session * session )
|
||||
{
|
||||
tr_peerMgr * m = tr_new0( tr_peerMgr, 1 );
|
||||
m->session = session;
|
||||
m->incomingHandshakes = TR_PTR_ARRAY_INIT;
|
||||
ensureMgrTimersExist( m );
|
||||
return m;
|
||||
}
|
||||
|
||||
|
@ -3557,23 +3560,42 @@ pumpAllPeers( tr_peerMgr * mgr )
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
queuePulse( tr_session * session, tr_direction dir )
|
||||
{
|
||||
assert( tr_isSession( session ) );
|
||||
assert( tr_isDirection( dir ) );
|
||||
|
||||
if( tr_sessionGetQueueEnabled( session, dir ) )
|
||||
{
|
||||
int i;
|
||||
const int n = tr_sessionCountQueueFreeSlots( session, dir );
|
||||
for( i=0; i<n; i++ ) {
|
||||
tr_torrent * tor = tr_sessionGetNextQueuedTorrent( session, dir );
|
||||
if( tor != NULL )
|
||||
tr_torrentStartNow( tor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bandwidthPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
|
||||
{
|
||||
tr_torrent * tor;
|
||||
tr_peerMgr * mgr = vmgr;
|
||||
tr_session * session = mgr->session;
|
||||
managerLock( mgr );
|
||||
|
||||
/* FIXME: this next line probably isn't necessary... */
|
||||
pumpAllPeers( mgr );
|
||||
|
||||
/* allocate bandwidth to the peers */
|
||||
tr_bandwidthAllocate( &mgr->session->bandwidth, TR_UP, BANDWIDTH_PERIOD_MSEC );
|
||||
tr_bandwidthAllocate( &mgr->session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC );
|
||||
tr_bandwidthAllocate( &session->bandwidth, TR_UP, BANDWIDTH_PERIOD_MSEC );
|
||||
tr_bandwidthAllocate( &session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC );
|
||||
|
||||
/* torrent upkeep */
|
||||
tor = NULL;
|
||||
while(( tor = tr_torrentNext( mgr->session, tor )))
|
||||
while(( tor = tr_torrentNext( session, tor )))
|
||||
{
|
||||
/* possibly stop torrents that have seeded enough */
|
||||
tr_torrentCheckSeedLimit( tor );
|
||||
|
@ -3590,6 +3612,10 @@ bandwidthPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
|
|||
tr_torrentStop( tor );
|
||||
}
|
||||
|
||||
/* pump the queues */
|
||||
queuePulse( session, TR_UP );
|
||||
queuePulse( session, TR_DOWN );
|
||||
|
||||
reconnectPulse( 0, 0, mgr );
|
||||
|
||||
tr_timerAddMsec( mgr->bandwidthTimer, BANDWIDTH_PERIOD_MSEC );
|
||||
|
|
|
@ -186,6 +186,70 @@ getTorrents( tr_session * session,
|
|||
return torrents;
|
||||
}
|
||||
|
||||
static void
|
||||
notifyBatchChange( tr_session * session, tr_torrent ** torrents, int n )
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<n; ++i )
|
||||
notify( session, TR_RPC_TORRENT_CHANGED, torrents[i] );
|
||||
}
|
||||
|
||||
static const char*
|
||||
queueMoveTop( tr_session * session,
|
||||
tr_benc * args_in,
|
||||
tr_benc * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED )
|
||||
{
|
||||
int n;
|
||||
tr_torrent ** torrents = getTorrents( session, args_in, &n );
|
||||
tr_torrentsQueueMoveTop( torrents, n );
|
||||
notifyBatchChange( session, torrents, n );
|
||||
tr_free( torrents );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
queueMoveUp( tr_session * session,
|
||||
tr_benc * args_in,
|
||||
tr_benc * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED )
|
||||
{
|
||||
int n;
|
||||
tr_torrent ** torrents = getTorrents( session, args_in, &n );
|
||||
tr_torrentsQueueMoveUp( torrents, n );
|
||||
notifyBatchChange( session, torrents, n );
|
||||
tr_free( torrents );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
queueMoveDown( tr_session * session,
|
||||
tr_benc * args_in,
|
||||
tr_benc * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED )
|
||||
{
|
||||
int n;
|
||||
tr_torrent ** torrents = getTorrents( session, args_in, &n );
|
||||
tr_torrentsQueueMoveDown( torrents, n );
|
||||
notifyBatchChange( session, torrents, n );
|
||||
tr_free( torrents );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
queueMoveBottom( tr_session * session,
|
||||
tr_benc * args_in,
|
||||
tr_benc * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED )
|
||||
{
|
||||
int n;
|
||||
tr_torrent ** torrents = getTorrents( session, args_in, &n );
|
||||
tr_torrentsQueueMoveBottom( torrents, n );
|
||||
notifyBatchChange( session, torrents, n );
|
||||
tr_free( torrents );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
torrentStart( tr_session * session,
|
||||
tr_benc * args_in,
|
||||
|
@ -210,6 +274,30 @@ torrentStart( tr_session * session,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
torrentStartNow( tr_session * session,
|
||||
tr_benc * args_in,
|
||||
tr_benc * args_out UNUSED,
|
||||
struct tr_rpc_idle_data * idle_data UNUSED )
|
||||
{
|
||||
int i, torrentCount;
|
||||
tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
|
||||
|
||||
assert( idle_data == NULL );
|
||||
|
||||
for( i = 0; i < torrentCount; ++i )
|
||||
{
|
||||
tr_torrent * tor = torrents[i];
|
||||
if( !tor->isRunning )
|
||||
{
|
||||
tr_torrentStartNow( tor );
|
||||
notify( session, TR_RPC_TORRENT_STARTED, tor );
|
||||
}
|
||||
}
|
||||
tr_free( torrents );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char*
|
||||
torrentStop( tr_session * session,
|
||||
tr_benc * args_in,
|
||||
|
@ -225,7 +313,7 @@ torrentStop( tr_session * session,
|
|||
{
|
||||
tr_torrent * tor = torrents[i];
|
||||
|
||||
if( tor->isRunning )
|
||||
if( tor->isRunning || ( tor->queuePosition >= 0 ) )
|
||||
{
|
||||
tor->isStopping = true;
|
||||
notify( session, TR_RPC_TORRENT_STOPPED, tor );
|
||||
|
@ -578,6 +666,8 @@ addField( const tr_torrent * const tor,
|
|||
for( i = 0; i < inf->fileCount; ++i )
|
||||
tr_bencListAddInt( p, inf->files[i].priority );
|
||||
}
|
||||
else if( tr_streq( key, keylen, "queuePosition" ) )
|
||||
tr_bencDictAddInt( d, key, st->queuePosition );
|
||||
else if( tr_streq( key, keylen, "rateDownload" ) )
|
||||
tr_bencDictAddInt( d, key, toSpeedBytes( st->pieceDownloadSpeed_KBps ) );
|
||||
else if( tr_streq( key, keylen, "rateUpload" ) )
|
||||
|
@ -1017,6 +1107,8 @@ torrentSet( tr_session * session,
|
|||
tr_torrentSetRatioLimit( tor, d );
|
||||
if( tr_bencDictFindInt( args_in, "seedRatioMode", &tmp ) )
|
||||
tr_torrentSetRatioMode( tor, tmp );
|
||||
if( tr_bencDictFindInt( args_in, "queuePosition", &tmp ) )
|
||||
tr_torrentSetQueuePosition( tor, tmp );
|
||||
if( !errmsg && tr_bencDictFindList( args_in, "trackerAdd", &trackers ) )
|
||||
errmsg = addTrackerUrls( tor, trackers );
|
||||
if( !errmsg && tr_bencDictFindList( args_in, "trackerRemove", &trackers ) )
|
||||
|
@ -1465,6 +1557,10 @@ sessionSet( tr_session * session,
|
|||
tr_blocklistSetURL( session, str );
|
||||
if( tr_bencDictFindStr( args_in, TR_PREFS_KEY_DOWNLOAD_DIR, &str ) )
|
||||
tr_sessionSetDownloadDir( session, str );
|
||||
if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, &boolVal ) )
|
||||
tr_sessionSetQueueEnabled ( session, TR_DOWN, boolVal );
|
||||
if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, &i ) )
|
||||
tr_sessionSetQueueSize( session, TR_DOWN, i );
|
||||
if( tr_bencDictFindStr( args_in, TR_PREFS_KEY_INCOMPLETE_DIR, &str ) )
|
||||
tr_sessionSetIncompleteDir( session, str );
|
||||
if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, &boolVal ) )
|
||||
|
@ -1499,6 +1595,10 @@ sessionSet( tr_session * session,
|
|||
tr_sessionSetIdleLimited( session, boolVal );
|
||||
if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_START, &boolVal ) )
|
||||
tr_sessionSetPaused( session, !boolVal );
|
||||
if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_SEED_QUEUE_ENABLED, &boolVal ) )
|
||||
tr_sessionSetQueueEnabled ( session, TR_UP, boolVal );
|
||||
if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_SEED_QUEUE_SIZE, &i ) )
|
||||
tr_sessionSetQueueSize( session, TR_UP, i );
|
||||
if( tr_bencDictFindStr( args_in, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, &str ) )
|
||||
tr_sessionSetTorrentDoneScript( session, str );
|
||||
if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, &boolVal ) )
|
||||
|
@ -1597,6 +1697,8 @@ sessionGet( tr_session * s,
|
|||
tr_bencDictAddInt ( d, "blocklist-size", tr_blocklistGetRuleCount( s ) );
|
||||
tr_bencDictAddStr ( d, "config-dir", tr_sessionGetConfigDir( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_sessionGetDownloadDir( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, tr_sessionGetQueueEnabled( s, TR_DOWN ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, tr_sessionGetQueueSize( s, TR_DOWN ) );
|
||||
tr_bencDictAddInt ( d, "download-dir-free-space", tr_sessionGetDownloadDirFreeSpace( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, tr_sessionGetPeerLimit( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, tr_sessionGetPeerLimitPerTorrent( s ) );
|
||||
|
@ -1616,6 +1718,8 @@ sessionGet( tr_session * s,
|
|||
tr_bencDictAddBool( d, "seedRatioLimited", tr_sessionIsRatioLimited( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT, tr_sessionGetIdleLimit( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, tr_sessionIsIdleLimited( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SEED_QUEUE_ENABLED, tr_sessionGetQueueEnabled( s, TR_UP ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_SEED_QUEUE_SIZE, tr_sessionGetQueueSize( s, TR_UP ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_START, !tr_sessionGetPaused( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL, tr_sessionGetDeleteSource( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps, tr_sessionGetSpeedLimit_KBps( s, TR_UP ) );
|
||||
|
@ -1676,9 +1780,14 @@ methods[] =
|
|||
{ "torrent-set", true, torrentSet },
|
||||
{ "torrent-set-location", true, torrentSetLocation },
|
||||
{ "torrent-start", true, torrentStart },
|
||||
{ "torrent-start-now", true, torrentStartNow },
|
||||
{ "torrent-stop", true, torrentStop },
|
||||
{ "torrent-verify", true, torrentVerify },
|
||||
{ "torrent-reannounce", true, torrentReannounce }
|
||||
{ "torrent-reannounce", true, torrentReannounce },
|
||||
{ "queue-move-top", true, queueMoveTop },
|
||||
{ "queue-move-up", true, queueMoveUp },
|
||||
{ "queue-move-down", true, queueMoveDown },
|
||||
{ "queue-move-bottom", true, queueMoveBottom }
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
|
@ -304,62 +304,67 @@ tr_sessionGetDefaultSettings( tr_benc * d )
|
|||
assert( tr_bencIsDict( d ) );
|
||||
|
||||
tr_bencDictReserve( d, 60 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL, "http://www.example.com/blocklist" );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB, DEFAULT_CACHE_SIZE_MB );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_getDefaultDownloadDir( ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps, 100 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, TR_DEFAULT_ENCRYPTION );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT, 30 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_getDefaultDownloadDir( ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, TR_MSG_INF );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, atoi( TR_DEFAULT_PEER_PORT_STR ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, 49152 );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, 65535 );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS, TR_DEFAULT_PEER_SOCKET_TOS_STR );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, true );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, TR_PREALLOCATE_SPARSE );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PREFETCH_ENABLED, DEFAULT_PREFETCH_ENABLED );
|
||||
tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO, 2.0 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED, false );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS, "0.0.0.0" );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD, "" );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME, "" );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST, TR_DEFAULT_RPC_WHITELIST );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, true );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT, atoi( TR_DEFAULT_RPC_PORT_STR ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL, TR_DEFAULT_RPC_URL_STR );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS, true );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, "" );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, false );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps, 50 ); /* half the regular */
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps, 50 ); /* half the regular */
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, 540 ); /* 9am */
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END, 1020 ); /* 5pm */
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, TR_SCHED_ALL );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps, 100 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK, 022 );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, 14 );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, TR_DEFAULT_BIND_ADDRESS_IPV4 );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, TR_DEFAULT_BIND_ADDRESS_IPV6 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_START, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL, false );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL, "http://www.example.com/blocklist" );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB, DEFAULT_CACHE_SIZE_MB );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_getDefaultDownloadDir( ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps, 100 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, TR_DEFAULT_ENCRYPTION );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT, 30 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_getDefaultDownloadDir( ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, TR_MSG_INF );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, 10 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, true );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, atoi( TR_DEFAULT_PEER_PORT_STR ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, 49152 );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, 65535 );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS, TR_DEFAULT_PEER_SOCKET_TOS_STR );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, true );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, TR_PREALLOCATE_SPARSE );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PREFETCH_ENABLED, DEFAULT_PREFETCH_ENABLED );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_QUEUE_STALLED_MINUTES, 30 );
|
||||
tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO, 2.0 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED, false );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS, "0.0.0.0" );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, false );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD, "" );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME, "" );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST, TR_DEFAULT_RPC_WHITELIST );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, true );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT, atoi( TR_DEFAULT_RPC_PORT_STR ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL, TR_DEFAULT_RPC_URL_STR );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS, true );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, "" );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_SEED_QUEUE_SIZE, 10 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SEED_QUEUE_ENABLED, false );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps, 50 ); /* half the regular */
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps, 50 ); /* half the regular */
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, 540 ); /* 9am */
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END, 1020 ); /* 5pm */
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, TR_SCHED_ALL );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps, 100 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED, false );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK, 022 );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, 14 );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, TR_DEFAULT_BIND_ADDRESS_IPV4 );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, TR_DEFAULT_BIND_ADDRESS_IPV6 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_START, true );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL, false );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -368,63 +373,68 @@ tr_sessionGetSettings( tr_session * s, struct tr_benc * d )
|
|||
assert( tr_bencIsDict( d ) );
|
||||
|
||||
tr_bencDictReserve( d, 60 );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, tr_blocklistIsEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL, tr_blocklistGetURL( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB, tr_sessionGetCacheLimit_MB( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED, s->isDHTEnabled );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED, s->isUTPEnabled );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED, s->isLPDEnabled );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, s->downloadDir );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps, tr_sessionGetSpeedLimit_KBps( s, TR_DOWN ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, tr_sessionIsSpeedLimited( s, TR_DOWN ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, s->encryptionMode );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT, tr_sessionGetIdleLimit( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, tr_sessionIsIdleLimited( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_sessionGetIncompleteDir( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, tr_sessionIsIncompleteDirEnabled( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, tr_getMessageLevel( ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, s->peerLimit );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, s->peerLimitPerTorrent );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, s->isPortRandom );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, s->randomPortLow );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, s->randomPortHigh );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS, format_tos(s->peerSocketTOS) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM, s->peer_congestion_algorithm );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, s->isPexEnabled );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, s->preallocationMode );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREFETCH_ENABLED, s->isPrefetchEnabled );
|
||||
tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO, s->desiredRatio );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED, s->isRatioLimited );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES, tr_sessionIsIncompleteFileNamingEnabled( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED, tr_sessionIsRPCPasswordEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS, tr_sessionGetRPCBindAddress( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, tr_sessionIsRPCEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD, tr_sessionGetRPCPassword( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT, tr_sessionGetRPCPort( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL, tr_sessionGetRPCUrl( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME, tr_sessionGetRPCUsername( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST, tr_sessionGetRPCWhitelist( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, tr_sessionGetRPCWhitelistEnabled( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS, s->scrapePausedTorrents );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, tr_sessionIsTorrentDoneScriptEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, tr_sessionGetTorrentDoneScript( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED, tr_sessionUsesAltSpeed( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps, tr_sessionGetAltSpeed_KBps( s, TR_UP ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps, tr_sessionGetAltSpeed_KBps( s, TR_DOWN ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, tr_sessionGetAltSpeedBegin( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, tr_sessionUsesAltSpeedTime( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END, tr_sessionGetAltSpeedEnd( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, tr_sessionGetAltSpeedDay( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps, tr_sessionGetSpeedLimit_KBps( s, TR_UP ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED, tr_sessionIsSpeedLimited( s, TR_UP ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK, s->umask );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, s->uploadSlotsPerTorrent );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, tr_address_to_string( &s->public_ipv4->addr ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, tr_address_to_string( &s->public_ipv6->addr ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_START, !tr_sessionGetPaused( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL, tr_sessionGetDeleteSource( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED, tr_blocklistIsEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL, tr_blocklistGetURL( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB, tr_sessionGetCacheLimit_MB( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED, s->isDHTEnabled );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED, s->isUTPEnabled );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED, s->isLPDEnabled );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, s->downloadDir );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, tr_sessionGetQueueSize( s, TR_DOWN ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, tr_sessionGetQueueEnabled( s, TR_DOWN ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps, tr_sessionGetSpeedLimit_KBps( s, TR_DOWN ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED, tr_sessionIsSpeedLimited( s, TR_DOWN ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION, s->encryptionMode );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT, tr_sessionGetIdleLimit( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, tr_sessionIsIdleLimited( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_sessionGetIncompleteDir( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, tr_sessionIsIncompleteDirEnabled( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, tr_getMessageLevel( ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, s->peerLimit );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, s->peerLimitPerTorrent );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, s->isPortRandom );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, s->randomPortLow );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, s->randomPortHigh );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS, format_tos(s->peerSocketTOS) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM, s->peer_congestion_algorithm );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED, s->isPexEnabled );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING, tr_sessionIsPortForwardingEnabled( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION, s->preallocationMode );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_PREFETCH_ENABLED, s->isPrefetchEnabled );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_QUEUE_STALLED_MINUTES, tr_sessionGetQueueStalledMinutes( s ) );
|
||||
tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO, s->desiredRatio );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED, s->isRatioLimited );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES, tr_sessionIsIncompleteFileNamingEnabled( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED, tr_sessionIsRPCPasswordEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS, tr_sessionGetRPCBindAddress( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED, tr_sessionIsRPCEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD, tr_sessionGetRPCPassword( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT, tr_sessionGetRPCPort( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL, tr_sessionGetRPCUrl( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME, tr_sessionGetRPCUsername( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST, tr_sessionGetRPCWhitelist( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED, tr_sessionGetRPCWhitelistEnabled( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS, s->scrapePausedTorrents );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, tr_sessionIsTorrentDoneScriptEnabled( s ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, tr_sessionGetTorrentDoneScript( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_SEED_QUEUE_SIZE, tr_sessionGetQueueSize( s, TR_UP ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_SEED_QUEUE_ENABLED, tr_sessionGetQueueEnabled( s, TR_UP ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED, tr_sessionUsesAltSpeed( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps, tr_sessionGetAltSpeed_KBps( s, TR_UP ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps, tr_sessionGetAltSpeed_KBps( s, TR_DOWN ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN, tr_sessionGetAltSpeedBegin( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED, tr_sessionUsesAltSpeedTime( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END, tr_sessionGetAltSpeedEnd( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY, tr_sessionGetAltSpeedDay( s ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps, tr_sessionGetSpeedLimit_KBps( s, TR_UP ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED, tr_sessionIsSpeedLimited( s, TR_UP ) );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK, s->umask );
|
||||
tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, s->uploadSlotsPerTorrent );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4, tr_address_to_string( &s->public_ipv4->addr ) );
|
||||
tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6, tr_address_to_string( &s->public_ipv6->addr ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_START, !tr_sessionGetPaused( s ) );
|
||||
tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL, tr_sessionGetDeleteSource( s ) );
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -779,6 +789,18 @@ sessionSetImpl( void * vdata )
|
|||
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_TRASH_ORIGINAL, &boolVal) )
|
||||
tr_sessionSetDeleteSource( session, boolVal );
|
||||
|
||||
/* torrent queues */
|
||||
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_QUEUE_STALLED_MINUTES, &i ) )
|
||||
tr_sessionSetQueueStalledMinutes( session, i );
|
||||
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, &i ) )
|
||||
tr_sessionSetQueueSize( session, TR_DOWN, i );
|
||||
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, &boolVal ) )
|
||||
tr_sessionSetQueueEnabled( session, TR_DOWN, boolVal );
|
||||
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_SEED_QUEUE_SIZE, &i ) )
|
||||
tr_sessionSetQueueSize( session, TR_UP, i );
|
||||
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_SEED_QUEUE_ENABLED, &boolVal ) )
|
||||
tr_sessionSetQueueEnabled( session, TR_UP, boolVal );
|
||||
|
||||
/* files and directories */
|
||||
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PREFETCH_ENABLED, &boolVal ) )
|
||||
session->isPrefetchEnabled = boolVal;
|
||||
|
@ -2600,3 +2622,109 @@ tr_sessionSetTorrentDoneScript( tr_session * session, const char * scriptFilenam
|
|||
session->torrentDoneScript = tr_strdup( scriptFilename );
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
void
|
||||
tr_sessionSetQueueSize( tr_session * session, tr_direction dir, int n )
|
||||
{
|
||||
assert( tr_isSession( session ) );
|
||||
assert( tr_isDirection( dir ) );
|
||||
|
||||
session->queueSize[dir] = n;
|
||||
}
|
||||
|
||||
int
|
||||
tr_sessionGetQueueSize( const tr_session * session, tr_direction dir )
|
||||
{
|
||||
assert( tr_isSession( session ) );
|
||||
assert( tr_isDirection( dir ) );
|
||||
|
||||
return session->queueSize[dir];
|
||||
}
|
||||
|
||||
void
|
||||
tr_sessionSetQueueEnabled( tr_session * session, tr_direction dir, bool is_enabled )
|
||||
{
|
||||
assert( tr_isSession( session ) );
|
||||
assert( tr_isDirection( dir ) );
|
||||
assert( tr_isBool( is_enabled ) );
|
||||
|
||||
session->queueEnabled[dir] = is_enabled;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_sessionGetQueueEnabled( const tr_session * session, tr_direction dir )
|
||||
{
|
||||
assert( tr_isSession( session ) );
|
||||
assert( tr_isDirection( dir ) );
|
||||
|
||||
return session->queueEnabled[dir];
|
||||
}
|
||||
|
||||
void
|
||||
tr_sessionSetQueueStalledMinutes( tr_session * session, int minutes )
|
||||
{
|
||||
assert( tr_isSession( session ) );
|
||||
assert( minutes > 0 );
|
||||
|
||||
session->queueStalledMinutes = minutes;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
tr_sessionGetQueueStalledMinutes( const tr_session * session )
|
||||
{
|
||||
assert( tr_isSession( session ) );
|
||||
|
||||
return session->queueStalledMinutes;
|
||||
}
|
||||
|
||||
tr_torrent *
|
||||
tr_sessionGetNextQueuedTorrent( tr_session * session, tr_direction direction )
|
||||
{
|
||||
tr_torrent * tor = NULL;
|
||||
tr_torrent * best_tor = NULL;
|
||||
int best_position = INT_MAX;
|
||||
|
||||
assert( tr_isSession( session ) );
|
||||
assert( tr_isDirection( direction ) );
|
||||
|
||||
while(( tor = tr_torrentNext( session, tor ))) {
|
||||
if( !tor->isRunning && ( direction == tr_torrentGetQueueDirection( tor ) ) ) {
|
||||
const int position = tr_torrentGetQueuePosition( tor );
|
||||
if( ( position >= 0 ) && ( best_position > position ) ) {
|
||||
best_position = position;
|
||||
best_tor = tor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best_tor;
|
||||
}
|
||||
|
||||
int
|
||||
tr_sessionCountQueueFreeSlots( tr_session * session, tr_direction dir )
|
||||
{
|
||||
tr_torrent * tor;
|
||||
int active_count;
|
||||
const int max = tr_sessionGetQueueSize( session, dir );
|
||||
const tr_torrent_activity activity = TR_UP ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
|
||||
|
||||
if( !tr_sessionGetQueueEnabled( session, dir ) )
|
||||
return INT_MAX;
|
||||
|
||||
tor = NULL;
|
||||
active_count = 0;
|
||||
while(( tor = tr_torrentNext( session, tor )))
|
||||
if( !tr_torrentIsStalled( tor ) )
|
||||
if( tr_torrentGetActivity( tor ) == activity )
|
||||
++active_count;
|
||||
|
||||
if( active_count >= max )
|
||||
return 0;
|
||||
|
||||
return max - active_count;
|
||||
}
|
||||
|
|
|
@ -111,6 +111,10 @@ struct tr_session
|
|||
|
||||
tr_benc removedTorrents;
|
||||
|
||||
bool queueEnabled[2];
|
||||
int queueSize[2];
|
||||
int queueStalledMinutes;
|
||||
|
||||
int umask;
|
||||
|
||||
int speedLimit_Bps[2];
|
||||
|
@ -308,4 +312,10 @@ bool tr_sessionGetActiveSpeedLimit_Bps( const tr_session * session,
|
|||
tr_direction dir,
|
||||
int * setme );
|
||||
|
||||
tr_torrent * tr_sessionGetNextQueuedSeed( tr_session * session );
|
||||
tr_torrent * tr_sessionGetNextQueuedTorrent( tr_session * session, tr_direction );
|
||||
|
||||
int tr_sessionCountQueueFreeSlots( tr_session * session, tr_direction );
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -669,7 +669,7 @@ tr_torrentInitFilePieces( tr_torrent * tor )
|
|||
tr_free( firstFiles );
|
||||
}
|
||||
|
||||
static void torrentStart( tr_torrent * tor );
|
||||
static void torrentStart( tr_torrent * tor, bool bypass_queue );
|
||||
|
||||
/**
|
||||
* Decide on a block size. Constraints:
|
||||
|
@ -802,6 +802,7 @@ torrentInit( tr_torrent * tor, const tr_ctor * ctor )
|
|||
tor->session = session;
|
||||
tor->uniqueId = nextUniqueId++;
|
||||
tor->magicNumber = TORRENT_MAGIC_NUMBER;
|
||||
tor->queuePosition = -1;
|
||||
|
||||
tr_peerIdInit( tor->peer_id );
|
||||
|
||||
|
@ -905,7 +906,7 @@ torrentInit( tr_torrent * tor, const tr_ctor * ctor )
|
|||
}
|
||||
else if( doStart )
|
||||
{
|
||||
torrentStart( tor );
|
||||
tr_torrentStart( tor );
|
||||
}
|
||||
|
||||
tr_sessionUnlock( session );
|
||||
|
@ -1089,25 +1090,61 @@ tr_torrentSetVerifyState( tr_torrent * tor, tr_verify_state state )
|
|||
tor->anyDate = tr_time( );
|
||||
}
|
||||
|
||||
tr_torrent_activity
|
||||
tr_torrentGetActivity( tr_torrent * tor )
|
||||
static tr_torrent_activity
|
||||
torrentGetActivity( const tr_torrent * tor )
|
||||
{
|
||||
const bool is_seed = tr_torrentIsSeed( tor );
|
||||
assert( tr_isTorrent( tor ) );
|
||||
|
||||
tr_torrentRecheckCompleteness( tor );
|
||||
|
||||
if( tor->verifyState == TR_VERIFY_NOW )
|
||||
return TR_STATUS_CHECK;
|
||||
|
||||
if( tor->verifyState == TR_VERIFY_WAIT )
|
||||
return TR_STATUS_CHECK_WAIT;
|
||||
if( !tor->isRunning )
|
||||
return TR_STATUS_STOPPED;
|
||||
if( tor->completeness == TR_LEECH )
|
||||
return TR_STATUS_DOWNLOAD;
|
||||
|
||||
return TR_STATUS_SEED;
|
||||
if( tor->isRunning )
|
||||
return is_seed ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
|
||||
|
||||
if( tor->queuePosition >= 0 ) {
|
||||
if( is_seed && tr_sessionGetQueueEnabled( tor->session, TR_UP ) )
|
||||
return TR_STATUS_SEED_WAIT;
|
||||
if( !is_seed && tr_sessionGetQueueEnabled( tor->session, TR_DOWN ) )
|
||||
return TR_STATUS_DOWNLOAD_WAIT;
|
||||
}
|
||||
|
||||
return TR_STATUS_STOPPED;
|
||||
}
|
||||
|
||||
tr_torrent_activity
|
||||
tr_torrentGetActivity( tr_torrent * tor )
|
||||
{
|
||||
/* FIXME: is this call still needed? */
|
||||
tr_torrentRecheckCompleteness( tor );
|
||||
|
||||
return torrentGetActivity( tor );
|
||||
}
|
||||
|
||||
static time_t
|
||||
torrentGetIdleSecs( const tr_torrent * tor )
|
||||
{
|
||||
int idle_secs;
|
||||
const tr_torrent_activity activity = torrentGetActivity( tor );
|
||||
|
||||
if ((activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_SEED) && tor->startDate != 0)
|
||||
idle_secs = difftime(tr_time(), MAX(tor->startDate, tor->activityDate));
|
||||
else
|
||||
idle_secs = -1;
|
||||
|
||||
return idle_secs;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_torrentIsStalled( const tr_torrent * tor )
|
||||
{
|
||||
return torrentGetIdleSecs( tor ) > ( tr_sessionGetQueueStalledMinutes( tor->session ) * 60 );
|
||||
}
|
||||
|
||||
|
||||
static double
|
||||
getVerifyProgress( const tr_torrent * tor )
|
||||
{
|
||||
|
@ -1145,6 +1182,7 @@ tr_torrentStat( tr_torrent * tor )
|
|||
s->id = tor->uniqueId;
|
||||
s->activity = tr_torrentGetActivity( tor );
|
||||
s->error = tor->error;
|
||||
s->queuePosition = tor->queuePosition;
|
||||
tr_strlcpy( s->errorString, tor->errorString, sizeof( s->errorString ) );
|
||||
|
||||
s->manualAnnounceTime = tr_announcerNextManualAnnounce( tor );
|
||||
|
@ -1175,11 +1213,7 @@ tr_torrentStat( tr_torrent * tor )
|
|||
s->startDate = tor->startDate;
|
||||
s->secondsSeeding = tor->secondsSeeding;
|
||||
s->secondsDownloading = tor->secondsDownloading;
|
||||
|
||||
if ((s->activity == TR_STATUS_DOWNLOAD || s->activity == TR_STATUS_SEED) && s->startDate != 0)
|
||||
s->idleSecs = difftime(tr_time(), MAX(s->startDate, s->activityDate));
|
||||
else
|
||||
s->idleSecs = -1;
|
||||
s->idleSecs = torrentGetIdleSecs( tor );
|
||||
|
||||
s->corruptEver = tor->corruptCur + tor->corruptPrev;
|
||||
s->downloadedEver = tor->downloadedCur + tor->downloadedPrev;
|
||||
|
@ -1505,6 +1539,8 @@ freeTorrent( tr_torrent * tor )
|
|||
*** Start/Stop Callback
|
||||
**/
|
||||
|
||||
static void queueRemove( tr_torrent * tor );
|
||||
|
||||
static void
|
||||
torrentStartImpl( void * vtor )
|
||||
{
|
||||
|
@ -1516,6 +1552,7 @@ torrentStartImpl( void * vtor )
|
|||
tr_sessionLock( tor->session );
|
||||
|
||||
tr_torrentRecheckCompleteness( tor );
|
||||
queueRemove( tor );
|
||||
|
||||
now = tr_time( );
|
||||
tor->isRunning = true;
|
||||
|
@ -1556,24 +1593,52 @@ tr_torrentGetCurrentSizeOnDisk( const tr_torrent * tor )
|
|||
return byte_count;
|
||||
}
|
||||
|
||||
static void
|
||||
torrentStart( tr_torrent * tor )
|
||||
static bool
|
||||
torrentShouldQueue( const tr_torrent * tor )
|
||||
{
|
||||
/* already running... */
|
||||
if( tor->isRunning )
|
||||
return;
|
||||
const tr_direction dir = tr_torrentGetQueueDirection( tor );
|
||||
|
||||
return tr_sessionCountQueueFreeSlots( tor->session, dir ) == 0;
|
||||
}
|
||||
|
||||
static void queueAppend( tr_torrent * tor );
|
||||
|
||||
static void
|
||||
torrentStart( tr_torrent * tor, bool bypass_queue )
|
||||
{
|
||||
switch( torrentGetActivity( tor ) )
|
||||
{
|
||||
case TR_STATUS_SEED:
|
||||
case TR_STATUS_DOWNLOAD:
|
||||
return; /* already started */
|
||||
break;
|
||||
|
||||
case TR_STATUS_SEED_WAIT:
|
||||
case TR_STATUS_DOWNLOAD_WAIT:
|
||||
if( !bypass_queue )
|
||||
return; /* already queued */
|
||||
break;
|
||||
|
||||
case TR_STATUS_CHECK:
|
||||
case TR_STATUS_CHECK_WAIT:
|
||||
/* verifying right now... wait until that's done so
|
||||
* we'll know what completeness to use/announce */
|
||||
tor->startAfterVerify = true;
|
||||
return;
|
||||
break;
|
||||
|
||||
case TR_STATUS_STOPPED:
|
||||
if( !bypass_queue && torrentShouldQueue( tor ) ) {
|
||||
queueAppend( tor );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* don't allow the torrent to be started if the files disappeared */
|
||||
if( setLocalErrorIfFilesDisappeared( tor ) )
|
||||
return;
|
||||
|
||||
/* verifying right now... wait until that's done so
|
||||
* we'll know what completeness to use/announce */
|
||||
if( tor->verifyState != TR_VERIFY_NONE ) {
|
||||
tor->startAfterVerify = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/* otherwise, start it now... */
|
||||
tr_sessionLock( tor->session );
|
||||
|
||||
|
@ -1600,7 +1665,14 @@ void
|
|||
tr_torrentStart( tr_torrent * tor )
|
||||
{
|
||||
if( tr_isTorrent( tor ) )
|
||||
torrentStart( tor );
|
||||
torrentStart( tor, false );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentStartNow( tr_torrent * tor )
|
||||
{
|
||||
if( tr_isTorrent( tor ) )
|
||||
torrentStart( tor, true );
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1613,7 +1685,7 @@ torrentRecheckDoneImpl( void * vtor )
|
|||
|
||||
if( tor->startAfterVerify ) {
|
||||
tor->startAfterVerify = false;
|
||||
torrentStart( tor );
|
||||
torrentStart( tor, false );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1681,6 +1753,7 @@ stopTorrent( void * vtor )
|
|||
tr_torrentLock( tor );
|
||||
|
||||
tr_verifyRemove( tor );
|
||||
queueRemove( tor );
|
||||
tr_peerMgrStopTorrent( tor );
|
||||
tr_announcerTorrentStopped( tor );
|
||||
tr_cacheFlushTorrent( tor->session->cache, tor );
|
||||
|
@ -3085,3 +3158,211 @@ tr_torrentBuildPartial( const tr_torrent * tor, tr_file_index_t fileNum )
|
|||
{
|
||||
return tr_strdup_printf( "%s.part", tor->info.files[fileNum].name );
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static int
|
||||
compareTorrentByQueuePosition( const void * va, const void * vb )
|
||||
{
|
||||
const tr_torrent * a = * (const tr_torrent **) va;
|
||||
const tr_torrent * b = * (const tr_torrent **) vb;
|
||||
|
||||
return a->queuePosition - b->queuePosition;
|
||||
}
|
||||
|
||||
static bool
|
||||
queueIsSequenced( tr_torrent * tor )
|
||||
{
|
||||
int i ;
|
||||
int n ;
|
||||
bool is_sequenced = true;
|
||||
tr_session * session = tor->session;
|
||||
tr_direction direction = tr_torrentGetQueueDirection( tor );
|
||||
tr_torrent ** tmp = tr_new( tr_torrent *, session->torrentCount );
|
||||
|
||||
/* get all the torrents in that queue */
|
||||
n = 0;
|
||||
tor = NULL;
|
||||
while(( tor = tr_torrentNext( session, tor )))
|
||||
if( tr_torrentIsQueued( tor ) && ( direction == tr_torrentGetQueueDirection( tor ) ) )
|
||||
tmp[n++] = tor;
|
||||
|
||||
/* sort them by position */
|
||||
qsort( tmp, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
|
||||
|
||||
#if 0
|
||||
/* print them */
|
||||
fprintf( stderr, "sequence: " );
|
||||
for( i=0; i<n; ++i )
|
||||
fprintf( stderr, "%d ", tmp[i]->queuePosition );
|
||||
fprintf( stderr, "\n" );
|
||||
#endif
|
||||
|
||||
/* test them */
|
||||
for( i=0; is_sequenced && i<n; ++i )
|
||||
if( tmp[i]->queuePosition != i )
|
||||
is_sequenced = false;
|
||||
|
||||
tr_free( tmp );
|
||||
return is_sequenced;
|
||||
}
|
||||
|
||||
int
|
||||
tr_torrentGetQueuePosition( const tr_torrent * tor )
|
||||
{
|
||||
return tor->queuePosition;
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentSetQueuePosition( tr_torrent * tor, int pos )
|
||||
{
|
||||
if( tr_torrentIsQueued( tor ) )
|
||||
{
|
||||
int back = -1;
|
||||
tr_torrent * walk;
|
||||
const tr_direction direction = tr_torrentGetQueueDirection( tor );
|
||||
const int old_pos = tor->queuePosition;
|
||||
const time_t now = tr_time( );
|
||||
|
||||
if( pos < 0 )
|
||||
pos = 0;
|
||||
|
||||
tor->queuePosition = -1;
|
||||
|
||||
walk = NULL;
|
||||
while(( walk = tr_torrentNext( tor->session, walk )))
|
||||
{
|
||||
if( tr_torrentIsQueued( walk ) && ( tr_torrentGetQueueDirection( walk ) == direction ) )
|
||||
{
|
||||
if( old_pos < pos ) {
|
||||
if( ( old_pos <= walk->queuePosition ) && ( walk->queuePosition <= pos ) ) {
|
||||
walk->queuePosition--;
|
||||
walk->anyDate = now;
|
||||
}
|
||||
}
|
||||
|
||||
if( old_pos > pos ) {
|
||||
if( ( pos <= walk->queuePosition ) && ( walk->queuePosition < old_pos ) ) {
|
||||
walk->queuePosition++;
|
||||
walk->anyDate = now;
|
||||
}
|
||||
}
|
||||
|
||||
if( back < walk->queuePosition )
|
||||
back = walk->queuePosition;
|
||||
}
|
||||
}
|
||||
|
||||
tor->queuePosition = MIN( pos, (back+1) );
|
||||
tor->anyDate = now;
|
||||
}
|
||||
|
||||
assert( queueIsSequenced( tor ) );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentsQueueMoveTop( tr_torrent ** torrents_in, int n )
|
||||
{
|
||||
int i;
|
||||
tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
|
||||
qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
|
||||
for( i=n-1; i>=0; --i )
|
||||
tr_torrentSetQueuePosition( torrents[i], 0 );
|
||||
tr_free( torrents );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentsQueueMoveUp( tr_torrent ** torrents_in, int n )
|
||||
{
|
||||
int i;
|
||||
tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
|
||||
qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
|
||||
for( i=0; i<n; ++i )
|
||||
tr_torrentSetQueuePosition( torrents[i], torrents[i]->queuePosition - 1 );
|
||||
tr_free( torrents );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentsQueueMoveDown( tr_torrent ** torrents_in, int n )
|
||||
{
|
||||
int i;
|
||||
tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
|
||||
qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
|
||||
for( i=n-1; i>=0; --i )
|
||||
tr_torrentSetQueuePosition( torrents[i], torrents[i]->queuePosition + 1 );
|
||||
tr_free( torrents );
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentsQueueMoveBottom( tr_torrent ** torrents_in, int n )
|
||||
{
|
||||
int i;
|
||||
tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
|
||||
qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
|
||||
for( i=0; i<n; ++i )
|
||||
tr_torrentSetQueuePosition( torrents[i], INT_MAX );
|
||||
tr_free( torrents );
|
||||
}
|
||||
|
||||
/* Ensure that the torrents queued for downloads have queuePositions contiguous from [0...n] */
|
||||
static void
|
||||
queueResequence( tr_session * session, tr_direction direction )
|
||||
{
|
||||
int i;
|
||||
int n;
|
||||
tr_torrent * tor = NULL;
|
||||
tr_torrent ** tmp = tr_new( tr_torrent *, session->torrentCount );
|
||||
const time_t now = tr_time( );
|
||||
|
||||
assert( tr_isSession( session ) );
|
||||
assert( tr_isDirection( direction ) );
|
||||
|
||||
/* get all the torrents in that queue */
|
||||
n = 0;
|
||||
while(( tor = tr_torrentNext( session, tor ))) {
|
||||
if( direction == tr_torrentGetQueueDirection( tor )) {
|
||||
const int position = tr_torrentGetQueuePosition( tor );
|
||||
if( position >= 0 )
|
||||
tmp[n++] = tor;
|
||||
}
|
||||
}
|
||||
|
||||
/* sort them by position */
|
||||
qsort( tmp, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
|
||||
|
||||
/* sequence them... */
|
||||
for( i=0; i<n; ++i ) {
|
||||
tr_torrent * tor = tmp[i];
|
||||
if( tor->queuePosition != i ) {
|
||||
tor->queuePosition = i;
|
||||
tor->anyDate = now;
|
||||
}
|
||||
}
|
||||
|
||||
tr_free( tmp );
|
||||
}
|
||||
|
||||
static void
|
||||
queueRemove( tr_torrent * tor )
|
||||
{
|
||||
if( tr_torrentIsQueued( tor ) )
|
||||
{
|
||||
tor->queuePosition = -1;
|
||||
queueResequence( tor->session, tr_torrentGetQueueDirection( tor ) );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
queueAppend( tr_torrent * tor )
|
||||
{
|
||||
if( !tr_torrentIsQueued( tor ) )
|
||||
{
|
||||
/* tr_torrentSetQueuePosition() requres the torrent to be queued,
|
||||
so init tor->queuePosition to the back... */
|
||||
tor->queuePosition = INT_MAX;
|
||||
|
||||
tr_torrentSetQueuePosition( tor, INT_MAX );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,6 +222,8 @@ struct tr_torrent
|
|||
int secondsDownloading;
|
||||
int secondsSeeding;
|
||||
|
||||
int queuePosition;
|
||||
|
||||
tr_torrent_metadata_func * metadata_func;
|
||||
void * metadata_func_user_data;
|
||||
|
||||
|
@ -426,5 +428,18 @@ time_t tr_torrentGetFileMTime( const tr_torrent * tor, tr_file_index_t i );
|
|||
|
||||
uint64_t tr_torrentGetCurrentSizeOnDisk( const tr_torrent * tor );
|
||||
|
||||
bool tr_torrentIsStalled( const tr_torrent * tor );
|
||||
|
||||
static inline bool
|
||||
tr_torrentIsQueued( const tr_torrent * tor )
|
||||
{
|
||||
return tor->queuePosition >= 0;
|
||||
}
|
||||
|
||||
static inline tr_direction
|
||||
tr_torrentGetQueueDirection( const tr_torrent * tor )
|
||||
{
|
||||
return tr_torrentIsSeed( tor ) ? TR_UP : TR_DOWN;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -156,63 +156,68 @@ const char* tr_getDefaultDownloadDir( void );
|
|||
#define TR_DEFAULT_PEER_LIMIT_GLOBAL_STR "240"
|
||||
#define TR_DEFAULT_PEER_LIMIT_TORRENT_STR "60"
|
||||
|
||||
#define TR_PREFS_KEY_ALT_SPEED_ENABLED "alt-speed-enabled"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_UP_KBps "alt-speed-up"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_DOWN_KBps "alt-speed-down"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN "alt-speed-time-begin"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED "alt-speed-time-enabled"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_END "alt-speed-time-end"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_DAY "alt-speed-time-day"
|
||||
#define TR_PREFS_KEY_BIND_ADDRESS_IPV4 "bind-address-ipv4"
|
||||
#define TR_PREFS_KEY_BIND_ADDRESS_IPV6 "bind-address-ipv6"
|
||||
#define TR_PREFS_KEY_BLOCKLIST_ENABLED "blocklist-enabled"
|
||||
#define TR_PREFS_KEY_BLOCKLIST_URL "blocklist-url"
|
||||
#define TR_PREFS_KEY_MAX_CACHE_SIZE_MB "cache-size-mb"
|
||||
#define TR_PREFS_KEY_DHT_ENABLED "dht-enabled"
|
||||
#define TR_PREFS_KEY_UTP_ENABLED "utp-enabled"
|
||||
#define TR_PREFS_KEY_LPD_ENABLED "lpd-enabled"
|
||||
#define TR_PREFS_KEY_PREFETCH_ENABLED "prefetch-enabled"
|
||||
#define TR_PREFS_KEY_DOWNLOAD_DIR "download-dir"
|
||||
#define TR_PREFS_KEY_ENCRYPTION "encryption"
|
||||
#define TR_PREFS_KEY_IDLE_LIMIT "idle-seeding-limit"
|
||||
#define TR_PREFS_KEY_IDLE_LIMIT_ENABLED "idle-seeding-limit-enabled"
|
||||
#define TR_PREFS_KEY_INCOMPLETE_DIR "incomplete-dir"
|
||||
#define TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED "incomplete-dir-enabled"
|
||||
#define TR_PREFS_KEY_MSGLEVEL "message-level"
|
||||
#define TR_PREFS_KEY_PEER_LIMIT_GLOBAL "peer-limit-global"
|
||||
#define TR_PREFS_KEY_PEER_LIMIT_TORRENT "peer-limit-per-torrent"
|
||||
#define TR_PREFS_KEY_PEER_PORT "peer-port"
|
||||
#define TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START "peer-port-random-on-start"
|
||||
#define TR_PREFS_KEY_PEER_PORT_RANDOM_LOW "peer-port-random-low"
|
||||
#define TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH "peer-port-random-high"
|
||||
#define TR_PREFS_KEY_PEER_SOCKET_TOS "peer-socket-tos"
|
||||
#define TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM "peer-congestion-algorithm"
|
||||
#define TR_PREFS_KEY_PEX_ENABLED "pex-enabled"
|
||||
#define TR_PREFS_KEY_PORT_FORWARDING "port-forwarding-enabled"
|
||||
#define TR_PREFS_KEY_PREALLOCATION "preallocation"
|
||||
#define TR_PREFS_KEY_RATIO "ratio-limit"
|
||||
#define TR_PREFS_KEY_RATIO_ENABLED "ratio-limit-enabled"
|
||||
#define TR_PREFS_KEY_RENAME_PARTIAL_FILES "rename-partial-files"
|
||||
#define TR_PREFS_KEY_RPC_AUTH_REQUIRED "rpc-authentication-required"
|
||||
#define TR_PREFS_KEY_RPC_BIND_ADDRESS "rpc-bind-address"
|
||||
#define TR_PREFS_KEY_RPC_ENABLED "rpc-enabled"
|
||||
#define TR_PREFS_KEY_RPC_PASSWORD "rpc-password"
|
||||
#define TR_PREFS_KEY_RPC_PORT "rpc-port"
|
||||
#define TR_PREFS_KEY_RPC_USERNAME "rpc-username"
|
||||
#define TR_PREFS_KEY_RPC_URL "rpc-url"
|
||||
#define TR_PREFS_KEY_RPC_WHITELIST_ENABLED "rpc-whitelist-enabled"
|
||||
#define TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS "scrape-paused-torrents-enabled"
|
||||
#define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME "script-torrent-done-filename"
|
||||
#define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED "script-torrent-done-enabled"
|
||||
#define TR_PREFS_KEY_RPC_WHITELIST "rpc-whitelist"
|
||||
#define TR_PREFS_KEY_DSPEED_KBps "speed-limit-down"
|
||||
#define TR_PREFS_KEY_DSPEED_ENABLED "speed-limit-down-enabled"
|
||||
#define TR_PREFS_KEY_USPEED_KBps "speed-limit-up"
|
||||
#define TR_PREFS_KEY_USPEED_ENABLED "speed-limit-up-enabled"
|
||||
#define TR_PREFS_KEY_UMASK "umask"
|
||||
#define TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT "upload-slots-per-torrent"
|
||||
#define TR_PREFS_KEY_START "start-added-torrents"
|
||||
#define TR_PREFS_KEY_TRASH_ORIGINAL "trash-original-torrent-files"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_ENABLED "alt-speed-enabled"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_UP_KBps "alt-speed-up"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_DOWN_KBps "alt-speed-down"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN "alt-speed-time-begin"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED "alt-speed-time-enabled"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_END "alt-speed-time-end"
|
||||
#define TR_PREFS_KEY_ALT_SPEED_TIME_DAY "alt-speed-time-day"
|
||||
#define TR_PREFS_KEY_BIND_ADDRESS_IPV4 "bind-address-ipv4"
|
||||
#define TR_PREFS_KEY_BIND_ADDRESS_IPV6 "bind-address-ipv6"
|
||||
#define TR_PREFS_KEY_BLOCKLIST_ENABLED "blocklist-enabled"
|
||||
#define TR_PREFS_KEY_BLOCKLIST_URL "blocklist-url"
|
||||
#define TR_PREFS_KEY_MAX_CACHE_SIZE_MB "cache-size-mb"
|
||||
#define TR_PREFS_KEY_DHT_ENABLED "dht-enabled"
|
||||
#define TR_PREFS_KEY_UTP_ENABLED "utp-enabled"
|
||||
#define TR_PREFS_KEY_LPD_ENABLED "lpd-enabled"
|
||||
#define TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE "download-queue-size"
|
||||
#define TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED "download-queue-enabled"
|
||||
#define TR_PREFS_KEY_PREFETCH_ENABLED "prefetch-enabled"
|
||||
#define TR_PREFS_KEY_DOWNLOAD_DIR "download-dir"
|
||||
#define TR_PREFS_KEY_ENCRYPTION "encryption"
|
||||
#define TR_PREFS_KEY_IDLE_LIMIT "idle-seeding-limit"
|
||||
#define TR_PREFS_KEY_IDLE_LIMIT_ENABLED "idle-seeding-limit-enabled"
|
||||
#define TR_PREFS_KEY_INCOMPLETE_DIR "incomplete-dir"
|
||||
#define TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED "incomplete-dir-enabled"
|
||||
#define TR_PREFS_KEY_MSGLEVEL "message-level"
|
||||
#define TR_PREFS_KEY_PEER_LIMIT_GLOBAL "peer-limit-global"
|
||||
#define TR_PREFS_KEY_PEER_LIMIT_TORRENT "peer-limit-per-torrent"
|
||||
#define TR_PREFS_KEY_PEER_PORT "peer-port"
|
||||
#define TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START "peer-port-random-on-start"
|
||||
#define TR_PREFS_KEY_PEER_PORT_RANDOM_LOW "peer-port-random-low"
|
||||
#define TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH "peer-port-random-high"
|
||||
#define TR_PREFS_KEY_PEER_SOCKET_TOS "peer-socket-tos"
|
||||
#define TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM "peer-congestion-algorithm"
|
||||
#define TR_PREFS_KEY_PEX_ENABLED "pex-enabled"
|
||||
#define TR_PREFS_KEY_PORT_FORWARDING "port-forwarding-enabled"
|
||||
#define TR_PREFS_KEY_PREALLOCATION "preallocation"
|
||||
#define TR_PREFS_KEY_RATIO "ratio-limit"
|
||||
#define TR_PREFS_KEY_RATIO_ENABLED "ratio-limit-enabled"
|
||||
#define TR_PREFS_KEY_RENAME_PARTIAL_FILES "rename-partial-files"
|
||||
#define TR_PREFS_KEY_RPC_AUTH_REQUIRED "rpc-authentication-required"
|
||||
#define TR_PREFS_KEY_RPC_BIND_ADDRESS "rpc-bind-address"
|
||||
#define TR_PREFS_KEY_RPC_ENABLED "rpc-enabled"
|
||||
#define TR_PREFS_KEY_RPC_PASSWORD "rpc-password"
|
||||
#define TR_PREFS_KEY_RPC_PORT "rpc-port"
|
||||
#define TR_PREFS_KEY_RPC_USERNAME "rpc-username"
|
||||
#define TR_PREFS_KEY_RPC_URL "rpc-url"
|
||||
#define TR_PREFS_KEY_RPC_WHITELIST_ENABLED "rpc-whitelist-enabled"
|
||||
#define TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS "scrape-paused-torrents-enabled"
|
||||
#define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME "script-torrent-done-filename"
|
||||
#define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED "script-torrent-done-enabled"
|
||||
#define TR_PREFS_KEY_SEED_QUEUE_SIZE "seed-queue-size"
|
||||
#define TR_PREFS_KEY_SEED_QUEUE_ENABLED "seed-queue-enabled"
|
||||
#define TR_PREFS_KEY_RPC_WHITELIST "rpc-whitelist"
|
||||
#define TR_PREFS_KEY_QUEUE_STALLED_MINUTES "queue-stalled-minutes"
|
||||
#define TR_PREFS_KEY_DSPEED_KBps "speed-limit-down"
|
||||
#define TR_PREFS_KEY_DSPEED_ENABLED "speed-limit-down-enabled"
|
||||
#define TR_PREFS_KEY_USPEED_KBps "speed-limit-up"
|
||||
#define TR_PREFS_KEY_USPEED_ENABLED "speed-limit-up-enabled"
|
||||
#define TR_PREFS_KEY_UMASK "umask"
|
||||
#define TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT "upload-slots-per-torrent"
|
||||
#define TR_PREFS_KEY_START "start-added-torrents"
|
||||
#define TR_PREFS_KEY_TRASH_ORIGINAL "trash-original-torrent-files"
|
||||
|
||||
|
||||
/**
|
||||
|
@ -736,6 +741,79 @@ bool tr_sessionGetDeleteSource ( const tr_session * );
|
|||
tr_priority_t tr_torrentGetPriority( const tr_torrent * );
|
||||
void tr_torrentSetPriority( tr_torrent *, tr_priority_t );
|
||||
|
||||
/***
|
||||
****
|
||||
**** Torrent Queueing
|
||||
****
|
||||
**** There are independent queues for seeding (TR_UP) and leeching (TR_DOWN).
|
||||
****
|
||||
**** If the session already has enough non-stalled seeds/leeches when
|
||||
**** tr_torrentStart() is called, the torrent will be moved into the
|
||||
**** appropriate queue and its state will be TR_STATUS_{DOWNLOAD,SEED}_WAIT.
|
||||
****
|
||||
**** To bypass the queue and unconditionally start the torrent use
|
||||
**** tr_torrentStartNow().
|
||||
****
|
||||
**** Torrents can be moved in the queue using the simple functions
|
||||
**** tr_torrentQueueMove{Top,Up,Down,Bottom}. They can be moved to
|
||||
**** arbitrary points in the queue with tr_torrentSetQueuePosition().
|
||||
****
|
||||
***/
|
||||
|
||||
|
||||
/** @brief Like tr_torrentStart(), but resumes right away regardless of the queues. */
|
||||
void tr_torrentStartNow ( tr_torrent * );
|
||||
|
||||
/** @brief Return the queued torrent's position in the queue it's in. [0...n) */
|
||||
int tr_torrentGetQueuePosition ( const tr_torrent * );
|
||||
|
||||
/** @brief Set the queued torrent's position in the queue it's in.
|
||||
* Special cases: pos <= 0 moves to the front; pos >= queue length moves to the back */
|
||||
void tr_torrentSetQueuePosition ( tr_torrent *, int queuePosition );
|
||||
|
||||
/**
|
||||
**/
|
||||
|
||||
/** @brief Convenience function for moving a batch of torrents to the front of their queue(s) */
|
||||
void tr_torrentsQueueMoveTop ( tr_torrent ** torrents, int torrentCount );
|
||||
|
||||
/** @brief Convenience function for moving a batch of torrents ahead one step in their queue(s) */
|
||||
void tr_torrentsQueueMoveUp ( tr_torrent ** torrents, int torrentCount );
|
||||
|
||||
/** @brief Convenience function for moving a batch of torrents back one step in their queue(s) */
|
||||
void tr_torrentsQueueMoveDown ( tr_torrent ** torrents, int torrentCount );
|
||||
|
||||
/** @brief Convenience function for moving a batch of torrents to the back of their queue(s) */
|
||||
void tr_torrentsQueueMoveBottom ( tr_torrent ** torrents, int torrentCount );
|
||||
|
||||
/**
|
||||
**/
|
||||
|
||||
/** @brief Set the number of torrents allowed to download (if direction is TR_DOWN) or seed (if direction is TR_UP) at the same time */
|
||||
void tr_sessionSetQueueSize ( tr_session *, tr_direction, int max_simultaneous_seed_torrents );
|
||||
|
||||
/** @brief Return the number of torrents allowed to download (if direction is TR_DOWN) or seed (if direction is TR_UP) at the same time */
|
||||
int tr_sessionGetQueueSize ( const tr_session *, tr_direction );
|
||||
|
||||
/** @brief Set whether or not to limit how many torrents can download (TR_DOWN) or seed (TR_UP) at the same time */
|
||||
void tr_sessionSetQueueEnabled ( tr_session *, tr_direction, bool do_limit_simultaneous_seed_torrents );
|
||||
|
||||
/** @brief Return true if we're limiting how many torrents can concurrently download (TR_DOWN) or seed (TR_UP) at the same time */
|
||||
bool tr_sessionGetQueueEnabled ( const tr_session *, tr_direction );
|
||||
|
||||
/** @brief Consider torrent as 'stalled' when it's been inactive for N minutes.
|
||||
Stalled torrents are left running but are not counted by tr_sessionGetQueueSize(). */
|
||||
void tr_sessionSetQueueStalledMinutes( tr_session *, int minutes );
|
||||
|
||||
/** @return the number of minutes a torrent can be idle before being considered as stalled */
|
||||
int tr_sessionGetQueueStalledMinutes( const tr_session * );
|
||||
|
||||
|
||||
/***
|
||||
****
|
||||
****
|
||||
***/
|
||||
|
||||
/**
|
||||
* Load all the torrents in tr_getTorrentDir().
|
||||
* This can be used at startup to kickstart all the torrents
|
||||
|
@ -1723,11 +1801,13 @@ static inline bool tr_torrentHasMetadata( const tr_torrent * tor )
|
|||
*/
|
||||
typedef enum
|
||||
{
|
||||
TR_STATUS_CHECK_WAIT = ( 1 << 0 ), /* Waiting in queue to check files */
|
||||
TR_STATUS_CHECK = ( 1 << 1 ), /* Checking files */
|
||||
TR_STATUS_DOWNLOAD = ( 1 << 2 ), /* Downloading */
|
||||
TR_STATUS_SEED = ( 1 << 3 ), /* Seeding */
|
||||
TR_STATUS_STOPPED = ( 1 << 4 ) /* Torrent is stopped */
|
||||
TR_STATUS_STOPPED = 0, /* Torrent is stopped */
|
||||
TR_STATUS_CHECK_WAIT = 1, /* Queued to check files */
|
||||
TR_STATUS_CHECK = 2, /* Checking files */
|
||||
TR_STATUS_DOWNLOAD_WAIT = 3, /* Queued to download */
|
||||
TR_STATUS_DOWNLOAD = 4, /* Downloading */
|
||||
TR_STATUS_SEED_WAIT = 5, /* Queued to seed */
|
||||
TR_STATUS_SEED = 6 /* Seeding */
|
||||
}
|
||||
tr_torrent_activity;
|
||||
|
||||
|
@ -1916,6 +1996,10 @@ typedef struct tr_stat
|
|||
/** A torrent is considered finished if it has met its seed ratio.
|
||||
As a result, only paused torrents can be finished. */
|
||||
bool finished;
|
||||
|
||||
/** The position of this torrent in the download queue.
|
||||
This will be >= 0 if the torrent is queued; -1 otherwise. */
|
||||
int queuePosition;
|
||||
}
|
||||
tr_stat;
|
||||
|
||||
|
|
|
@ -247,10 +247,6 @@ FilterBar :: createActivityCombo( )
|
|||
row->setData( FilterMode::SHOW_FINISHED, ActivityRole );
|
||||
model->appendRow( row );
|
||||
|
||||
row = new QStandardItem( blankIcon, tr( "Queued" ) );
|
||||
row->setData( FilterMode::SHOW_QUEUED, ActivityRole );
|
||||
model->appendRow( row );
|
||||
|
||||
row = new QStandardItem( QIcon::fromTheme( "view-refresh", blankIcon ), tr( "Verifying" ) );
|
||||
row->setData( FilterMode::SHOW_VERIFYING, ActivityRole );
|
||||
model->appendRow( row );
|
||||
|
|
|
@ -20,7 +20,6 @@ const QString FilterMode::names[NUM_MODES] =
|
|||
"show-seeding",
|
||||
"show-paused",
|
||||
"show-finished",
|
||||
"show-queued",
|
||||
"show-verifying",
|
||||
"show-error",
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@ class FilterMode
|
|||
FilterMode( const QString& name ): myMode(modeFromName(name)) { }
|
||||
static const QString names[];
|
||||
enum { SHOW_ALL, SHOW_ACTIVE, SHOW_DOWNLOADING, SHOW_SEEDING, SHOW_PAUSED,
|
||||
SHOW_FINISHED, SHOW_QUEUED, SHOW_VERIFYING, SHOW_ERROR, NUM_MODES };
|
||||
SHOW_FINISHED, SHOW_VERIFYING, SHOW_ERROR, NUM_MODES };
|
||||
static int modeFromName( const QString& name );
|
||||
static const QString& nameFromMode( int mode ) { return names[mode]; }
|
||||
int mode() const { return myMode; }
|
||||
|
|
122
qt/mainwin.cc
122
qt/mainwin.cc
|
@ -112,6 +112,7 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode
|
|||
ui.action_Properties->setIcon( getStockIcon( "document-properties", QStyle::SP_DesktopIcon ) );
|
||||
ui.action_OpenFolder->setIcon( getStockIcon( "folder-open", QStyle::SP_DirOpenIcon ) );
|
||||
ui.action_Start->setIcon( getStockIcon( "media-playback-start", QStyle::SP_MediaPlay ) );
|
||||
ui.action_StartNow->setIcon( getStockIcon( "media-playback-start", QStyle::SP_MediaPlay ) );
|
||||
ui.action_Announce->setIcon( getStockIcon( "network-transmit-receive" ) );
|
||||
ui.action_Pause->setIcon( getStockIcon( "media-playback-pause", QStyle::SP_MediaPause ) );
|
||||
ui.action_Remove->setIcon( getStockIcon( "list-remove", QStyle::SP_TrashIcon ) );
|
||||
|
@ -124,6 +125,10 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode
|
|||
ui.action_Preferences->setIcon( getStockIcon( "preferences-system" ) );
|
||||
ui.action_Contents->setIcon( getStockIcon( "help-contents", QStyle::SP_DialogHelpButton ) );
|
||||
ui.action_About->setIcon( getStockIcon( "help-about" ) );
|
||||
ui.action_QueueMoveTop->setIcon( getStockIcon( "go-top" ) );
|
||||
ui.action_QueueMoveUp->setIcon( getStockIcon( "go-up", QStyle::SP_ArrowUp ) );
|
||||
ui.action_QueueMoveDown->setIcon( getStockIcon( "go-down", QStyle::SP_ArrowDown ) );
|
||||
ui.action_QueueMoveBottom->setIcon( getStockIcon( "go-bottom" ) );
|
||||
|
||||
// ui signals
|
||||
connect( ui.action_Toolbar, SIGNAL(toggled(bool)), this, SLOT(setToolbarVisible(bool)));
|
||||
|
@ -140,6 +145,11 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode
|
|||
connect( ui.action_SortByState, SIGNAL(toggled(bool)), this, SLOT(onSortByStateToggled(bool)));
|
||||
connect( ui.action_ReverseSortOrder, SIGNAL(toggled(bool)), this, SLOT(setSortAscendingPref(bool)));
|
||||
connect( ui.action_Start, SIGNAL(triggered()), this, SLOT(startSelected()));
|
||||
connect( ui.action_QueueMoveTop, SIGNAL(triggered()), this, SLOT(queueMoveTop()));
|
||||
connect( ui.action_QueueMoveUp, SIGNAL(triggered()), this, SLOT(queueMoveUp()));
|
||||
connect( ui.action_QueueMoveDown, SIGNAL(triggered()), this, SLOT(queueMoveDown()));
|
||||
connect( ui.action_QueueMoveBottom, SIGNAL(triggered()), this, SLOT(queueMoveBottom()));
|
||||
connect( ui.action_StartNow, SIGNAL(triggered()), this, SLOT(startSelectedNow()));
|
||||
connect( ui.action_Pause, SIGNAL(triggered()), this, SLOT(pauseSelected()));
|
||||
connect( ui.action_Remove, SIGNAL(triggered()), this, SLOT(removeSelected()));
|
||||
connect( ui.action_Delete, SIGNAL(triggered()), this, SLOT(deleteSelected()));
|
||||
|
@ -162,29 +172,6 @@ TrMainWindow :: TrMainWindow( Session& session, Prefs& prefs, TorrentModel& mode
|
|||
connect( ui.action_SessionDialog, SIGNAL(triggered()), mySessionDialog, SLOT(show()));
|
||||
connect( ui.listView, SIGNAL(activated(const QModelIndex&)), ui.action_Properties, SLOT(trigger()));
|
||||
|
||||
QAction * sep2 = new QAction( this );
|
||||
sep2->setSeparator( true );
|
||||
QAction * sep3 = new QAction( this );
|
||||
sep3->setSeparator( true );
|
||||
|
||||
// context menu
|
||||
QList<QAction*> actions;
|
||||
actions << ui.action_Properties
|
||||
<< ui.action_OpenFolder
|
||||
<< sep2
|
||||
<< ui.action_Start
|
||||
<< ui.action_Announce
|
||||
<< ui.action_Pause
|
||||
<< ui.action_CopyMagnetToClipboard
|
||||
<< sep3
|
||||
<< ui.action_Verify
|
||||
<< ui.action_SetLocation
|
||||
<< sep
|
||||
<< ui.action_Remove
|
||||
<< ui.action_Delete;
|
||||
addActions( actions );
|
||||
setContextMenuPolicy( Qt::ActionsContextMenu );
|
||||
|
||||
// signals
|
||||
connect( ui.action_SelectAll, SIGNAL(triggered()), ui.listView, SLOT(selectAll()));
|
||||
connect( ui.action_DeselectAll, SIGNAL(triggered()), ui.listView, SLOT(clearSelection()));
|
||||
|
@ -725,7 +712,9 @@ TrMainWindow :: refreshActionSensitivity( )
|
|||
{
|
||||
int selected( 0 );
|
||||
int paused( 0 );
|
||||
int queued( 0 );
|
||||
int selectedAndPaused( 0 );
|
||||
int selectedAndQueued( 0 );
|
||||
int canAnnounce( 0 );
|
||||
const QAbstractItemModel * model( ui.listView->model( ) );
|
||||
const QItemSelectionModel * selectionModel( ui.listView->selectionModel( ) );
|
||||
|
@ -739,14 +728,13 @@ TrMainWindow :: refreshActionSensitivity( )
|
|||
if( tor ) {
|
||||
const bool isSelected( selectionModel->isSelected( modelIndex ) );
|
||||
const bool isPaused( tor->isPaused( ) );
|
||||
if( isSelected )
|
||||
++selected;
|
||||
if( isPaused )
|
||||
++ paused;
|
||||
if( isSelected && isPaused )
|
||||
++selectedAndPaused;
|
||||
if( tor->canManualAnnounce( ) )
|
||||
++canAnnounce;
|
||||
const bool isQueued( tor->isQueued( ) );
|
||||
if( isSelected ) ++selected;
|
||||
if( isQueued ) ++queued;
|
||||
if( isPaused ) ++ paused;
|
||||
if( isSelected && isPaused ) ++selectedAndPaused;
|
||||
if( isSelected && isQueued ) ++selectedAndQueued;
|
||||
if( tor->canManualAnnounce( ) ) ++canAnnounce;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -766,9 +754,15 @@ TrMainWindow :: refreshActionSensitivity( )
|
|||
ui.action_StartAll->setEnabled( paused > 0 );
|
||||
ui.action_PauseAll->setEnabled( paused < rowCount );
|
||||
ui.action_Start->setEnabled( selectedAndPaused > 0 );
|
||||
ui.action_StartNow->setEnabled( selectedAndPaused + selectedAndQueued > 0 );
|
||||
ui.action_Pause->setEnabled( selectedAndPaused < selected );
|
||||
ui.action_Announce->setEnabled( selected > 0 && ( canAnnounce == selected ) );
|
||||
|
||||
ui.action_QueueMoveTop->setEnabled( selectedAndQueued > 0 );
|
||||
ui.action_QueueMoveUp->setEnabled( selectedAndQueued > 0 );
|
||||
ui.action_QueueMoveDown->setEnabled( selectedAndQueued > 0 );
|
||||
ui.action_QueueMoveBottom->setEnabled( selectedAndQueued > 0 );
|
||||
|
||||
if( myDetailsDialog )
|
||||
myDetailsDialog->setIds( getSelectedTorrents( ) );
|
||||
}
|
||||
|
@ -803,11 +797,36 @@ TrMainWindow :: startSelected( )
|
|||
mySession.startTorrents( getSelectedTorrents( ) );
|
||||
}
|
||||
void
|
||||
TrMainWindow :: startSelectedNow( )
|
||||
{
|
||||
mySession.startTorrentsNow( getSelectedTorrents( ) );
|
||||
}
|
||||
void
|
||||
TrMainWindow :: pauseSelected( )
|
||||
{
|
||||
mySession.pauseTorrents( getSelectedTorrents( ) );
|
||||
}
|
||||
void
|
||||
TrMainWindow :: queueMoveTop( )
|
||||
{
|
||||
mySession.queueMoveTop( getSelectedTorrents( ) );
|
||||
}
|
||||
void
|
||||
TrMainWindow :: queueMoveUp( )
|
||||
{
|
||||
mySession.queueMoveUp( getSelectedTorrents( ) );
|
||||
}
|
||||
void
|
||||
TrMainWindow :: queueMoveDown( )
|
||||
{
|
||||
mySession.queueMoveDown( getSelectedTorrents( ) );
|
||||
}
|
||||
void
|
||||
TrMainWindow :: queueMoveBottom( )
|
||||
{
|
||||
mySession.queueMoveBottom( getSelectedTorrents( ) );
|
||||
}
|
||||
void
|
||||
TrMainWindow :: startAll( )
|
||||
{
|
||||
mySession.startTorrents( );
|
||||
|
@ -1296,3 +1315,44 @@ TrMainWindow :: dropEvent( QDropEvent * event )
|
|||
|
||||
dynamic_cast<MyApp*>(QApplication::instance())->addTorrent( key );
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
void
|
||||
TrMainWindow :: contextMenuEvent( QContextMenuEvent * event )
|
||||
{
|
||||
QMenu * menu = new QMenu( this );
|
||||
|
||||
menu->addAction( ui.action_Properties );
|
||||
menu->addAction( ui.action_OpenFolder );
|
||||
|
||||
QAction * sep = new QAction( this );
|
||||
sep->setSeparator( true );
|
||||
menu->addAction( sep );
|
||||
menu->addAction( ui.action_Start );
|
||||
menu->addAction( ui.action_StartNow );
|
||||
menu->addAction( ui.action_Announce );
|
||||
QMenu * queueMenu = menu->addMenu( tr( "Queue" ) );
|
||||
queueMenu->addAction( ui.action_QueueMoveTop );
|
||||
queueMenu->addAction( ui.action_QueueMoveUp );
|
||||
queueMenu->addAction( ui.action_QueueMoveDown );
|
||||
queueMenu->addAction( ui.action_QueueMoveBottom );
|
||||
menu->addAction( ui.action_Pause );
|
||||
|
||||
sep = new QAction( this );
|
||||
sep->setSeparator( true );
|
||||
menu->addAction( sep );
|
||||
menu->addAction( ui.action_Verify );
|
||||
menu->addAction( ui.action_SetLocation );
|
||||
menu->addAction( ui.action_CopyMagnetToClipboard );
|
||||
|
||||
sep = new QAction( this );
|
||||
sep->setSeparator( true );
|
||||
menu->addAction( sep );
|
||||
menu->addAction( ui.action_Remove );
|
||||
menu->addAction( ui.action_Delete );
|
||||
|
||||
menu->popup( event->globalPos( ) );
|
||||
}
|
||||
|
|
|
@ -161,11 +161,16 @@ class TrMainWindow: public QMainWindow
|
|||
public slots:
|
||||
void startAll( );
|
||||
void startSelected( );
|
||||
void startSelectedNow( );
|
||||
void pauseAll( );
|
||||
void pauseSelected( );
|
||||
void removeSelected( );
|
||||
void deleteSelected( );
|
||||
void verifySelected( );
|
||||
void queueMoveTop( );
|
||||
void queueMoveUp( );
|
||||
void queueMoveDown( );
|
||||
void queueMoveBottom( );
|
||||
void reannounceSelected( );
|
||||
void addTorrent( const QString& filename );
|
||||
void onNetworkTimer( );
|
||||
|
@ -187,6 +192,7 @@ class TrMainWindow: public QMainWindow
|
|||
virtual ~TrMainWindow( );
|
||||
|
||||
protected:
|
||||
virtual void contextMenuEvent( QContextMenuEvent * );
|
||||
virtual void dragEnterEvent( QDragEnterEvent * );
|
||||
virtual void dropEvent( QDropEvent * );
|
||||
};
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>792</width>
|
||||
<height>23</height>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -64,17 +64,28 @@
|
|||
<property name="title">
|
||||
<string>&Torrent</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuQueue">
|
||||
<property name="title">
|
||||
<string>Queue</string>
|
||||
</property>
|
||||
<addaction name="action_QueueMoveTop"/>
|
||||
<addaction name="action_QueueMoveUp"/>
|
||||
<addaction name="action_QueueMoveDown"/>
|
||||
<addaction name="action_QueueMoveBottom"/>
|
||||
</widget>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Properties"/>
|
||||
<addaction name="action_OpenFolder"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Start"/>
|
||||
<addaction name="action_StartNow"/>
|
||||
<addaction name="menuQueue"/>
|
||||
<addaction name="action_Announce"/>
|
||||
<addaction name="action_Pause"/>
|
||||
<addaction name="action_CopyMagnetToClipboard"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_SetLocation"/>
|
||||
<addaction name="action_Verify"/>
|
||||
<addaction name="action_CopyMagnetToClipboard"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Remove"/>
|
||||
<addaction name="action_Delete"/>
|
||||
|
@ -587,6 +598,40 @@
|
|||
<string>&Donate</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_StartNow">
|
||||
<property name="text">
|
||||
<string>Start &Now</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Bypass the queue and start now</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+S</string>
|
||||
</property>
|
||||
<property name="priority">
|
||||
<enum>QAction::LowPriority</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_QueueMoveTop">
|
||||
<property name="text">
|
||||
<string>Move to &Top</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_QueueMoveUp">
|
||||
<property name="text">
|
||||
<string>Move &Up</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_QueueMoveDown">
|
||||
<property name="text">
|
||||
<string>Move &Down</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_QueueMoveBottom">
|
||||
<property name="text">
|
||||
<string>Move to &Bottom</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="application.qrc"/>
|
||||
|
|
|
@ -532,6 +532,10 @@ PrefsDialog :: createTorrentsTab( )
|
|||
HIG * hig = new HIG( this );
|
||||
hig->addSectionTitle( tr( "Adding" ) );
|
||||
|
||||
hig->addWideControl( checkBoxNew( tr( "Show &options dialog" ), Prefs::OPTIONS_PROMPT ) );
|
||||
hig->addWideControl( checkBoxNew( tr( "&Start when added" ), Prefs::START ) );
|
||||
hig->addWideControl( checkBoxNew( tr( "Mo&ve .torrent file to the trash" ), Prefs::TRASH_ORIGINAL ) );
|
||||
|
||||
l = checkBoxNew( tr( "Automatically &add torrents from:" ), Prefs::DIR_WATCH_ENABLED );
|
||||
QPushButton * b = myWatchButton = new QPushButton;
|
||||
b->setIcon( folderPixmap );
|
||||
|
@ -540,21 +544,54 @@ PrefsDialog :: createTorrentsTab( )
|
|||
hig->addRow( l, b );
|
||||
enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
|
||||
|
||||
hig->addWideControl( checkBoxNew( tr( "Show &options dialog" ), Prefs::OPTIONS_PROMPT ) );
|
||||
hig->addWideControl( checkBoxNew( tr( "&Start when added" ), Prefs::START ) );
|
||||
hig->addWideControl( checkBoxNew( tr( "Mo&ve .torrent file to the trash" ), Prefs::TRASH_ORIGINAL ) );
|
||||
|
||||
hig->addSectionDivider( );
|
||||
hig->addSectionTitle( tr( "Downloading" ) );
|
||||
hig->addSectionTitle( tr( "Seeding Limits" ) );
|
||||
|
||||
hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) );
|
||||
l = checkBoxNew( tr( "Stop seeding at &ratio:" ), Prefs::RATIO_ENABLED );
|
||||
r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 );
|
||||
hig->addRow( l, r );
|
||||
enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
|
||||
|
||||
b = myDestinationButton = new QPushButton;
|
||||
l = checkBoxNew( tr( "Stop seeding if idle for &N minutes:" ), Prefs::IDLE_LIMIT_ENABLED );
|
||||
r = spinBoxNew( Prefs::IDLE_LIMIT, 1, INT_MAX, 5 );
|
||||
hig->addRow( l, r );
|
||||
enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
|
||||
|
||||
hig->finish( );
|
||||
return hig;
|
||||
}
|
||||
|
||||
QWidget *
|
||||
PrefsDialog :: createDownloadTab( )
|
||||
{
|
||||
const int iconSize( style( )->pixelMetric( QStyle :: PM_SmallIconSize ) );
|
||||
const QFileIconProvider iconProvider;
|
||||
const QIcon folderIcon = iconProvider.icon( QFileIconProvider::Folder );
|
||||
const QPixmap folderPixmap = folderIcon.pixmap( iconSize );
|
||||
const QIcon fileIcon = iconProvider.icon( QFileIconProvider::File );
|
||||
const QPixmap filePixmap = fileIcon.pixmap( iconSize );
|
||||
|
||||
QWidget *l;
|
||||
HIG * hig = new HIG( this );
|
||||
hig->addSectionTitle( tr( "Location" ) );
|
||||
|
||||
QPushButton * b = myDestinationButton = new QPushButton;
|
||||
b->setIcon( folderPixmap );
|
||||
b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
|
||||
connect( b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)) );
|
||||
hig->addRow( tr( "Save to &Location:" ), b );
|
||||
|
||||
hig->addSectionDivider( );
|
||||
hig->addSectionTitle( tr( "Queue" ) );
|
||||
|
||||
hig->addRow( tr( "Maximum active &downloads:" ), spinBoxNew( Prefs::DOWNLOAD_QUEUE_SIZE, 1, FD_SETSIZE, 5 ) );
|
||||
hig->addRow( tr( "E&xempt torrents if idle for N minutes:" ), spinBoxNew( Prefs::QUEUE_STALLED_MINUTES, 1, FD_SETSIZE, 5 ) );
|
||||
|
||||
hig->addSectionDivider( );
|
||||
hig->addSectionTitle( tr( "Incomplete" ) );
|
||||
|
||||
hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) );
|
||||
|
||||
l = myIncompleteCheckbox = checkBoxNew( tr( "Keep &incomplete files in:" ), Prefs::INCOMPLETE_DIR_ENABLED );
|
||||
b = myIncompleteButton = new QPushButton;
|
||||
b->setIcon( folderPixmap );
|
||||
|
@ -571,19 +608,6 @@ PrefsDialog :: createTorrentsTab( )
|
|||
hig->addRow( myTorrentDoneScriptCheckbox, b );
|
||||
enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
|
||||
|
||||
hig->addSectionDivider( );
|
||||
hig->addSectionTitle( tr( "Seeding Limits" ) );
|
||||
|
||||
l = checkBoxNew( tr( "Stop seeding at &ratio:" ), Prefs::RATIO_ENABLED );
|
||||
r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 );
|
||||
hig->addRow( l, r );
|
||||
enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
|
||||
|
||||
l = checkBoxNew( tr( "Stop seeding if idle for &N minutes:" ), Prefs::IDLE_LIMIT_ENABLED );
|
||||
r = spinBoxNew( Prefs::IDLE_LIMIT, 1, INT_MAX, 5 );
|
||||
hig->addRow( l, r );
|
||||
enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
|
||||
|
||||
hig->finish( );
|
||||
return hig;
|
||||
}
|
||||
|
@ -603,6 +627,7 @@ PrefsDialog :: PrefsDialog( Session& session, Prefs& prefs, QWidget * parent ):
|
|||
|
||||
QTabWidget * t = new QTabWidget( this );
|
||||
t->addTab( createTorrentsTab( ), tr( "Torrents" ) );
|
||||
t->addTab( createDownloadTab( ), tr( "Download" ) );
|
||||
t->addTab( createSpeedTab( ), tr( "Speed" ) );
|
||||
t->addTab( createPrivacyTab( ), tr( "Privacy" ) );
|
||||
t->addTab( createNetworkTab( ), tr( "Network" ) );
|
||||
|
|
|
@ -78,6 +78,7 @@ class PrefsDialog: public QDialog
|
|||
void setPref( int key, const QVariant& v );
|
||||
bool isAllowed( int key ) const;
|
||||
QWidget * createTorrentsTab( );
|
||||
QWidget * createDownloadTab( );
|
||||
QWidget * createSpeedTab( );
|
||||
QWidget * createPrivacyTab( );
|
||||
QWidget * createNetworkTab( );
|
||||
|
|
|
@ -79,6 +79,8 @@ Prefs::PrefItem Prefs::myItems[] =
|
|||
{ DSPEED, TR_PREFS_KEY_DSPEED_KBps, QVariant::Int },
|
||||
{ DSPEED_ENABLED, TR_PREFS_KEY_DSPEED_ENABLED, QVariant::Bool },
|
||||
{ DOWNLOAD_DIR, TR_PREFS_KEY_DOWNLOAD_DIR, QVariant::String },
|
||||
{ DOWNLOAD_QUEUE_ENABLED, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, QVariant::Bool },
|
||||
{ DOWNLOAD_QUEUE_SIZE, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, QVariant::Int },
|
||||
{ ENCRYPTION, TR_PREFS_KEY_ENCRYPTION, QVariant::Int },
|
||||
{ IDLE_LIMIT, TR_PREFS_KEY_IDLE_LIMIT, QVariant::Int },
|
||||
{ IDLE_LIMIT_ENABLED, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, QVariant::Bool },
|
||||
|
@ -91,6 +93,7 @@ Prefs::PrefItem Prefs::myItems[] =
|
|||
{ PEER_PORT_RANDOM_ON_START, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, QVariant::Bool },
|
||||
{ PEER_PORT_RANDOM_LOW, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, QVariant::Int },
|
||||
{ PEER_PORT_RANDOM_HIGH, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, QVariant::Int },
|
||||
{ QUEUE_STALLED_MINUTES, TR_PREFS_KEY_QUEUE_STALLED_MINUTES, QVariant::Int },
|
||||
{ SCRIPT_TORRENT_DONE_ENABLED, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, QVariant::Bool },
|
||||
{ SCRIPT_TORRENT_DONE_FILENAME, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, QVariant::String },
|
||||
{ SOCKET_TOS, TR_PREFS_KEY_PEER_SOCKET_TOS, QVariant::Int },
|
||||
|
|
|
@ -84,6 +84,8 @@ class Prefs: public QObject
|
|||
DSPEED,
|
||||
DSPEED_ENABLED,
|
||||
DOWNLOAD_DIR,
|
||||
DOWNLOAD_QUEUE_ENABLED,
|
||||
DOWNLOAD_QUEUE_SIZE,
|
||||
ENCRYPTION,
|
||||
IDLE_LIMIT,
|
||||
IDLE_LIMIT_ENABLED,
|
||||
|
@ -96,6 +98,7 @@ class Prefs: public QObject
|
|||
PEER_PORT_RANDOM_ON_START,
|
||||
PEER_PORT_RANDOM_LOW,
|
||||
PEER_PORT_RANDOM_HIGH,
|
||||
QUEUE_STALLED_MINUTES,
|
||||
SCRIPT_TORRENT_DONE_ENABLED,
|
||||
SCRIPT_TORRENT_DONE_FILENAME,
|
||||
SOCKET_TOS,
|
||||
|
|
|
@ -151,6 +151,8 @@ Session :: updatePref( int key )
|
|||
case Prefs :: BLOCKLIST_URL:
|
||||
case Prefs :: DHT_ENABLED:
|
||||
case Prefs :: DOWNLOAD_DIR:
|
||||
case Prefs :: DOWNLOAD_QUEUE_ENABLED:
|
||||
case Prefs :: DOWNLOAD_QUEUE_SIZE:
|
||||
case Prefs :: DSPEED:
|
||||
case Prefs :: DSPEED_ENABLED:
|
||||
case Prefs :: IDLE_LIMIT:
|
||||
|
@ -536,17 +538,13 @@ Session :: sendTorrentRequest( const char * request, const QSet<int>& ids )
|
|||
refreshTorrents( ids );
|
||||
}
|
||||
|
||||
void
|
||||
Session :: pauseTorrents( const QSet<int>& ids )
|
||||
{
|
||||
sendTorrentRequest( "torrent-stop", ids );
|
||||
}
|
||||
|
||||
void
|
||||
Session :: startTorrents( const QSet<int>& ids )
|
||||
{
|
||||
sendTorrentRequest( "torrent-start", ids );
|
||||
}
|
||||
void Session :: pauseTorrents ( const QSet<int>& ids ) { sendTorrentRequest( "torrent-stop", ids ); }
|
||||
void Session :: startTorrents ( const QSet<int>& ids ) { sendTorrentRequest( "torrent-start", ids ); }
|
||||
void Session :: startTorrentsNow ( const QSet<int>& ids ) { sendTorrentRequest( "torrent-start-now", ids ); }
|
||||
void Session :: queueMoveTop ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-top", ids ); }
|
||||
void Session :: queueMoveUp ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-up", ids ); }
|
||||
void Session :: queueMoveDown ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-down", ids ); }
|
||||
void Session :: queueMoveBottom ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-bottom", ids ); }
|
||||
|
||||
void
|
||||
Session :: refreshActiveTorrents( )
|
||||
|
|
|
@ -105,6 +105,11 @@ class Session: public QObject
|
|||
public slots:
|
||||
void pauseTorrents( const QSet<int>& torrentIds = QSet<int>() );
|
||||
void startTorrents( const QSet<int>& torrentIds = QSet<int>() );
|
||||
void startTorrentsNow( const QSet<int>& torrentIds = QSet<int>() );
|
||||
void queueMoveTop( const QSet<int>& torrentIds = QSet<int>() );
|
||||
void queueMoveUp( const QSet<int>& torrentIds = QSet<int>() );
|
||||
void queueMoveDown( const QSet<int>& torrentIds = QSet<int>() );
|
||||
void queueMoveBottom( const QSet<int>& torrentIds = QSet<int>() );
|
||||
void refreshSessionInfo( );
|
||||
void refreshSessionStats( );
|
||||
void refreshActiveTorrents( );
|
||||
|
|
|
@ -101,11 +101,12 @@ TorrentFilter :: lessThan( const QModelIndex& left, const QModelIndex& right ) c
|
|||
case SortMode :: SORT_BY_STATE:
|
||||
if( !val ) val = compare( a->hasError(), b->hasError() );
|
||||
if( !val ) val = compare( a->getActivity(), b->getActivity() );
|
||||
if( !val ) val = a->compareQueue( *b );
|
||||
// fall through
|
||||
case SortMode :: SORT_BY_PROGRESS:
|
||||
if( !val ) val = compare( a->percentComplete(), b->percentComplete() );
|
||||
if( !val ) val = a->compareSeedRatio( *b );
|
||||
// fall through
|
||||
if( !val ) val = a->compareQueue( *b );
|
||||
case SortMode :: SORT_BY_RATIO:
|
||||
if( !val ) val = a->compareRatio( *b );
|
||||
break;
|
||||
|
@ -144,10 +145,10 @@ TorrentFilter :: activityFilterAcceptsTorrent( const Torrent * tor, const Filter
|
|||
accepts = tor->peersWeAreUploadingTo( ) > 0 || tor->peersWeAreDownloadingFrom( ) > 0 || tor->isVerifying( );
|
||||
break;
|
||||
case FilterMode::SHOW_DOWNLOADING:
|
||||
accepts = tor->isDownloading( );
|
||||
accepts = tor->isDownloading( ) || tor->isWaitingToDownload( );
|
||||
break;
|
||||
case FilterMode::SHOW_SEEDING:
|
||||
accepts = tor->isSeeding( );
|
||||
accepts = tor->isSeeding( ) || tor->isWaitingToSeed( );
|
||||
break;
|
||||
case FilterMode::SHOW_PAUSED:
|
||||
accepts = tor->isPaused( );
|
||||
|
@ -155,9 +156,6 @@ TorrentFilter :: activityFilterAcceptsTorrent( const Torrent * tor, const Filter
|
|||
case FilterMode::SHOW_FINISHED:
|
||||
accepts = tor->isFinished( );
|
||||
break;
|
||||
case FilterMode::SHOW_QUEUED:
|
||||
accepts = tor->isWaitingToVerify( );
|
||||
break;
|
||||
case FilterMode::SHOW_VERIFYING:
|
||||
accepts = tor->isVerifying( ) || tor->isWaitingToVerify( );
|
||||
break;
|
||||
|
|
|
@ -107,7 +107,8 @@ Torrent :: myProperties[] =
|
|||
{ MANUAL_ANNOUNCE_TIME, "manualAnnounceTime", QVariant::DateTime, STAT_EXTRA },
|
||||
{ PEERS, "peers", TrTypes::PeerList, STAT_EXTRA },
|
||||
{ TORRENT_FILE, "torrentFile", QVariant::String, STAT_EXTRA },
|
||||
{ BANDWIDTH_PRIORITY, "bandwidthPriority", QVariant::Int, STAT_EXTRA }
|
||||
{ BANDWIDTH_PRIORITY, "bandwidthPriority", QVariant::Int, STAT_EXTRA },
|
||||
{ QUEUE_POSITION, "queuePosition", QVariant::Int, STAT }
|
||||
};
|
||||
|
||||
Torrent :: KeyList
|
||||
|
@ -368,6 +369,18 @@ Torrent :: hasTrackerSubstring( const QString& substr ) const
|
|||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
Torrent :: compareQueue( const Torrent& that ) const
|
||||
{
|
||||
const bool a_is_queued = isQueued( );
|
||||
const bool b_is_queued = that.isQueued( );
|
||||
|
||||
if( a_is_queued != b_is_queued )
|
||||
return a_is_queued ? -1 : 1;
|
||||
|
||||
return that.queuePosition() - queuePosition();
|
||||
}
|
||||
|
||||
int
|
||||
Torrent :: compareSeedRatio( const Torrent& that ) const
|
||||
{
|
||||
|
@ -701,11 +714,13 @@ Torrent :: activityString( ) const
|
|||
|
||||
switch( getActivity( ) )
|
||||
{
|
||||
case TR_STATUS_CHECK_WAIT: str = tr( "Waiting to verify local data" ); break;
|
||||
case TR_STATUS_CHECK: str = tr( "Verifying local data" ); break;
|
||||
case TR_STATUS_DOWNLOAD: str = tr( "Downloading" ); break;
|
||||
case TR_STATUS_SEED: str = tr( "Seeding" ); break;
|
||||
case TR_STATUS_STOPPED: str = isFinished() ? tr( "Finished" ): tr( "Paused" ); break;
|
||||
case TR_STATUS_STOPPED: str = isFinished() ? tr( "Finished" ): tr( "Paused" ); break;
|
||||
case TR_STATUS_CHECK_WAIT: str = tr( "Waiting to verify local data" ); break;
|
||||
case TR_STATUS_CHECK: str = tr( "Verifying local data" ); break;
|
||||
case TR_STATUS_DOWNLOAD_WAIT: str = tr( "Download queue #%1" ).arg( queuePosition() + 1 ); break;
|
||||
case TR_STATUS_DOWNLOAD: str = tr( "Downloading" );
|
||||
case TR_STATUS_SEED_WAIT: str = tr( "Seed queue #%1" ).arg( queuePosition() + 1 ); break;
|
||||
case TR_STATUS_SEED: str = tr( "Seeding" ); break;
|
||||
}
|
||||
|
||||
return str;
|
||||
|
|
|
@ -172,6 +172,7 @@ class Torrent: public QObject
|
|||
PEERS,
|
||||
TORRENT_FILE,
|
||||
BANDWIDTH_PRIORITY,
|
||||
QUEUE_POSITION,
|
||||
|
||||
PROPERTY_COUNT
|
||||
};
|
||||
|
@ -271,6 +272,7 @@ class Torrent: public QObject
|
|||
int compareTracker( const Torrent& ) const;
|
||||
int compareSeedRatio( const Torrent& ) const;
|
||||
int compareRatio( const Torrent& ) const;
|
||||
int compareQueue( const Torrent& ) const;
|
||||
int compareETA( const Torrent& ) const;
|
||||
bool hasETA( ) const { return getETA( ) >= 0; }
|
||||
int getETA( ) const { return getInt( ETA ); }
|
||||
|
@ -304,6 +306,8 @@ class Torrent: public QObject
|
|||
QStringList trackers() const { return myValues[TRACKERS].value<QStringList>(); }
|
||||
PeerList peers( ) const{ return myValues[PEERS].value<PeerList>(); }
|
||||
const FileList& files( ) const { return myFiles; }
|
||||
int queuePosition( ) const { return getInt( QUEUE_POSITION ); }
|
||||
bool isQueued( ) const { return queuePosition( ) >= 0; }
|
||||
|
||||
public:
|
||||
QString activityString( ) const;
|
||||
|
@ -313,7 +317,9 @@ class Torrent: public QObject
|
|||
bool isWaitingToVerify( ) const { return getActivity( ) == TR_STATUS_CHECK_WAIT; }
|
||||
bool isVerifying( ) const { return getActivity( ) == TR_STATUS_CHECK; }
|
||||
bool isDownloading( ) const { return getActivity( ) == TR_STATUS_DOWNLOAD; }
|
||||
bool isWaitingToDownload( ) const { return getActivity( ) == TR_STATUS_DOWNLOAD_WAIT; }
|
||||
bool isSeeding( ) const { return getActivity( ) == TR_STATUS_SEED; }
|
||||
bool isWaitingToSeed( ) const { return getActivity( ) == TR_STATUS_SEED_WAIT; }
|
||||
bool isReadyToTransfer( ) const { return getActivity()==TR_STATUS_DOWNLOAD || getActivity()==TR_STATUS_SEED; }
|
||||
void notifyComplete( ) const;
|
||||
|
||||
|
|
|
@ -526,7 +526,6 @@
|
|||
<li id="sort_by_name">Name</li>
|
||||
<li id="sort_by_percent_completed">Progress</li>
|
||||
<li id="sort_by_ratio">Ratio</li>
|
||||
<li id="sort_by_queue_order">Queue Order</li>
|
||||
<li id="sort_by_state">State</li>
|
||||
<li class="separator"></li>
|
||||
<li id="reverse_sort_order">Reverse Sort Order</li>
|
||||
|
@ -543,8 +542,9 @@
|
|||
|
||||
<div class="contextMenu" id="torrent_context_menu">
|
||||
<ul>
|
||||
<li id="context_pause_selected" class="disabled context_pause_selected">Pause Selected</li>
|
||||
<li id="context_resume_selected" class="disabled context_resume_selected">Resume Selected</li>
|
||||
<li id="context_pause_selected" class="disabled context_pause_selected">Pause</li>
|
||||
<li id="context_resume_selected" class="disabled context_resume_selected">Resume</li>
|
||||
<li id="context_resume_now_selected" class="disabled context_resume_selected">Resume Now</li>
|
||||
<li class="separator"></li>
|
||||
<li id="context_remove">Remove From List...</li>
|
||||
<li id="context_removedata">Trash Data & Remove From List...</li>
|
||||
|
|
|
@ -232,7 +232,6 @@ Prefs._SortDescending = 'descending';
|
|||
Prefs._SortMethod = 'sort_method';
|
||||
Prefs._SortByAge = 'age';
|
||||
Prefs._SortByActivity = 'activity';
|
||||
Prefs._SortByQueue = 'queue_order';
|
||||
Prefs._SortByName = 'name';
|
||||
Prefs._SortByProgress = 'percent_completed';
|
||||
Prefs._SortByRatio = 'ratio';
|
||||
|
|
|
@ -11,11 +11,21 @@ function Torrent( transferListParent, fileListParent, controller, data) {
|
|||
}
|
||||
|
||||
// Constants
|
||||
Torrent._StatusStopped = 0; /* torrent is stopped */
|
||||
Torrent._StatusCheckWait = 1; /* waiting in queue to check files */
|
||||
Torrent._StatusCheck = 2; /* checking files */
|
||||
Torrent._StatusDownloadWait = 3; /* queued to download */
|
||||
Torrent._StatusDownload = 4; /* downloading */
|
||||
Torrent._StatusSeedWait = 5; /* queeud to seed */
|
||||
Torrent._StatusSeed = 6; /* seeding */
|
||||
|
||||
/*
|
||||
Torrent._StatusWaitingToCheck = 1;
|
||||
Torrent._StatusChecking = 2;
|
||||
Torrent._StatusDownloading = 4;
|
||||
Torrent._StatusSeeding = 8;
|
||||
Torrent._StatusPaused = 16;
|
||||
*/
|
||||
|
||||
Torrent._InfiniteTimeRemaining = 215784000; // 999 Hours - may as well be infinite
|
||||
|
||||
Torrent._RatioUseGlobal = 0;
|
||||
|
@ -27,10 +37,10 @@ Torrent._ErrTrackerWarning = 1;
|
|||
Torrent._ErrTrackerError = 2;
|
||||
Torrent._ErrLocalError = 3;
|
||||
|
||||
Torrent._TrackerInactive = 0;
|
||||
Torrent._TrackerWaiting = 1;
|
||||
Torrent._TrackerQueued = 2;
|
||||
Torrent._TrackerActive = 3;
|
||||
Torrent._TrackerInactive = 0;
|
||||
Torrent._TrackerWaiting = 1;
|
||||
Torrent._TrackerQueued = 2;
|
||||
Torrent._TrackerActive = 3;
|
||||
|
||||
|
||||
Torrent._StaticFields = [ 'hashString', 'id' ]
|
||||
|
@ -39,10 +49,12 @@ Torrent._MetaDataFields = [ 'addedDate', 'comment', 'creator', 'dateCreated',
|
|||
'isPrivate', 'name', 'totalSize', 'pieceCount', 'pieceSize' ]
|
||||
|
||||
Torrent._DynamicFields = [ 'downloadedEver', 'error', 'errorString', 'eta',
|
||||
'haveUnchecked', 'haveValid', 'leftUntilDone', 'metadataPercentComplete', 'peers',
|
||||
'peersConnected', 'peersGettingFromUs', 'peersSendingToUs', 'rateDownload', 'rateUpload',
|
||||
'recheckProgress', 'sizeWhenDone', 'status', 'trackerStats', 'desiredAvailable',
|
||||
'uploadedEver', 'uploadRatio', 'seedRatioLimit', 'seedRatioMode', 'downloadDir', 'isFinished' ]
|
||||
'haveUnchecked', 'haveValid', 'leftUntilDone', 'metadataPercentComplete',
|
||||
'peers', 'peersConnected', 'peersGettingFromUs', 'peersSendingToUs',
|
||||
'queuePosition', 'rateDownload', 'rateUpload', 'recheckProgress',
|
||||
'sizeWhenDone', 'status', 'trackerStats', 'desiredAvailable',
|
||||
'uploadedEver', 'uploadRatio', 'seedRatioLimit', 'seedRatioMode',
|
||||
'downloadDir', 'isFinished' ]
|
||||
|
||||
Torrent.prototype =
|
||||
{
|
||||
|
@ -233,12 +245,14 @@ Torrent.prototype =
|
|||
isActiveFilter: function() { return this.peersGettingFromUs() > 0
|
||||
|| this.peersSendingToUs() > 0
|
||||
|| this.webseedsSendingToUs() > 0
|
||||
|| this.state() == Torrent._StatusChecking; },
|
||||
isActive: function() { return this.state() != Torrent._StatusPaused; },
|
||||
isDownloading: function() { return this.state() == Torrent._StatusDownloading; },
|
||||
|| this.state() == Torrent._StatusCheck; },
|
||||
isActive: function() { return this.state() != Torrent._StatusStopped; },
|
||||
isDownloading: function() { return this.state() == Torrent._StatusDownload; },
|
||||
isFinished: function() { return this._isFinishedSeeding; },
|
||||
isSeeding: function() { return this.state() == Torrent._StatusSeeding; },
|
||||
isSeeding: function() { return this.state() == Torrent._StatusSeed; },
|
||||
name: function() { return this._name; },
|
||||
queuePosition: function() { return this._queue_position; },
|
||||
isQueued: function() { return this.queuePosition() >= 0; },
|
||||
webseedsSendingToUs: function() { return this._webseeds_sending_to_us; },
|
||||
peersSendingToUs: function() { return this._peers_sending_to_us; },
|
||||
peersGettingFromUs: function() { return this._peers_getting_from_us; },
|
||||
|
@ -255,11 +269,13 @@ Torrent.prototype =
|
|||
state: function() { return this._state; },
|
||||
stateStr: function() {
|
||||
switch( this.state() ) {
|
||||
case Torrent._StatusSeeding: return 'Seeding';
|
||||
case Torrent._StatusDownloading: return 'Downloading';
|
||||
case Torrent._StatusPaused: return this.isFinished() ? 'Seeding complete' : 'Paused';
|
||||
case Torrent._StatusChecking: return 'Verifying local data';
|
||||
case Torrent._StatusWaitingToCheck: return 'Waiting to verify';
|
||||
case Torrent._StatusStopped: return this.isFinished() ? 'Seeding complete' : 'Paused';
|
||||
case Torrent._StatusCheckWait: return 'Waiting to verify local data';
|
||||
case Torrent._StatusCheck: return 'Verifying local data';
|
||||
case Torrent._StatusDownloadWait: return 'Waiting to download #' + (this.queuePosition()+1);
|
||||
case Torrent._StatusDownload: return 'Downloading';
|
||||
case Torrent._StatusSeedWait: return 'Waiting to seed #' + (this.queuePosition()+1);
|
||||
case Torrent._StatusSeed: return 'Seeding';
|
||||
default: return 'error';
|
||||
}
|
||||
},
|
||||
|
@ -397,6 +413,7 @@ Torrent.prototype =
|
|||
this._peers_connected = data.peersConnected;
|
||||
this._peers_getting_from_us = data.peersGettingFromUs;
|
||||
this._peers_sending_to_us = data.peersSendingToUs;
|
||||
this._queue_position = data.queuePosition;
|
||||
this._webseeds_sending_to_us = data.webseedsSendingToUs;
|
||||
this._sizeWhenDone = data.sizeWhenDone;
|
||||
this._recheckProgress = data.recheckProgress;
|
||||
|
@ -455,12 +472,14 @@ Torrent.prototype =
|
|||
var st = this.state( );
|
||||
switch( st )
|
||||
{
|
||||
case Torrent._StatusPaused:
|
||||
case Torrent._StatusWaitingToCheck:
|
||||
case Torrent._StatusStopped:
|
||||
case Torrent._StatusCheckWait:
|
||||
case Torrent._StatusDownloadWait:
|
||||
case Torrent._StatusSeedWait:
|
||||
c = this.stateStr( );
|
||||
break;
|
||||
|
||||
case Torrent._StatusDownloading:
|
||||
case Torrent._StatusDownload:
|
||||
var a = [ ];
|
||||
if(!compact_mode)
|
||||
a.push( 'Downloading from', this.peersSendingToUs(), 'of', this._peers_connected, 'peers', '-' );
|
||||
|
@ -468,7 +487,7 @@ Torrent.prototype =
|
|||
c = a.join(' ');
|
||||
break;
|
||||
|
||||
case Torrent._StatusSeeding:
|
||||
case Torrent._StatusSeed:
|
||||
if(compact_mode){
|
||||
c = this.formatUL();
|
||||
} else {
|
||||
|
@ -477,7 +496,7 @@ Torrent.prototype =
|
|||
}
|
||||
break;
|
||||
|
||||
case Torrent._StatusChecking:
|
||||
case Torrent._StatusCheck:
|
||||
// 'Verifying local data (40% tested)'
|
||||
c = [ 'Verifying local data (', Transmission.fmt.percentString( 100.0 * this._recheckProgress ), '% tested)' ].join('');
|
||||
break;
|
||||
|
@ -647,7 +666,7 @@ Torrent.prototype =
|
|||
|
||||
// Update the peer details and pause/resume button
|
||||
e = root._pause_resume_button_image;
|
||||
if ( this.state() === Torrent._StatusPaused ) {
|
||||
if ( this.state() === Torrent._StatusStopped ) {
|
||||
e.alt = 'Resume';
|
||||
e.className = "torrent_resume"+compact;
|
||||
} else {
|
||||
|
@ -701,6 +720,7 @@ Torrent.prototype =
|
|||
test: function( filter, search )
|
||||
{
|
||||
var pass = false;
|
||||
var s = this.state( );
|
||||
|
||||
switch( filter )
|
||||
{
|
||||
|
@ -708,10 +728,10 @@ Torrent.prototype =
|
|||
pass = this.isActiveFilter();
|
||||
break;
|
||||
case Prefs._FilterSeeding:
|
||||
pass = this.isSeeding();
|
||||
pass = ( s == Torrent._StatusSeed ) || ( s == Torrent._StatusSeedWait );
|
||||
break;
|
||||
case Prefs._FilterDownloading:
|
||||
pass = this.isDownloading();
|
||||
pass = ( s == Torrent._StatusDownload ) || ( s == Torrent._StatusDownloadWait );
|
||||
break;
|
||||
case Prefs._FilterPaused:
|
||||
pass = !this.isActive();
|
||||
|
@ -739,38 +759,76 @@ Torrent.compareById = function( a, b ) {
|
|||
return a.id() - b.id();
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByAge = function( a, b ) {
|
||||
return a.dateAdded() - b.dateAdded();
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByName = function( a, b ) {
|
||||
return a._name_lc.compareTo( b._name_lc );
|
||||
var i = a._name_lc.compareTo( b._name_lc );
|
||||
if( i )
|
||||
return i;
|
||||
return Torrent.compareById( a, b );
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByState = function( a, b ) {
|
||||
return a.state() - b.state();
|
||||
Torrent.compareByQueue = function( a, b )
|
||||
{
|
||||
var a_is_queued = a.isQueued( );
|
||||
var b_is_queued = b.isQueued( );
|
||||
if( a_is_queued != b_is_queued )
|
||||
return a_is_queued ? -1 : 1;
|
||||
|
||||
var a_pos = a.queuePosition( );
|
||||
var b_pos = b.queuePosition( );
|
||||
if( a_pos != b_pos )
|
||||
return a_pos - b_pos;
|
||||
|
||||
return Torrent.compareByName( a, b );
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByActivity = function( a, b ) {
|
||||
return a.activity() - b.activity();
|
||||
Torrent.compareByAge = function( a, b )
|
||||
{
|
||||
var a_age = a.dateAdded();
|
||||
var b_age = b.dateAdded();
|
||||
if( a_age != b_age )
|
||||
return a_age - b_age;
|
||||
|
||||
return Torrent.compareByQueue( a, b );
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByState = function( a, b )
|
||||
{
|
||||
var a_state = a.state( );
|
||||
var b_state = b.state( );
|
||||
if( a_state != b_state )
|
||||
return b_state - a_state;
|
||||
|
||||
return Torrent.compareByQueue( a, b );
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByActivity = function( a, b )
|
||||
{
|
||||
var a_activity = a.activity( );
|
||||
var b_activity = b.activity( );
|
||||
if( a_activity != b_activity )
|
||||
return a_activity - b_activity;
|
||||
|
||||
return Torrent.compareByState( a, b );
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByRatio = function( a, b ) {
|
||||
var a_ratio = Math.ratio( a._upload_total, a._download_total );
|
||||
var b_ratio = Math.ratio( b._upload_total, b._download_total );
|
||||
return a_ratio - b_ratio;
|
||||
if( a_ratio != b_ratio )
|
||||
return a_ratio - b_ratio;
|
||||
return Torrent.compareByState( a, b );
|
||||
};
|
||||
|
||||
/** Helper function for sortTorrents(). */
|
||||
Torrent.compareByProgress = function( a, b ) {
|
||||
if( a.getPercentDone() !== b.getPercentDone() )
|
||||
return a.getPercentDone() - b.getPercentDone();
|
||||
return this.compareByRatio( a, b );
|
||||
return Torrent.compareByRatio( a, b );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -788,9 +846,6 @@ Torrent.sortTorrents = function( torrents, sortMethod, sortDirection )
|
|||
case Prefs._SortByAge:
|
||||
torrents.sort( this.compareByAge );
|
||||
break;
|
||||
case Prefs._SortByQueue:
|
||||
torrents.sort( this.compareById );
|
||||
break;
|
||||
case Prefs._SortByProgress:
|
||||
torrents.sort( this.compareByProgress );
|
||||
break;
|
||||
|
|
|
@ -100,6 +100,7 @@ Transmission.prototype =
|
|||
this._toolbar_remove_button = $('li#remove')[0];
|
||||
this._context_pause_button = $('li#context_pause_selected')[0];
|
||||
this._context_start_button = $('li#context_resume_selected')[0];
|
||||
this._context_start_now_button = $('li#context_resume_now_selected')[0];
|
||||
|
||||
var ti = '#torrent_inspector_';
|
||||
this._inspector = { };
|
||||
|
@ -281,7 +282,10 @@ Transmission.prototype =
|
|||
this.stopSelectedTorrents( );
|
||||
},
|
||||
contextStartSelected: function( ) {
|
||||
this.startSelectedTorrents( );
|
||||
this.startSelectedTorrents( false );
|
||||
},
|
||||
contextStartNowSelected: function( ) {
|
||||
this.startSelectedTorrents( true );
|
||||
},
|
||||
contextRemoveSelected: function( ) {
|
||||
this.removeSelectedTorrents( );
|
||||
|
@ -311,15 +315,16 @@ Transmission.prototype =
|
|||
createContextMenu: function() {
|
||||
var tr = this;
|
||||
var bindings = {
|
||||
context_pause_selected: function(e){ tr.contextStopSelected(e); },
|
||||
context_resume_selected: function(e){ tr.contextStartSelected(e); },
|
||||
context_remove: function(e){ tr.contextRemoveSelected(e); },
|
||||
context_removedata: function(e){ tr.contextRemoveDataSelected(e); },
|
||||
context_verify: function(e){ tr.contextVerifySelected(e); },
|
||||
context_reannounce: function(e){ tr.contextReannounceSelected(e); },
|
||||
context_toggle_inspector: function(e){ tr.contextToggleInspector(e); },
|
||||
context_select_all: function(e){ tr.contextSelectAll(e); },
|
||||
context_deselect_all: function(e){ tr.contextDeselectAll(e); }
|
||||
context_pause_selected: function(e){ tr.contextStopSelected(e); },
|
||||
context_resume_selected: function(e){ tr.contextStartSelected(e); },
|
||||
context_resume_now_selected: function(e){ tr.contextStartNowSelected(e); },
|
||||
context_remove: function(e){ tr.contextRemoveSelected(e); },
|
||||
context_removedata: function(e){ tr.contextRemoveDataSelected(e); },
|
||||
context_verify: function(e){ tr.contextVerifySelected(e); },
|
||||
context_reannounce: function(e){ tr.contextReannounceSelected(e); },
|
||||
context_toggle_inspector: function(e){ tr.contextToggleInspector(e); },
|
||||
context_select_all: function(e){ tr.contextSelectAll(e); },
|
||||
context_deselect_all: function(e){ tr.contextDeselectAll(e); }
|
||||
};
|
||||
|
||||
// Setup the context menu
|
||||
|
@ -618,7 +623,7 @@ Transmission.prototype =
|
|||
startSelectedClicked: function( event ) {
|
||||
var tr = this;
|
||||
if( tr.isButtonEnabled( event ) ) {
|
||||
tr.startSelectedTorrents( );
|
||||
tr.startSelectedTorrents( false );
|
||||
tr.hideiPhoneAddressbar( );
|
||||
}
|
||||
},
|
||||
|
@ -1994,19 +1999,19 @@ Transmission.prototype =
|
|||
this.reannounceTorrents( this.getSelectedTorrents( ) );
|
||||
},
|
||||
|
||||
startSelectedTorrents: function( ) {
|
||||
this.startTorrents( this.getSelectedTorrents( ) );
|
||||
startSelectedTorrents: function( force ) {
|
||||
this.startTorrents( this.getSelectedTorrents( ), force );
|
||||
},
|
||||
startAllTorrents: function( ) {
|
||||
this.startTorrents( this.getAllTorrents( ) );
|
||||
this.startTorrents( this.getAllTorrents( ), false );
|
||||
},
|
||||
startTorrent: function( torrent ) {
|
||||
this.startTorrents( [ torrent ] );
|
||||
this.startTorrents( [ torrent ], false );
|
||||
},
|
||||
startTorrents: function( torrents ) {
|
||||
startTorrents: function( torrents, force ) {
|
||||
var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
|
||||
var tr = this;
|
||||
this.remote.startTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids) } );
|
||||
this.remote.startTorrents( torrent_ids, force, function(){ tr.refreshTorrents(torrent_ids) } );
|
||||
},
|
||||
verifyTorrent: function( torrent ) {
|
||||
this.verifyTorrents( [ torrent ] );
|
||||
|
@ -2137,6 +2142,7 @@ Transmission.prototype =
|
|||
this.setEnabled( this._context_pause_button, haveActiveSelection );
|
||||
this.setEnabled( this._toolbar_start_button, havePausedSelection );
|
||||
this.setEnabled( this._context_start_button, havePausedSelection );
|
||||
this.setEnabled( this._context_start_now_button, havePausedSelection );
|
||||
this.setEnabled( this._toolbar_remove_button, haveSelection );
|
||||
this.setEnabled( this._toolbar_pause_all_button, haveActive );
|
||||
this.setEnabled( this._toolbar_start_all_button, havePaused );
|
||||
|
|
|
@ -28,17 +28,17 @@ RPC._TurtleTimeEnabled = 'alt-speed-time-enabled';
|
|||
RPC._TurtleTimeBegin = 'alt-speed-time-begin';
|
||||
RPC._TurtleTimeEnd = 'alt-speed-time-end';
|
||||
RPC._TurtleTimeDay = 'alt-speed-time-day';
|
||||
RPC._PeerLimitGlobal = 'peer-limit-global';
|
||||
RPC._PeerLimitPerTorrent = 'peer-limit-per-torrent';
|
||||
RPC._PexEnabled = 'pex-enabled';
|
||||
RPC._DhtEnabled = 'dht-enabled';
|
||||
RPC._LpdEnabled = 'lpd-enabled';
|
||||
RPC._BlocklistEnabled = 'blocklist-enabled';
|
||||
RPC._BlocklistURL = 'blocklist-url';
|
||||
RPC._BlocklistSize = 'blocklist-size';
|
||||
RPC._UtpEnabled = 'utp-enabled';
|
||||
RPC._PeerPortRandom = 'peer-port-random-on-start';
|
||||
RPC._PortForwardingEnabled = 'port-forwarding-enabled';
|
||||
RPC._PeerLimitGlobal = 'peer-limit-global';
|
||||
RPC._PeerLimitPerTorrent = 'peer-limit-per-torrent';
|
||||
RPC._PexEnabled = 'pex-enabled';
|
||||
RPC._DhtEnabled = 'dht-enabled';
|
||||
RPC._LpdEnabled = 'lpd-enabled';
|
||||
RPC._BlocklistEnabled = 'blocklist-enabled';
|
||||
RPC._BlocklistURL = 'blocklist-url';
|
||||
RPC._BlocklistSize = 'blocklist-size';
|
||||
RPC._UtpEnabled = 'utp-enabled';
|
||||
RPC._PeerPortRandom = 'peer-port-random-on-start';
|
||||
RPC._PortForwardingEnabled = 'port-forwarding-enabled';
|
||||
RPC._StartAddedTorrent = 'start-added-torrents';
|
||||
|
||||
function TransmissionRemote( controller )
|
||||
|
@ -215,8 +215,9 @@ TransmissionRemote.prototype =
|
|||
this.sendTorrentSetRequests( method, torrent_ids, null, callback );
|
||||
},
|
||||
|
||||
startTorrents: function( torrent_ids, callback ) {
|
||||
this.sendTorrentActionRequests( 'torrent-start', torrent_ids, callback );
|
||||
startTorrents: function( torrent_ids, noqueue, callback ) {
|
||||
var name = noqueue ? 'torrent-start-now' : 'torrent-start';
|
||||
this.sendTorrentActionRequests( name, torrent_ids, callback );
|
||||
},
|
||||
stopTorrents: function( torrent_ids, callback ) {
|
||||
this.sendTorrentActionRequests( 'torrent-stop', torrent_ids, callback );
|
||||
|
|
Loading…
Reference in New Issue