Changeset 12607


Ignore:
Timestamp:
Aug 1, 2011, 10:24:24 PM (10 years ago)
Author:
jordan
Message:

(trunk) #671 "torrent queuing" -- Preliminary implementation. Covers libtransmission; GTK+ and Qt clients, and rudimentary web client support.

Location:
trunk
Files:
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/extras/rpc-spec.txt

    r12524 r12607  
    6666   ---------------------+-------------------------------------------------
    6767   "torrent-start"      | tr_torrentStart
     68   "torrent-start-now"  | tr_torrentStartNow
    6869   "torrent-stop"       | tr_torrentStop
    6970   "torrent-verify"     | tr_torrentVerify
     
    99100   "priority-low"        | array      indices of low-priority file(s)
    100101   "priority-normal"     | array      indices of normal-priority file(s)
     102   "queuePosition"       | number     position of this torrent in its queue [0...n)
    101103   "seedIdleLimit"       | number     torrent-level number of minutes of seeding inactivity
    102104   "seedIdleMode"        | number     which seeding inactivity to use.  See tr_inactvelimit
     
    180182   pieceSize                   | number                      | tr_info
    181183   priorities                  | array (see below)           | n/a
     184   queuePosition               | number                      | tr_stat
    182185   rateDownload (B/s)          | number                      | tr_stat
    183186   rateUpload (B/s)            | number                      | tr_stat
     
    424427   "download-dir"                   | string     | default path to download torrents
    425428   "download-dir-free-space"        | number     | number of free bytes available in download-dir, or -1 if it can't be calculated
     429   "download-queue-size"            | number     | max number of torrents to download at once (see download-queue-enabled)
     430   "download-queue-enabled"         | boolean    | if true, limit how many torrents can be downloaded at once
    426431   "dht-enabled"                    | boolean    | true means allow dht in public torrents
    427432   "encryption"                     | string     | "required", "preferred", "tolerated"
     
    437442   "peer-port-random-on-start"      | boolean    | true means pick a random peer port on launch
    438443   "port-forwarding-enabled"        | boolean    | true means enabled
     444   "queue-stalled-minutes"          | number     | torrents that are idle for N minuets aren't counted toward seed-queue-size or download-queue-size
    439445   "rename-partial-files"           | boolean    | true means append ".part" to incomplete files
    440446   "rpc-version"                    | number     | the current RPC API version
     
    444450   "seedRatioLimit"                 | double     | the default seed ratio for torrents to use
    445451   "seedRatioLimited"               | boolean    | true if seedRatioLimit is honored by default
     452   "seed-queue-size"                | number     | max number of torrents to uploaded at once (see seed-queue-enabled)
     453   "seed-queue-enabled"             | boolean    | if true, limit how many torrents can be uploaded at once
    446454   "speed-limit-down"               | number     | max global download speed (KBps)
    447455   "speed-limit-down-enabled"       | boolean    | true means enabled
     
    537545   This method tells the transmission session to shut down.
    538546
    539    Method-name: "session-close"
     547   Method name: "session-close"
    540548   Request arguments: none
     549   Response arguments: none
     550
     5514.6.  Queue Movement Requests
     552
     553   Method name          | libtransmission function
     554   ---------------------+-------------------------------------------------
     555   "queue-move-top"     | tr_torrentQueueMoveTop()
     556   "queue-move-up"      | tr_torrentQueueMoveUp()
     557   "queue-move-down"    | tr_torrentQueueMoveDown()
     558   "queue-move-bottom"  | tr_torrentQueueMoveBottom()
     559
     560   Request arguments:
     561
     562   string      | value type & description
     563   ------------+----------------------------------------------------------
     564   "ids"       | array   torrent list, as described in 3.1.
     565
    541566   Response arguments: none
    542567
     
    663688         |         | yes       | torrent-add    | new arg "cookies"
    664689         |         |        NO | torrent-get    | removed arg "peersKnown"
     690   ------+---------+-----------+----------------+-------------------------------
     691   14    | 2.40    |        NO | torrent-get    | values of "status" field changed
     692         |         | yes       | torrent-get    | new arg "queuePosition"
     693         |         | yes       | torrent-set    | new arg "queuePosition"
     694         |         | yes       | session-set    | new arg "download-queue-size"
     695         |         | yes       | session-set    | new arg "download-queue-enabled"
     696         |         | yes       | session-set    | new arg "seed-queue-size"
     697         |         | yes       | session-set    | new arg "seed-queue-enabled"
     698         |         | yes       | session-set    | new arg "queue-stalled-minutes"
     699         |         | yes       |                | new method "queue-move-top"
     700         |         | yes       |                | new method "queue-move-up"
     701         |         | yes       |                | new method "queue-move-down"
     702         |         | yes       |                | new method "queue-move-bottom"
     703         |         | yes       |                | new method "torrent-start-now"
  • trunk/gtk/actions.c

    r12354 r12607  
    101101    { "view-menu", NULL, N_( "_View" ), NULL, NULL, NULL  },
    102102    { "sort-menu", NULL, N_( "_Sort Torrents By" ), NULL, NULL, NULL },
     103    { "queue-menu", NULL, N_( "_Queue" ), NULL, NULL, NULL },
    103104    { "edit-menu", NULL, N_( "_Edit" ), NULL, NULL, NULL },
    104105    { "help-menu", NULL, N_( "_Help" ), NULL, NULL, NULL },
     
    107108    { "open-torrent-toolbar",  GTK_STOCK_OPEN, NULL, NULL, N_( "Open a torrent" ),  G_CALLBACK( action_cb ) },
    108109    { "open-torrent-menu", GTK_STOCK_OPEN, NULL, NULL, N_( "Open a torrent" ), G_CALLBACK( action_cb ) },
    109     { "start-torrent", GTK_STOCK_MEDIA_PLAY, N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK( action_cb ) },
     110    { "torrent-start", GTK_STOCK_MEDIA_PLAY, N_( "_Start" ), "<control>S", N_( "Start torrent" ), G_CALLBACK( action_cb ) },
     111    { "torrent-start-now", GTK_STOCK_MEDIA_PLAY, N_( "Start _Now" ), "<shift><control>S", N_( "Start torrent now" ), G_CALLBACK( action_cb ) },
    110112    { "show-stats", NULL, N_( "_Statistics" ), NULL, NULL, G_CALLBACK( action_cb ) },
    111113    { "donate", NULL, N_( "_Donate" ), NULL, NULL, G_CALLBACK( action_cb ) },
    112     { "verify-torrent", NULL, N_( "_Verify Local Data" ), "<control>V", NULL, G_CALLBACK( action_cb ) },
    113     { "pause-torrent", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK( action_cb ) },
     114    { "torrent-verify", NULL, N_( "_Verify Local Data" ), "<control>V", NULL, G_CALLBACK( action_cb ) },
     115    { "torrent-stop", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause" ), "<control>P", N_( "Pause torrent" ), G_CALLBACK( action_cb ) },
    114116    { "pause-all-torrents", GTK_STOCK_MEDIA_PAUSE, N_( "_Pause All" ), NULL, N_( "Pause all torrents" ), G_CALLBACK( action_cb ) },
    115117    { "start-all-torrents", GTK_STOCK_MEDIA_PLAY, N_( "_Start All" ), NULL, N_( "Start all torrents" ), G_CALLBACK( action_cb ) },
     
    126128    { "show-about-dialog", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK( action_cb ) },
    127129    { "help", GTK_STOCK_HELP, N_( "_Contents" ), "F1", NULL, G_CALLBACK( action_cb ) },
    128     { "update-tracker", GTK_STOCK_NETWORK, N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK( action_cb ) },
     130    { "torrent-reannounce", GTK_STOCK_NETWORK, N_( "Ask Tracker for _More Peers" ), NULL, NULL, G_CALLBACK( action_cb ) },
     131    { "queue-move-top", GTK_STOCK_GOTO_TOP, N_( "Move to _Top" ), NULL, NULL, G_CALLBACK( action_cb ) },
     132    { "queue-move-up", GTK_STOCK_GO_UP, N_( "Move _Up" ), NULL, NULL, G_CALLBACK( action_cb ) },
     133    { "queue-move-down", GTK_STOCK_GO_DOWN, N_( "Move _Down" ), NULL, NULL, G_CALLBACK( action_cb ) },
     134    { "queue-move-bottom", GTK_STOCK_GOTO_BOTTOM, N_( "Move to _Bottom" ), NULL, NULL, G_CALLBACK( action_cb ) }
    129135};
    130136
  • trunk/gtk/details.c

    r12487 r12607  
    558558    switch( activity )
    559559    {
    560         case TR_STATUS_CHECK_WAIT: return _( "Waiting to verify local data" );
    561         case TR_STATUS_CHECK:      return _( "Verifying local data" );
    562         case TR_STATUS_DOWNLOAD:   return _( "Downloading" );
    563         case TR_STATUS_SEED:       return _( "Seeding" );
    564         case TR_STATUS_STOPPED:    return finished ? _( "Finished" ) : _( "Paused" );
     560        case TR_STATUS_CHECK_WAIT:    return _( "Waiting to verify local data" );
     561        case TR_STATUS_CHECK:         return _( "Verifying local data" );
     562        case TR_STATUS_DOWNLOAD_WAIT: return _( "Queued to download" );
     563        case TR_STATUS_DOWNLOAD:      return _( "Downloading" );
     564        case TR_STATUS_SEED_WAIT:     return _( "Queued to seed" );
     565        case TR_STATUS_SEED:          return _( "Seeding" );
     566        case TR_STATUS_STOPPED:       return finished ? _( "Finished" ) : _( "Paused" );
    565567    }
    566568
  • trunk/gtk/filter.c

    r12399 r12607  
    582582    ACTIVITY_FILTER_PAUSED,
    583583    ACTIVITY_FILTER_FINISHED,
    584     ACTIVITY_FILTER_QUEUED,
    585584    ACTIVITY_FILTER_VERIFYING,
    586585    ACTIVITY_FILTER_ERROR,
     
    613612    {
    614613        case ACTIVITY_FILTER_DOWNLOADING:
    615             return st->activity == TR_STATUS_DOWNLOAD;
     614            return ( st->activity == TR_STATUS_DOWNLOAD )
     615                || ( st->activity == TR_STATUS_DOWNLOAD_WAIT );
    616616
    617617        case ACTIVITY_FILTER_SEEDING:
    618             return st->activity == TR_STATUS_SEED;
     618            return ( st->activity == TR_STATUS_SEED )
     619                || ( st->activity == TR_STATUS_SEED_WAIT );
    619620
    620621        case ACTIVITY_FILTER_ACTIVE:
     
    630631            return st->finished == TRUE;
    631632
    632         case ACTIVITY_FILTER_QUEUED:
    633             return st->activity == TR_STATUS_CHECK_WAIT;
    634 
    635633        case ACTIVITY_FILTER_VERIFYING:
    636             return ( st->activity == TR_STATUS_CHECK ) || ( st->activity == TR_STATUS_CHECK_WAIT );
     634            return ( st->activity == TR_STATUS_CHECK )
     635                || ( st->activity == TR_STATUS_CHECK_WAIT );
    637636
    638637        case ACTIVITY_FILTER_ERROR:
     
    701700        { ACTIVITY_FILTER_PAUSED, N_( "Paused" ), GTK_STOCK_MEDIA_PAUSE },
    702701        { ACTIVITY_FILTER_FINISHED, N_( "Finished" ), NULL },
    703         { ACTIVITY_FILTER_QUEUED, N_( "Queued" ), NULL },
    704702        { ACTIVITY_FILTER_VERIFYING, N_( "Verifying" ), GTK_STOCK_REFRESH },
    705703        { ACTIVITY_FILTER_ERROR, N_( "Error" ), GTK_STOCK_DIALOG_ERROR }
  • trunk/gtk/main.c

    r12602 r12607  
    249249    int total_count;
    250250    int active_count;
    251     int inactive_count;
     251    int queued_count;
     252    int stopped_count;
    252253};
    253254
     
    257258{
    258259    int activity = 0;
     260    int queuePosition = -1;
    259261    struct counts_data * counts = user_data;
    260262
     
    263265    gtk_tree_model_get( model, iter, MC_ACTIVITY, &activity, -1 );
    264266
    265     if( activity == TR_STATUS_STOPPED )
    266         ++counts->inactive_count;
     267    if( activity == TR_STATUS_DOWNLOAD_WAIT )
     268        ++counts->queued_count;
     269
     270    if( ( activity == TR_STATUS_STOPPED ) && ( queuePosition < 0 ) )
     271        ++counts->stopped_count;
    267272    else
    268273        ++counts->active_count;
     
    272277get_selected_torrent_counts( struct cbdata * data, struct counts_data * counts )
    273278{
     279    counts->total_count = 0;
    274280    counts->active_count = 0;
    275     counts->inactive_count = 0;
    276     counts->total_count = 0;
     281    counts->queued_count = 0;
     282    counts->stopped_count = 0;
    277283
    278284    gtk_tree_selection_selected_foreach( data->sel, get_selected_torrent_counts_foreach, counts );
     
    297303    const size_t active = gtr_core_get_active_torrent_count( data->core );
    298304    const int torrent_count = gtk_tree_model_iter_n_children( gtr_core_model( data->core ), NULL );
     305    const tr_session * session = gtr_core_session( data->core );
     306    const bool queue_enabled = tr_sessionGetQueueEnabled( session, TR_DOWN )
     307                            || tr_sessionGetQueueEnabled( session, TR_UP );
    299308
    300309    gtr_action_set_sensitive( "select-all", torrent_count != 0 );
     
    304313
    305314    get_selected_torrent_counts( data, &sel_counts );
    306     gtr_action_set_sensitive( "pause-torrent", sel_counts.active_count != 0 );
    307     gtr_action_set_sensitive( "start-torrent", sel_counts.inactive_count != 0 );
     315    gtr_action_set_sensitive( "torrent-stop", ( sel_counts.active_count + sel_counts.queued_count ) > 0 );
     316    gtr_action_set_sensitive( "torrent-start", ( sel_counts.stopped_count ) > 0 );
     317    gtr_action_set_sensitive( "torrent-start-now", ( sel_counts.stopped_count + sel_counts.queued_count ) > 0 );
     318    gtr_action_set_sensitive( "torrent-verify", sel_counts.total_count != 0 );
    308319    gtr_action_set_sensitive( "remove-torrent", sel_counts.total_count != 0 );
    309320    gtr_action_set_sensitive( "delete-torrent", sel_counts.total_count != 0 );
    310     gtr_action_set_sensitive( "verify-torrent", sel_counts.total_count != 0 );
    311321    gtr_action_set_sensitive( "relocate-torrent", sel_counts.total_count != 0 );
    312322    gtr_action_set_sensitive( "show-torrent-properties", sel_counts.total_count != 0 );
    313323    gtr_action_set_sensitive( "open-torrent-folder", sel_counts.total_count == 1 );
    314324    gtr_action_set_sensitive( "copy-magnet-link-to-clipboard", sel_counts.total_count == 1 );
     325    gtr_action_set_sensitive( "queue-move-top",    queue_enabled && ( sel_counts.queued_count > 0 ) );
     326    gtr_action_set_sensitive( "queue-move-up",     queue_enabled && ( sel_counts.queued_count > 0 ) );
     327    gtr_action_set_sensitive( "queue-move-down",   queue_enabled && ( sel_counts.queued_count > 0 ) );
     328    gtr_action_set_sensitive( "queue-move-bottom", queue_enabled && ( sel_counts.queued_count > 0 ) );
    315329
    316330    canUpdate = 0;
    317331    gtk_tree_selection_selected_foreach( data->sel, count_updatable_foreach, &canUpdate );
    318     gtr_action_set_sensitive( "update-tracker", canUpdate != 0 );
     332    gtr_action_set_sensitive( "torrent-reannounce", canUpdate != 0 );
    319333
    320334    data->refresh_actions_tag = 0;
     
    12871301        tr_sessionSetIncompleteFileNamingEnabled( tr, gtr_pref_flag_get( key ) );
    12881302    }
     1303    else if( !strcmp( key, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE ) )
     1304    {
     1305        tr_sessionSetQueueSize( tr, TR_DOWN, gtr_pref_int_get( key ) );
     1306    }
     1307    else if( !strcmp( key, TR_PREFS_KEY_QUEUE_STALLED_MINUTES ) )
     1308    {
     1309        tr_sessionSetQueueStalledMinutes( tr, gtr_pref_int_get( key ) );
     1310    }
    12891311    else if( !strcmp( key, TR_PREFS_KEY_DHT_ENABLED ) )
    12901312    {
     
    16621684        }
    16631685    }
    1664     else if( !strcmp( action_name, "start-torrent" ) )
    1665     {
    1666         changed |= call_rpc_for_selected_torrents( data, "torrent-start" );
    1667     }
    1668     else if( !strcmp( action_name, "pause-torrent" ) )
    1669     {
    1670         changed |= call_rpc_for_selected_torrents( data, "torrent-stop" );
    1671     }
    1672     else if( !strcmp( action_name, "verify-torrent" ) )
    1673     {
    1674         changed |= call_rpc_for_selected_torrents( data, "torrent-verify" );
    1675     }
    1676     else if( !strcmp( action_name, "update-tracker" ) )
    1677     {
    1678         changed |= call_rpc_for_selected_torrents( data, "torrent-reannounce" );
     1686    else if( !strcmp( action_name, "torrent-start" )
     1687          || !strcmp( action_name, "torrent-start-now" )
     1688          || !strcmp( action_name, "torrent-stop" )
     1689          || !strcmp( action_name, "torrent-reannounce" )
     1690          || !strcmp( action_name, "torrent-verify" )
     1691          || !strcmp( action_name, "queue-move-top" )
     1692          || !strcmp( action_name, "queue-move-up" )
     1693          || !strcmp( action_name, "queue-move-down" )
     1694          || !strcmp( action_name, "queue-move-bottom" ) )
     1695    {
     1696        changed |= call_rpc_for_selected_torrents( data, action_name );
    16791697    }
    16801698    else if( !strcmp( action_name, "open-torrent-folder" ) )
  • trunk/gtk/torrent-cell-renderer.c

    r12591 r12607  
    227227            break;
    228228
     229        case TR_STATUS_DOWNLOAD_WAIT:
     230            g_string_append_printf( gstr, _( "Download queue #%d" ), st->queuePosition + 1 );
     231            break;
     232
     233        case TR_STATUS_SEED_WAIT:
     234            g_string_append_printf( gstr, _( "Seed queue #%d" ), st->queuePosition + 1 );
     235            break;
     236
    229237        case TR_STATUS_DOWNLOAD:
    230238        case TR_STATUS_SEED:
     
    254262                 const double        downloadSpeed_KBps )
    255263{
    256     const int isActive = st->activity != TR_STATUS_STOPPED;
    257     const int isChecking = st->activity == TR_STATUS_CHECK
    258                         || st->activity == TR_STATUS_CHECK_WAIT;
    259 
    260264    if( st->error )
    261265    {
     
    270274        case TR_STATUS_CHECK_WAIT:
    271275        case TR_STATUS_CHECK:
     276        case TR_STATUS_DOWNLOAD_WAIT:
     277        case TR_STATUS_SEED_WAIT:
    272278        {
    273279            getShortStatusString( gstr, tor, st, uploadSpeed_KBps, downloadSpeed_KBps );
     
    308314    }
    309315
    310     if( isActive && !isChecking )
     316    if( ( st->activity != TR_STATUS_CHECK_WAIT ) &&
     317        ( st->activity != TR_STATUS_CHECK ) &&
     318        ( st->activity != TR_STATUS_DOWNLOAD_WAIT ) &&
     319        ( st->activity != TR_STATUS_SEED_WAIT ) &&
     320        ( st->activity != TR_STATUS_STOPPED ) )
    311321    {
    312322        char buf[256];
     
    631641    const tr_torrent * tor = p->tor;
    632642    const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );
    633     const gboolean active = st->activity != TR_STATUS_STOPPED;
     643    const gboolean active = ( st->activity != TR_STATUS_STOPPED ) && ( st->activity != TR_STATUS_DOWNLOAD_WAIT ) && ( st->activity != TR_STATUS_SEED_WAIT );
    634644    const double percentDone = get_percent_done( tor, st, &seed );
    635645    const gboolean sensitive = active || st->error;
     
    674684    g_object_set( p->icon_renderer, "pixbuf", icon, "sensitive", sensitive, NULL );
    675685    gtr_cell_renderer_render( p->icon_renderer, window, widget, &icon_area, flags );
    676     g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", NULL, "sensitive", sensitive,
     686    g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", NULL,
     687        "sensitive", sensitive || ( st->queuePosition >= 0 ),
    677688#if GTK_CHECK_VERSION( 3,0,0 )
    678689        "inverted", seed,
     
    684695    g_object_set( p->text_renderer, "text", gstr_stat->str, "scale", SMALL_SCALE, "ellipsize", PANGO_ELLIPSIZE_END, FOREGROUND_COLOR_KEY, &text_color, NULL );
    685696    gtr_cell_renderer_render( p->text_renderer, window, widget, &stat_area, flags );
    686     g_object_set( p->text_renderer, "text", name, "scale", 1.0, NULL );
     697    g_object_set( p->text_renderer, "text", name, "scale", 1.0, FOREGROUND_COLOR_KEY, &text_color, NULL );
    687698    gtr_cell_renderer_render( p->text_renderer, window, widget, &name_area, flags );
    688699
     
    716727    const tr_stat * st = tr_torrentStatCached( (tr_torrent*)tor );
    717728    const tr_info * inf = tr_torrentInfo( tor );
    718     const gboolean active = st->activity != TR_STATUS_STOPPED;
     729    const gboolean active = ( st->activity != TR_STATUS_STOPPED ) && ( st->activity != TR_STATUS_DOWNLOAD_WAIT ) && ( st->activity != TR_STATUS_SEED_WAIT );
    719730    const double percentDone = get_percent_done( tor, st, &seed );
    720731    const gboolean sensitive = active || st->error;
     
    794805    g_object_set( p->text_renderer, "text", gstr_prog->str, "scale", SMALL_SCALE, "weight", PANGO_WEIGHT_NORMAL, NULL );
    795806    gtr_cell_renderer_render( p->text_renderer, window, widget, &prog_area, flags );
    796     g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", "", "sensitive", sensitive,
     807    g_object_set( p->progress_renderer, "value", (int)(percentDone*100.0), "text", "", "sensitive", ( sensitive || st->queuePosition >= 0 ),
    797808#if GTK_CHECK_VERSION( 3,0,0 )
    798809        "inverted", seed,
     
    802813        NULL );
    803814    gtr_cell_renderer_render( p->progress_renderer, window, widget, &prct_area, flags );
    804     g_object_set( p->text_renderer, "text", gstr_stat->str, NULL );
     815    g_object_set( p->text_renderer, "text", gstr_stat->str, FOREGROUND_COLOR_KEY, &text_color, NULL );
    805816    gtr_cell_renderer_render( p->text_renderer, window, widget, &stat_area, flags );
    806817
  • trunk/gtk/tr-core.c

    r12375 r12607  
    248248                      G_TYPE_UCHAR,     /* tr_stat.finished */
    249249                      G_TYPE_CHAR,      /* tr_priority_t */
     250                      G_TYPE_INT,       /* tr_stat.queuePosition */
    250251                      G_TYPE_UINT,      /* build_torrent_trackers_hash() */
    251252                      G_TYPE_INT,       /* MC_ERROR */
     
    459460
    460461static int
     462compare_by_queue( const tr_stat * a, const tr_stat * b )
     463{
     464    const bool a_is_queued = a->queuePosition >= 0;
     465    const bool b_is_queued = b->queuePosition >= 0;
     466    if( a_is_queued != b_is_queued ) return a_is_queued ? -1 : 1;
     467    return b->queuePosition - a->queuePosition;
     468}
     469
     470static int
    461471compare_by_ratio( GtkTreeModel* m, GtkTreeIter * a, GtkTreeIter * b, gpointer user_data )
    462472{
     
    471481
    472482    if( !ret ) ret = compare_ratio( sa->ratio, sb->ratio );
     483    if( !ret ) ret = compare_by_queue( sa, sb );
    473484    if( !ret ) ret = compare_by_name( m, a, b, user_data );
    474485    return ret;
     
    496507    if( !ret ) ret = compare_double( aUp+aDown, bUp+bDown );
    497508    if( !ret ) ret = compare_uint64( sa->uploadedEver, sb->uploadedEver );
     509    if( !ret ) ret = compare_by_queue( sa, sb );
    498510    if( !ret ) ret = compare_by_name( m, a, b, user_data );
    499511    return ret;
     
    570582    int ret = 0;
    571583    int sa, sb;
    572 
    573     gtk_tree_model_get( m, a, MC_ACTIVITY, &sa, -1 );
    574     gtk_tree_model_get( m, b, MC_ACTIVITY, &sb, -1 );
     584    tr_torrent *ta, *tb;
     585
     586    gtk_tree_model_get( m, a, MC_ACTIVITY, &sa, MC_TORRENT, &ta, -1 );
     587    gtk_tree_model_get( m, b, MC_ACTIVITY, &sb, MC_TORRENT, &tb, -1 );
    575588
    576589    if( !ret ) ret = compare_int( sa, sb );
     590    if( !ret ) ret = compare_by_queue( tr_torrentStatCached( ta ), tr_torrentStatCached( tb ) );
    577591    if( !ret ) ret = compare_by_progress( m, a, b, u );
    578592    return ret;
     
    10271041            MC_FINISHED,          st->finished,
    10281042            MC_PRIORITY,          tr_torrentGetPriority( tor ),
     1043            MC_QUEUE_POSITION,    st->queuePosition,
    10291044            MC_TRACKERS,          trackers_hash,
    10301045            -1 );
     
    14131428    int oldError, newError;
    14141429    bool oldFinished, newFinished;
     1430    int oldQueuePosition, newQueuePosition;
    14151431    tr_priority_t oldPriority, newPriority;
    14161432    unsigned int oldTrackers, newTrackers;
     
    14311447                        MC_FINISHED, &oldFinished,
    14321448                        MC_PRIORITY, &oldPriority,
     1449                        MC_QUEUE_POSITION, &oldQueuePosition,
    14331450                        MC_TRACKERS, &oldTrackers,
    14341451                        MC_SPEED_UP, &oldUpSpeed,
     
    14431460    newFinished = st->finished;
    14441461    newPriority = tr_torrentGetPriority( tor );
     1462    newQueuePosition = st->queuePosition;
    14451463    newTrackers = build_torrent_trackers_hash( tor );
    14461464    newUpSpeed = st->pieceUploadSpeed_KBps;
     
    14561474        || ( newFinished != oldFinished )
    14571475        || ( newPriority != oldPriority )
     1476        || ( newQueuePosition != oldQueuePosition )
    14581477        || ( newError != oldError )
    14591478        || ( newActivePeerCount != oldActivePeerCount )
     
    14701489                            MC_FINISHED, newFinished,
    14711490                            MC_PRIORITY, newPriority,
     1491                            MC_QUEUE_POSITION, newQueuePosition,
    14721492                            MC_TRACKERS, newTrackers,
    14731493                            MC_SPEED_UP, newUpSpeed,
  • trunk/gtk/tr-core.h

    r12321 r12607  
    194194    MC_FINISHED,
    195195    MC_PRIORITY,
     196    MC_QUEUE_POSITION,
    196197    MC_TRACKERS,
    197198
  • trunk/gtk/tr-prefs.c

    r12578 r12607  
    254254
    255255/****
     256*****  Download Tab
     257****/
     258
     259static GtkWidget*
     260downloadPage( GObject * core )
     261{
     262    GtkWidget * t;
     263    GtkWidget * w;
     264    GtkWidget * l;
     265    const char * s;
     266    int row = 0;
     267
     268    t = hig_workarea_create( );
     269
     270    hig_workarea_add_section_title( t, &row, _( "Location" ) );
     271
     272    w = new_path_chooser_button( TR_PREFS_KEY_DOWNLOAD_DIR, core );
     273    hig_workarea_add_row( t, &row, _( "Save to _Location:" ), w, NULL );
     274
     275    hig_workarea_add_section_divider( t, &row );
     276    hig_workarea_add_section_title( t, &row, _( "Queue" ) );
     277
     278    s = _( "Maximum active _downloads:" );
     279    w = new_spin_button( TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, core, 0, INT_MAX, 1 );
     280    hig_workarea_add_row( t, &row, s, w, NULL );
     281
     282    s = _( "E_xempt torrents if idle for N minutes:" );
     283    w = new_spin_button( TR_PREFS_KEY_QUEUE_STALLED_MINUTES, core, 1, INT_MAX, 1 );
     284    hig_workarea_add_row( t, &row, s, w, NULL );
     285
     286    hig_workarea_add_section_divider( t, &row );
     287    hig_workarea_add_section_title( t, &row, _( "Incomplete" ) );
     288
     289    s = _( "Append \"._part\" to incomplete files' names" );
     290    w = new_check_button( s, TR_PREFS_KEY_RENAME_PARTIAL_FILES, core );
     291    hig_workarea_add_wide_control( t, &row, w );
     292
     293    s = _( "Keep _incomplete torrents in:" );
     294    l = new_check_button( s, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, core );
     295    w = new_path_chooser_button( TR_PREFS_KEY_INCOMPLETE_DIR, core );
     296    gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED ) );
     297    g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
     298    hig_workarea_add_row_w( t, &row, l, w, NULL );
     299
     300    s = _( "Call _script when torrent is completed:" );
     301    l = new_check_button( s, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, core );
     302    w = new_file_chooser_button( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, core );
     303    gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED ) );
     304    g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
     305    hig_workarea_add_row_w( t, &row, l, w, NULL );
     306
     307    hig_workarea_finish( t, &row );
     308    return t;
     309}
     310
     311/****
    256312*****  Torrent Tab
    257313****/
     
    291347    hig_workarea_add_row_w( t, &row, l, w, NULL );
    292348#endif
    293 
    294     hig_workarea_add_section_divider( t, &row );
    295     hig_workarea_add_section_title( t, &row, _( "Downloading" ) );
    296 
    297     s = _( "Append \"._part\" to incomplete files' names" );
    298     w = new_check_button( s, TR_PREFS_KEY_RENAME_PARTIAL_FILES, core );
    299     hig_workarea_add_wide_control( t, &row, w );
    300 
    301     w = new_path_chooser_button( TR_PREFS_KEY_DOWNLOAD_DIR, core );
    302     hig_workarea_add_row( t, &row, _( "Save to _Location:" ), w, NULL );
    303 
    304     s = _( "Keep _incomplete torrents in:" );
    305     l = new_check_button( s, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, core );
    306     w = new_path_chooser_button( TR_PREFS_KEY_INCOMPLETE_DIR, core );
    307     gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED ) );
    308     g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
    309     hig_workarea_add_row_w( t, &row, l, w, NULL );
    310 
    311     s = _( "Call scrip_t when torrent is completed:" );
    312     l = new_check_button( s, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, core );
    313     w = new_file_chooser_button( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, core );
    314     gtk_widget_set_sensitive( GTK_WIDGET( w ), gtr_pref_flag_get( TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED ) );
    315     g_signal_connect( l, "toggled", G_CALLBACK( target_cb ), w );
    316     hig_workarea_add_row_w( t, &row, l, w, NULL );
    317349
    318350    hig_workarea_add_section_divider( t, &row );
     
    12531285                              gtk_label_new ( _( "Torrents" ) ) );
    12541286    gtk_notebook_append_page( GTK_NOTEBOOK( n ),
     1287                              downloadPage( core ),
     1288                              gtk_label_new ( _( "Downloading" ) ) );
     1289    gtk_notebook_append_page( GTK_NOTEBOOK( n ),
    12551290                              bandwidthPage( core ),
    12561291                              gtk_label_new ( _( "Speed" ) ) );
  • trunk/gtk/tr-window.c

    r12592 r12607  
    597597    /* main menu */
    598598    mainmenu = gtr_action_get_widget( "/main-window-menu" );
    599     w = gtr_action_get_widget( "/main-window-menu/torrent-menu/update-tracker" );
     599    w = gtr_action_get_widget( "/main-window-menu/torrent-menu/torrent-reannounce" );
    600600#if GTK_CHECK_VERSION( 2, 12, 0 )
    601601    g_signal_connect( w, "query-tooltip",
  • trunk/gtk/ui.h

    r11720 r12607  
    2222    "      <menuitem action='open-torrent-folder'/>\n"
    2323    "      <separator/>\n"
    24     "      <menuitem action='start-torrent'/>\n"
    25     "      <menuitem action='update-tracker'/>\n"
    26     "      <menuitem action='pause-torrent'/>\n"
    27     "      <menuitem action='copy-magnet-link-to-clipboard'/>\n"
     24    "      <menuitem action='torrent-start'/>\n"
     25    "      <menuitem action='torrent-start-now'/>\n"
     26    "      <menuitem action='torrent-reannounce'/>\n"
     27    "      <menu action='queue-menu'>\n"
     28    "        <menuitem action='queue-move-top'/>\n"
     29    "        <menuitem action='queue-move-up'/>\n"
     30    "        <menuitem action='queue-move-down'/>\n"
     31    "        <menuitem action='queue-move-bottom'/>\n"
     32    "      </menu>\n"
     33    "      <menuitem action='torrent-stop'/>\n"
    2834    "      <separator/>\n"
    2935    "      <menuitem action='relocate-torrent'/>\n"
    30     "      <menuitem action='verify-torrent'/>\n"
     36    "      <menuitem action='torrent-verify'/>\n"
     37    "      <menuitem action='copy-magnet-link-to-clipboard'/>\n"
    3138    "      <separator/>\n"
    3239    "      <menuitem action='remove-torrent'/>\n"
     
    6471    "  <toolbar name='main-window-toolbar'>\n"
    6572    "    <toolitem action='open-torrent-toolbar'/>\n"
    66     "    <toolitem action='start-torrent'/>\n"
    67     "    <toolitem action='pause-torrent'/>\n"
     73    "    <toolitem action='torrent-start'/>\n"
     74    "    <toolitem action='torrent-stop'/>\n"
    6875    "    <toolitem action='remove-torrent'/>\n"
    6976    "    <separator/>\n"
     
    8895    "    </menu>\n"
    8996    "    <separator/>\n"
    90     "    <menuitem action='start-torrent'/>\n"
    91     "    <menuitem action='update-tracker'/>\n"
    92     "    <menuitem action='pause-torrent'/>\n"
     97    "    <menuitem action='torrent-start'/>\n"
     98    "    <menuitem action='torrent-start-now'/>\n"
     99    "    <menuitem action='torrent-reannounce'/>\n"
     100    "    <menu action='queue-menu'>\n"
     101    "      <menuitem action='queue-move-top'/>\n"
     102    "      <menuitem action='queue-move-up'/>\n"
     103    "      <menuitem action='queue-move-down'/>\n"
     104    "      <menuitem action='queue-move-bottom'/>\n"
     105    "    </menu>\n"
     106    "    <menuitem action='torrent-stop'/>\n"
     107    "    <separator/>\n"
     108    "    <menuitem action='relocate-torrent'/>\n"
     109    "    <menuitem action='torrent-verify'/>\n"
    93110    "    <menuitem action='copy-magnet-link-to-clipboard'/>\n"
    94     "    <separator/>\n"
    95     "    <menuitem action='verify-torrent'/>\n"
    96     "    <menuitem action='relocate-torrent'/>\n"
    97111    "    <separator/>\n"
    98112    "    <menuitem action='remove-torrent'/>\n"
  • trunk/libtransmission/peer-mgr.c

    r12539 r12607  
    531531}
    532532
     533static void ensureMgrTimersExist( struct tr_peerMgr * m );
     534
    533535tr_peerMgr*
    534536tr_peerMgrNew( tr_session * session )
     
    537539    m->session = session;
    538540    m->incomingHandshakes = TR_PTR_ARRAY_INIT;
     541    ensureMgrTimersExist( m );
    539542    return m;
    540543}
     
    35593562
    35603563static void
     3564queuePulse( tr_session * session, tr_direction dir )
     3565{
     3566    assert( tr_isSession( session ) );
     3567    assert( tr_isDirection( dir ) );
     3568
     3569    if( tr_sessionGetQueueEnabled( session, dir ) )
     3570    {
     3571        int i;
     3572        const int n = tr_sessionCountQueueFreeSlots( session, dir );
     3573        for( i=0; i<n; i++ ) {
     3574            tr_torrent * tor = tr_sessionGetNextQueuedTorrent( session, dir );
     3575            if( tor != NULL )
     3576                tr_torrentStartNow( tor );
     3577        }
     3578    }
     3579}
     3580
     3581static void
    35613582bandwidthPulse( int foo UNUSED, short bar UNUSED, void * vmgr )
    35623583{
    35633584    tr_torrent * tor;
    35643585    tr_peerMgr * mgr = vmgr;
     3586    tr_session * session = mgr->session;
    35653587    managerLock( mgr );
    35663588
     
    35693591
    35703592    /* allocate bandwidth to the peers */
    3571     tr_bandwidthAllocate( &mgr->session->bandwidth, TR_UP, BANDWIDTH_PERIOD_MSEC );
    3572     tr_bandwidthAllocate( &mgr->session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC );
     3593    tr_bandwidthAllocate( &session->bandwidth, TR_UP, BANDWIDTH_PERIOD_MSEC );
     3594    tr_bandwidthAllocate( &session->bandwidth, TR_DOWN, BANDWIDTH_PERIOD_MSEC );
    35733595
    35743596    /* torrent upkeep */
    35753597    tor = NULL;
    3576     while(( tor = tr_torrentNext( mgr->session, tor )))
     3598    while(( tor = tr_torrentNext( session, tor )))
    35773599    {
    35783600        /* possibly stop torrents that have seeded enough */
     
    35903612            tr_torrentStop( tor );
    35913613    }
     3614
     3615    /* pump the queues */
     3616    queuePulse( session, TR_UP );
     3617    queuePulse( session, TR_DOWN );
    35923618
    35933619    reconnectPulse( 0, 0, mgr );
  • trunk/libtransmission/rpcimpl.c

    r12521 r12607  
    187187}
    188188
     189static void
     190notifyBatchChange( tr_session * session, tr_torrent ** torrents, int n )
     191{
     192    int i;
     193    for( i=0; i<n; ++i )
     194        notify( session, TR_RPC_TORRENT_CHANGED, torrents[i] );
     195}
     196
     197static const char*
     198queueMoveTop( tr_session               * session,
     199              tr_benc                  * args_in,
     200              tr_benc                  * args_out UNUSED,
     201              struct tr_rpc_idle_data  * idle_data UNUSED )
     202{
     203    int n;
     204    tr_torrent ** torrents = getTorrents( session, args_in, &n );
     205    tr_torrentsQueueMoveTop( torrents, n );
     206    notifyBatchChange( session, torrents, n );
     207    tr_free( torrents );
     208    return NULL;
     209}
     210
     211static const char*
     212queueMoveUp( tr_session               * session,
     213             tr_benc                  * args_in,
     214             tr_benc                  * args_out UNUSED,
     215             struct tr_rpc_idle_data  * idle_data UNUSED )
     216{
     217    int n;
     218    tr_torrent ** torrents = getTorrents( session, args_in, &n );
     219    tr_torrentsQueueMoveUp( torrents, n );
     220    notifyBatchChange( session, torrents, n );
     221    tr_free( torrents );
     222    return NULL;
     223}
     224
     225static const char*
     226queueMoveDown( tr_session               * session,
     227               tr_benc                  * args_in,
     228               tr_benc                  * args_out UNUSED,
     229               struct tr_rpc_idle_data  * idle_data UNUSED )
     230{
     231    int n;
     232    tr_torrent ** torrents = getTorrents( session, args_in, &n );
     233    tr_torrentsQueueMoveDown( torrents, n );
     234    notifyBatchChange( session, torrents, n );
     235    tr_free( torrents );
     236    return NULL;
     237}
     238
     239static const char*
     240queueMoveBottom( tr_session               * session,
     241                 tr_benc                  * args_in,
     242                 tr_benc                  * args_out UNUSED,
     243                 struct tr_rpc_idle_data  * idle_data UNUSED )
     244{
     245    int n;
     246    tr_torrent ** torrents = getTorrents( session, args_in, &n );
     247    tr_torrentsQueueMoveBottom( torrents, n );
     248    notifyBatchChange( session, torrents, n );
     249    tr_free( torrents );
     250    return NULL;
     251}
     252
    189253static const char*
    190254torrentStart( tr_session               * session,
     
    212276
    213277static const char*
     278torrentStartNow( tr_session               * session,
     279                 tr_benc                  * args_in,
     280                 tr_benc                  * args_out UNUSED,
     281                 struct tr_rpc_idle_data  * idle_data UNUSED )
     282{
     283    int           i, torrentCount;
     284    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     285
     286    assert( idle_data == NULL );
     287
     288    for( i = 0; i < torrentCount; ++i )
     289    {
     290        tr_torrent * tor = torrents[i];
     291        if( !tor->isRunning )
     292        {
     293            tr_torrentStartNow( tor );
     294            notify( session, TR_RPC_TORRENT_STARTED, tor );
     295        }
     296    }
     297    tr_free( torrents );
     298    return NULL;
     299}
     300
     301static const char*
    214302torrentStop( tr_session               * session,
    215303             tr_benc                  * args_in,
     
    226314        tr_torrent * tor = torrents[i];
    227315
    228         if( tor->isRunning )
     316        if( tor->isRunning || ( tor->queuePosition >= 0 ) )
    229317        {
    230318            tor->isStopping = true;
     
    579667            tr_bencListAddInt( p, inf->files[i].priority );
    580668    }
     669    else if( tr_streq( key, keylen, "queuePosition" ) )
     670        tr_bencDictAddInt( d, key, st->queuePosition );
    581671    else if( tr_streq( key, keylen, "rateDownload" ) )
    582672        tr_bencDictAddInt( d, key, toSpeedBytes( st->pieceDownloadSpeed_KBps ) );
     
    10181108        if( tr_bencDictFindInt( args_in, "seedRatioMode", &tmp ) )
    10191109            tr_torrentSetRatioMode( tor, tmp );
     1110        if( tr_bencDictFindInt( args_in, "queuePosition", &tmp ) )
     1111            tr_torrentSetQueuePosition( tor, tmp );
    10201112        if( !errmsg && tr_bencDictFindList( args_in, "trackerAdd", &trackers ) )
    10211113            errmsg = addTrackerUrls( tor, trackers );
     
    14661558    if( tr_bencDictFindStr( args_in, TR_PREFS_KEY_DOWNLOAD_DIR, &str ) )
    14671559        tr_sessionSetDownloadDir( session, str );
     1560    if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, &boolVal ) )
     1561        tr_sessionSetQueueEnabled ( session, TR_DOWN, boolVal );
     1562    if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, &i ) )
     1563        tr_sessionSetQueueSize( session, TR_DOWN, i );
    14681564    if( tr_bencDictFindStr( args_in, TR_PREFS_KEY_INCOMPLETE_DIR, &str ) )
    14691565        tr_sessionSetIncompleteDir( session, str );
     
    15001596    if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_START, &boolVal ) )
    15011597        tr_sessionSetPaused( session, !boolVal );
     1598    if( tr_bencDictFindBool( args_in, TR_PREFS_KEY_SEED_QUEUE_ENABLED, &boolVal ) )
     1599        tr_sessionSetQueueEnabled ( session, TR_UP, boolVal );
     1600    if( tr_bencDictFindInt( args_in, TR_PREFS_KEY_SEED_QUEUE_SIZE, &i ) )
     1601        tr_sessionSetQueueSize( session, TR_UP, i );
    15021602    if( tr_bencDictFindStr( args_in, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, &str ) )
    15031603        tr_sessionSetTorrentDoneScript( session, str );
     
    15981698    tr_bencDictAddStr ( d, "config-dir", tr_sessionGetConfigDir( s ) );
    15991699    tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR, tr_sessionGetDownloadDir( s ) );
     1700    tr_bencDictAddBool( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, tr_sessionGetQueueEnabled( s, TR_DOWN ) );
     1701    tr_bencDictAddInt ( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, tr_sessionGetQueueSize( s, TR_DOWN ) );
    16001702    tr_bencDictAddInt ( d, "download-dir-free-space",  tr_sessionGetDownloadDirFreeSpace( s ) );
    16011703    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, tr_sessionGetPeerLimit( s ) );
     
    16171719    tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT, tr_sessionGetIdleLimit( s ) );
    16181720    tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED, tr_sessionIsIdleLimited( s ) );
     1721    tr_bencDictAddBool( d, TR_PREFS_KEY_SEED_QUEUE_ENABLED, tr_sessionGetQueueEnabled( s, TR_UP ) );
     1722    tr_bencDictAddInt ( d, TR_PREFS_KEY_SEED_QUEUE_SIZE, tr_sessionGetQueueSize( s, TR_UP ) );
    16191723    tr_bencDictAddBool( d, TR_PREFS_KEY_START, !tr_sessionGetPaused( s ) );
    16201724    tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL, tr_sessionGetDeleteSource( s ) );
     
    16771781    { "torrent-set-location",  true,  torrentSetLocation  },
    16781782    { "torrent-start",         true,  torrentStart        },
     1783    { "torrent-start-now",     true,  torrentStartNow     },
    16791784    { "torrent-stop",          true,  torrentStop         },
    16801785    { "torrent-verify",        true,  torrentVerify       },
    1681     { "torrent-reannounce",    true,  torrentReannounce   }
     1786    { "torrent-reannounce",    true,  torrentReannounce   },
     1787    { "queue-move-top",        true,  queueMoveTop        },
     1788    { "queue-move-up",         true,  queueMoveUp         },
     1789    { "queue-move-down",       true,  queueMoveDown       },
     1790    { "queue-move-bottom",     true,  queueMoveBottom     }
    16821791};
    16831792
  • trunk/libtransmission/session.c

    r12577 r12607  
    305305
    306306    tr_bencDictReserve( d, 60 );
    307     tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED,        false );
    308     tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL,            "http://www.example.com/blocklist" );
    309     tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB,        DEFAULT_CACHE_SIZE_MB );
    310     tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED,              true );
    311     tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED,              true );
    312     tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED,              false );
    313     tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR,             tr_getDefaultDownloadDir( ) );
    314     tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps,              100 );
    315     tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED,           false );
    316     tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION,               TR_DEFAULT_ENCRYPTION );
    317     tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT,               30 );
    318     tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED,       false );
    319     tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR,           tr_getDefaultDownloadDir( ) );
    320     tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED,   false );
    321     tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL,                 TR_MSG_INF );
    322     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL,        atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ) );
    323     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT,       atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR ) );
    324     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT,                atoi( TR_DEFAULT_PEER_PORT_STR ) );
    325     tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, false );
    326     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW,     49152 );
    327     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH,    65535 );
    328     tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS,          TR_DEFAULT_PEER_SOCKET_TOS_STR );
    329     tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED,              true );
    330     tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING,          true );
    331     tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION,            TR_PREALLOCATE_SPARSE );
    332     tr_bencDictAddBool( d, TR_PREFS_KEY_PREFETCH_ENABLED,         DEFAULT_PREFETCH_ENABLED );
    333     tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO,                    2.0 );
    334     tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED,            false );
    335     tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES,     true );
    336     tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,        false );
    337     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS,         "0.0.0.0" );
    338     tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED,              false );
    339     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD,             "" );
    340     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME,             "" );
    341     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST,            TR_DEFAULT_RPC_WHITELIST );
    342     tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED,    true );
    343     tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT,                 atoi( TR_DEFAULT_RPC_PORT_STR ) );
    344     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL,                  TR_DEFAULT_RPC_URL_STR );
    345     tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS,   true );
    346     tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, "" );
    347     tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, false );
    348     tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED,        false );
    349     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps,        50 ); /* half the regular */
    350     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps,      50 ); /* half the regular */
    351     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN,     540 ); /* 9am */
    352     tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED,   false );
    353     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END,       1020 ); /* 5pm */
    354     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY,       TR_SCHED_ALL );
    355     tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps,              100 );
    356     tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED,           false );
    357     tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK,                    022 );
    358     tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, 14 );
    359     tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4,        TR_DEFAULT_BIND_ADDRESS_IPV4 );
    360     tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6,        TR_DEFAULT_BIND_ADDRESS_IPV6 );
    361     tr_bencDictAddBool( d, TR_PREFS_KEY_START,                    true );
    362     tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL,           false );
     307    tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED,               false );
     308    tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL,                   "http://www.example.com/blocklist" );
     309    tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB,               DEFAULT_CACHE_SIZE_MB );
     310    tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED,                     true );
     311    tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED,                     true );
     312    tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED,                     false );
     313    tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR,                    tr_getDefaultDownloadDir( ) );
     314    tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps,                     100 );
     315    tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED,                  false );
     316    tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION,                      TR_DEFAULT_ENCRYPTION );
     317    tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT,                      30 );
     318    tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED,              false );
     319    tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR,                  tr_getDefaultDownloadDir( ) );
     320    tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED,          false );
     321    tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL,                        TR_MSG_INF );
     322    tr_bencDictAddInt ( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE,             10 );
     323    tr_bencDictAddBool( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED,          true );
     324    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL,               atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ) );
     325    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT,              atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR ) );
     326    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT,                       atoi( TR_DEFAULT_PEER_PORT_STR ) );
     327    tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START,       false );
     328    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW,            49152 );
     329    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH,           65535 );
     330    tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS,                 TR_DEFAULT_PEER_SOCKET_TOS_STR );
     331    tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED,                     true );
     332    tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING,                 true );
     333    tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION,                   TR_PREALLOCATE_SPARSE );
     334    tr_bencDictAddBool( d, TR_PREFS_KEY_PREFETCH_ENABLED,                DEFAULT_PREFETCH_ENABLED );
     335    tr_bencDictAddInt ( d, TR_PREFS_KEY_QUEUE_STALLED_MINUTES,           30 );
     336    tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO,                           2.0 );
     337    tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED,                   false );
     338    tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES,            true );
     339    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,               false );
     340    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS,                "0.0.0.0" );
     341    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED,                     false );
     342    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD,                    "" );
     343    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME,                    "" );
     344    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST,                   TR_DEFAULT_RPC_WHITELIST );
     345    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED,           true );
     346    tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT,                        atoi( TR_DEFAULT_RPC_PORT_STR ) );
     347    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL,                         TR_DEFAULT_RPC_URL_STR );
     348    tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS,          true );
     349    tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME,    "" );
     350    tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED,     false );
     351    tr_bencDictAddInt ( d, TR_PREFS_KEY_SEED_QUEUE_SIZE,                 10 );
     352    tr_bencDictAddBool( d, TR_PREFS_KEY_SEED_QUEUE_ENABLED,              false );
     353    tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED,               false );
     354    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps,               50 ); /* half the regular */
     355    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps,             50 ); /* half the regular */
     356    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN,            540 ); /* 9am */
     357    tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED,          false );
     358    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END,              1020 ); /* 5pm */
     359    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY,              TR_SCHED_ALL );
     360    tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps,                     100 );
     361    tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED,                  false );
     362    tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK,                           022 );
     363    tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT,        14 );
     364    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4,               TR_DEFAULT_BIND_ADDRESS_IPV4 );
     365    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6,               TR_DEFAULT_BIND_ADDRESS_IPV6 );
     366    tr_bencDictAddBool( d, TR_PREFS_KEY_START,                           true );
     367    tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL,                  false );
    363368}
    364369
     
    369374
    370375    tr_bencDictReserve( d, 60 );
    371     tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED,        tr_blocklistIsEnabled( s ) );
    372     tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL,            tr_blocklistGetURL( s ) );
    373     tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB,        tr_sessionGetCacheLimit_MB( s ) );
    374     tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED,              s->isDHTEnabled );
    375     tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED,              s->isUTPEnabled );
    376     tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED,              s->isLPDEnabled );
    377     tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR,             s->downloadDir );
    378     tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps,              tr_sessionGetSpeedLimit_KBps( s, TR_DOWN ) );
    379     tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED,           tr_sessionIsSpeedLimited( s, TR_DOWN ) );
    380     tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION,               s->encryptionMode );
    381     tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT,               tr_sessionGetIdleLimit( s ) );
    382     tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED,       tr_sessionIsIdleLimited( s ) );
    383     tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR,           tr_sessionGetIncompleteDir( s ) );
    384     tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED,   tr_sessionIsIncompleteDirEnabled( s ) );
    385     tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL,                 tr_getMessageLevel( ) );
    386     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL,        s->peerLimit );
    387     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT,       s->peerLimitPerTorrent );
    388     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT,                tr_sessionGetPeerPort( s ) );
    389     tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, s->isPortRandom );
    390     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW,     s->randomPortLow );
    391     tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH,    s->randomPortHigh );
    392     tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS,          format_tos(s->peerSocketTOS) );
    393     tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM, s->peer_congestion_algorithm );
    394     tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED,              s->isPexEnabled );
    395     tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING,          tr_sessionIsPortForwardingEnabled( s ) );
    396     tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION,            s->preallocationMode );
    397     tr_bencDictAddInt ( d, TR_PREFS_KEY_PREFETCH_ENABLED,         s->isPrefetchEnabled );
    398     tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO,                    s->desiredRatio );
    399     tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED,            s->isRatioLimited );
    400     tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES,     tr_sessionIsIncompleteFileNamingEnabled( s ) );
    401     tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,        tr_sessionIsRPCPasswordEnabled( s ) );
    402     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS,         tr_sessionGetRPCBindAddress( s ) );
    403     tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED,              tr_sessionIsRPCEnabled( s ) );
    404     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD,             tr_sessionGetRPCPassword( s ) );
    405     tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT,                 tr_sessionGetRPCPort( s ) );
    406     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL,                  tr_sessionGetRPCUrl( s ) );
    407     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME,             tr_sessionGetRPCUsername( s ) );
    408     tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST,            tr_sessionGetRPCWhitelist( s ) );
    409     tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED,    tr_sessionGetRPCWhitelistEnabled( s ) );
    410     tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS,   s->scrapePausedTorrents );
    411     tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, tr_sessionIsTorrentDoneScriptEnabled( s ) );
    412     tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, tr_sessionGetTorrentDoneScript( s ) );
    413     tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED,        tr_sessionUsesAltSpeed( s ) );
    414     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps,        tr_sessionGetAltSpeed_KBps( s, TR_UP ) );
    415     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps,      tr_sessionGetAltSpeed_KBps( s, TR_DOWN ) );
    416     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN,     tr_sessionGetAltSpeedBegin( s ) );
    417     tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED,   tr_sessionUsesAltSpeedTime( s ) );
    418     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END,       tr_sessionGetAltSpeedEnd( s ) );
    419     tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY,       tr_sessionGetAltSpeedDay( s ) );
    420     tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps,              tr_sessionGetSpeedLimit_KBps( s, TR_UP ) );
    421     tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED,           tr_sessionIsSpeedLimited( s, TR_UP ) );
    422     tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK,                    s->umask );
    423     tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT, s->uploadSlotsPerTorrent );
    424     tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4,        tr_address_to_string( &s->public_ipv4->addr ) );
    425     tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6,        tr_address_to_string( &s->public_ipv6->addr ) );
    426     tr_bencDictAddBool( d, TR_PREFS_KEY_START,                    !tr_sessionGetPaused( s ) );
    427     tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL,           tr_sessionGetDeleteSource( s ) );
     376    tr_bencDictAddBool( d, TR_PREFS_KEY_BLOCKLIST_ENABLED,                tr_blocklistIsEnabled( s ) );
     377    tr_bencDictAddStr ( d, TR_PREFS_KEY_BLOCKLIST_URL,                    tr_blocklistGetURL( s ) );
     378    tr_bencDictAddInt ( d, TR_PREFS_KEY_MAX_CACHE_SIZE_MB,                tr_sessionGetCacheLimit_MB( s ) );
     379    tr_bencDictAddBool( d, TR_PREFS_KEY_DHT_ENABLED,                      s->isDHTEnabled );
     380    tr_bencDictAddBool( d, TR_PREFS_KEY_UTP_ENABLED,                      s->isUTPEnabled );
     381    tr_bencDictAddBool( d, TR_PREFS_KEY_LPD_ENABLED,                      s->isLPDEnabled );
     382    tr_bencDictAddStr ( d, TR_PREFS_KEY_DOWNLOAD_DIR,                     s->downloadDir );
     383    tr_bencDictAddInt ( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE,              tr_sessionGetQueueSize( s, TR_DOWN ) );
     384    tr_bencDictAddBool( d, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED,           tr_sessionGetQueueEnabled( s, TR_DOWN ) );
     385    tr_bencDictAddInt ( d, TR_PREFS_KEY_DSPEED_KBps,                      tr_sessionGetSpeedLimit_KBps( s, TR_DOWN ) );
     386    tr_bencDictAddBool( d, TR_PREFS_KEY_DSPEED_ENABLED,                   tr_sessionIsSpeedLimited( s, TR_DOWN ) );
     387    tr_bencDictAddInt ( d, TR_PREFS_KEY_ENCRYPTION,                       s->encryptionMode );
     388    tr_bencDictAddInt ( d, TR_PREFS_KEY_IDLE_LIMIT,                       tr_sessionGetIdleLimit( s ) );
     389    tr_bencDictAddBool( d, TR_PREFS_KEY_IDLE_LIMIT_ENABLED,               tr_sessionIsIdleLimited( s ) );
     390    tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR,                   tr_sessionGetIncompleteDir( s ) );
     391    tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED,           tr_sessionIsIncompleteDirEnabled( s ) );
     392    tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL,                         tr_getMessageLevel( ) );
     393    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL,                s->peerLimit );
     394    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT,               s->peerLimitPerTorrent );
     395    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT,                        tr_sessionGetPeerPort( s ) );
     396    tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START,        s->isPortRandom );
     397    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW,             s->randomPortLow );
     398    tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH,            s->randomPortHigh );
     399    tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_SOCKET_TOS,                  format_tos(s->peerSocketTOS) );
     400    tr_bencDictAddStr ( d, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM,        s->peer_congestion_algorithm );
     401    tr_bencDictAddBool( d, TR_PREFS_KEY_PEX_ENABLED,                      s->isPexEnabled );
     402    tr_bencDictAddBool( d, TR_PREFS_KEY_PORT_FORWARDING,                  tr_sessionIsPortForwardingEnabled( s ) );
     403    tr_bencDictAddInt ( d, TR_PREFS_KEY_PREALLOCATION,                    s->preallocationMode );
     404    tr_bencDictAddInt ( d, TR_PREFS_KEY_PREFETCH_ENABLED,                 s->isPrefetchEnabled );
     405    tr_bencDictAddInt ( d, TR_PREFS_KEY_QUEUE_STALLED_MINUTES,            tr_sessionGetQueueStalledMinutes( s ) );
     406    tr_bencDictAddReal( d, TR_PREFS_KEY_RATIO,                            s->desiredRatio );
     407    tr_bencDictAddBool( d, TR_PREFS_KEY_RATIO_ENABLED,                    s->isRatioLimited );
     408    tr_bencDictAddBool( d, TR_PREFS_KEY_RENAME_PARTIAL_FILES,             tr_sessionIsIncompleteFileNamingEnabled( s ) );
     409    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,                tr_sessionIsRPCPasswordEnabled( s ) );
     410    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_BIND_ADDRESS,                 tr_sessionGetRPCBindAddress( s ) );
     411    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_ENABLED,                      tr_sessionIsRPCEnabled( s ) );
     412    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_PASSWORD,                     tr_sessionGetRPCPassword( s ) );
     413    tr_bencDictAddInt ( d, TR_PREFS_KEY_RPC_PORT,                         tr_sessionGetRPCPort( s ) );
     414    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_URL,                          tr_sessionGetRPCUrl( s ) );
     415    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_USERNAME,                     tr_sessionGetRPCUsername( s ) );
     416    tr_bencDictAddStr ( d, TR_PREFS_KEY_RPC_WHITELIST,                    tr_sessionGetRPCWhitelist( s ) );
     417    tr_bencDictAddBool( d, TR_PREFS_KEY_RPC_WHITELIST_ENABLED,            tr_sessionGetRPCWhitelistEnabled( s ) );
     418    tr_bencDictAddBool( d, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS,           s->scrapePausedTorrents );
     419    tr_bencDictAddBool( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED,      tr_sessionIsTorrentDoneScriptEnabled( s ) );
     420    tr_bencDictAddStr ( d, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME,     tr_sessionGetTorrentDoneScript( s ) );
     421    tr_bencDictAddInt ( d, TR_PREFS_KEY_SEED_QUEUE_SIZE,                  tr_sessionGetQueueSize( s, TR_UP ) );
     422    tr_bencDictAddBool( d, TR_PREFS_KEY_SEED_QUEUE_ENABLED,               tr_sessionGetQueueEnabled( s, TR_UP ) );
     423    tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_ENABLED,                tr_sessionUsesAltSpeed( s ) );
     424    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_UP_KBps,                tr_sessionGetAltSpeed_KBps( s, TR_UP ) );
     425    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps,              tr_sessionGetAltSpeed_KBps( s, TR_DOWN ) );
     426    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN,             tr_sessionGetAltSpeedBegin( s ) );
     427    tr_bencDictAddBool( d, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED,           tr_sessionUsesAltSpeedTime( s ) );
     428    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_END,               tr_sessionGetAltSpeedEnd( s ) );
     429    tr_bencDictAddInt ( d, TR_PREFS_KEY_ALT_SPEED_TIME_DAY,               tr_sessionGetAltSpeedDay( s ) );
     430    tr_bencDictAddInt ( d, TR_PREFS_KEY_USPEED_KBps,                      tr_sessionGetSpeedLimit_KBps( s, TR_UP ) );
     431    tr_bencDictAddBool( d, TR_PREFS_KEY_USPEED_ENABLED,                   tr_sessionIsSpeedLimited( s, TR_UP ) );
     432    tr_bencDictAddInt ( d, TR_PREFS_KEY_UMASK,                            s->umask );
     433    tr_bencDictAddInt ( d, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT,         s->uploadSlotsPerTorrent );
     434    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV4,                tr_address_to_string( &s->public_ipv4->addr ) );
     435    tr_bencDictAddStr ( d, TR_PREFS_KEY_BIND_ADDRESS_IPV6,                tr_address_to_string( &s->public_ipv6->addr ) );
     436    tr_bencDictAddBool( d, TR_PREFS_KEY_START,                            !tr_sessionGetPaused( s ) );
     437    tr_bencDictAddBool( d, TR_PREFS_KEY_TRASH_ORIGINAL,                   tr_sessionGetDeleteSource( s ) );
    428438}
    429439
     
    780790        tr_sessionSetDeleteSource( session, boolVal );
    781791
     792    /* torrent queues */
     793    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_QUEUE_STALLED_MINUTES, &i ) )
     794        tr_sessionSetQueueStalledMinutes( session, i );
     795    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, &i ) )
     796        tr_sessionSetQueueSize( session, TR_DOWN, i );
     797    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, &boolVal ) )
     798        tr_sessionSetQueueEnabled( session, TR_DOWN, boolVal );
     799    if( tr_bencDictFindInt( settings, TR_PREFS_KEY_SEED_QUEUE_SIZE, &i ) )
     800        tr_sessionSetQueueSize( session, TR_UP, i );
     801    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_SEED_QUEUE_ENABLED, &boolVal ) )
     802        tr_sessionSetQueueEnabled( session, TR_UP, boolVal );
     803
    782804    /* files and directories */
    783805    if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PREFETCH_ENABLED, &boolVal ) )
     
    26012623    }
    26022624}
     2625
     2626/***
     2627****
     2628***/
     2629
     2630void
     2631tr_sessionSetQueueSize( tr_session * session, tr_direction dir, int n )
     2632{
     2633    assert( tr_isSession( session ) );
     2634    assert( tr_isDirection( dir ) );
     2635
     2636    session->queueSize[dir] = n;
     2637}
     2638
     2639int
     2640tr_sessionGetQueueSize( const tr_session * session, tr_direction dir )
     2641{
     2642    assert( tr_isSession( session ) );
     2643    assert( tr_isDirection( dir ) );
     2644
     2645    return session->queueSize[dir];
     2646}
     2647
     2648void
     2649tr_sessionSetQueueEnabled( tr_session * session, tr_direction dir, bool is_enabled )
     2650{
     2651    assert( tr_isSession( session ) );
     2652    assert( tr_isDirection( dir ) );
     2653    assert( tr_isBool( is_enabled ) );
     2654
     2655    session->queueEnabled[dir] = is_enabled;
     2656}
     2657
     2658bool
     2659tr_sessionGetQueueEnabled( const tr_session * session, tr_direction dir )
     2660{
     2661    assert( tr_isSession( session ) );
     2662    assert( tr_isDirection( dir ) );
     2663
     2664    return session->queueEnabled[dir];
     2665}
     2666
     2667void
     2668tr_sessionSetQueueStalledMinutes( tr_session * session, int minutes )
     2669{
     2670    assert( tr_isSession( session ) );
     2671    assert( minutes > 0 );
     2672
     2673    session->queueStalledMinutes = minutes;
     2674   
     2675}
     2676
     2677int
     2678tr_sessionGetQueueStalledMinutes( const tr_session * session )
     2679{
     2680    assert( tr_isSession( session ) );
     2681
     2682    return session->queueStalledMinutes;
     2683}
     2684
     2685tr_torrent *
     2686tr_sessionGetNextQueuedTorrent( tr_session * session, tr_direction direction )
     2687{
     2688    tr_torrent * tor = NULL;
     2689    tr_torrent * best_tor = NULL;
     2690    int best_position = INT_MAX;
     2691
     2692    assert( tr_isSession( session ) );
     2693    assert( tr_isDirection( direction ) );
     2694
     2695    while(( tor = tr_torrentNext( session, tor ))) {
     2696        if( !tor->isRunning && ( direction == tr_torrentGetQueueDirection( tor ) ) ) {
     2697            const int position = tr_torrentGetQueuePosition( tor );
     2698            if( ( position >= 0 ) && ( best_position > position ) ) {
     2699                best_position = position;
     2700                best_tor = tor;
     2701            }
     2702        }
     2703    }
     2704
     2705    return best_tor;
     2706}
     2707
     2708int
     2709tr_sessionCountQueueFreeSlots( tr_session * session, tr_direction dir )
     2710{
     2711    tr_torrent * tor;
     2712    int active_count;
     2713    const int max = tr_sessionGetQueueSize( session, dir );
     2714    const tr_torrent_activity activity = TR_UP ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
     2715
     2716    if( !tr_sessionGetQueueEnabled( session, dir ) )
     2717        return INT_MAX;
     2718
     2719    tor = NULL;
     2720    active_count = 0;
     2721    while(( tor = tr_torrentNext( session, tor )))
     2722        if( !tr_torrentIsStalled( tor ) )
     2723            if( tr_torrentGetActivity( tor ) == activity )
     2724                ++active_count;
     2725
     2726    if( active_count >= max )
     2727        return 0;
     2728
     2729    return max - active_count;
     2730}
  • trunk/libtransmission/session.h

    r12577 r12607  
    112112    tr_benc                      removedTorrents;
    113113
     114    bool                         queueEnabled[2];
     115    int                          queueSize[2];
     116    int                          queueStalledMinutes;
     117
    114118    int                          umask;
    115119
     
    309313                                         int               * setme );
    310314
     315tr_torrent * tr_sessionGetNextQueuedSeed( tr_session * session );
     316tr_torrent * tr_sessionGetNextQueuedTorrent( tr_session * session, tr_direction );
     317
     318int tr_sessionCountQueueFreeSlots( tr_session * session, tr_direction );
     319
     320
    311321#endif
  • trunk/libtransmission/torrent.c

    r12600 r12607  
    670670}
    671671
    672 static void torrentStart( tr_torrent * tor );
     672static void torrentStart( tr_torrent * tor, bool bypass_queue );
    673673
    674674/**
     
    803803    tor->uniqueId = nextUniqueId++;
    804804    tor->magicNumber = TORRENT_MAGIC_NUMBER;
     805    tor->queuePosition = -1;
    805806
    806807    tr_peerIdInit( tor->peer_id );
     
    906907    else if( doStart )
    907908    {
    908         torrentStart( tor );
     909        tr_torrentStart( tor );
    909910    }
    910911
     
    10901091}
    10911092
     1093static tr_torrent_activity
     1094torrentGetActivity( const tr_torrent * tor )
     1095{
     1096    const bool is_seed = tr_torrentIsSeed( tor );
     1097    assert( tr_isTorrent( tor ) );
     1098
     1099    if( tor->verifyState == TR_VERIFY_NOW )
     1100        return TR_STATUS_CHECK;
     1101
     1102    if( tor->verifyState == TR_VERIFY_WAIT )
     1103        return TR_STATUS_CHECK_WAIT;
     1104
     1105    if( tor->isRunning )
     1106        return is_seed ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
     1107
     1108    if( tor->queuePosition >= 0 ) {
     1109        if( is_seed && tr_sessionGetQueueEnabled( tor->session, TR_UP ) )
     1110            return TR_STATUS_SEED_WAIT;
     1111        if( !is_seed && tr_sessionGetQueueEnabled( tor->session, TR_DOWN ) )
     1112            return TR_STATUS_DOWNLOAD_WAIT;
     1113    }
     1114
     1115    return TR_STATUS_STOPPED;
     1116}
     1117
    10921118tr_torrent_activity
    10931119tr_torrentGetActivity( tr_torrent * tor )
    10941120{
    1095     assert( tr_isTorrent( tor ) );
    1096 
     1121    /* FIXME: is this call still needed? */
    10971122    tr_torrentRecheckCompleteness( tor );
    10981123
    1099     if( tor->verifyState == TR_VERIFY_NOW )
    1100         return TR_STATUS_CHECK;
    1101     if( tor->verifyState == TR_VERIFY_WAIT )
    1102         return TR_STATUS_CHECK_WAIT;
    1103     if( !tor->isRunning )
    1104         return TR_STATUS_STOPPED;
    1105     if( tor->completeness == TR_LEECH )
    1106         return TR_STATUS_DOWNLOAD;
    1107 
    1108     return TR_STATUS_SEED;
    1109 }
     1124    return torrentGetActivity( tor );
     1125}
     1126
     1127static time_t
     1128torrentGetIdleSecs( const tr_torrent * tor )
     1129{
     1130    int idle_secs;
     1131    const tr_torrent_activity activity = torrentGetActivity( tor );
     1132
     1133    if ((activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_SEED) && tor->startDate != 0)
     1134        idle_secs = difftime(tr_time(), MAX(tor->startDate, tor->activityDate));
     1135    else
     1136        idle_secs = -1;
     1137
     1138    return idle_secs;
     1139}
     1140
     1141bool
     1142tr_torrentIsStalled( const tr_torrent * tor )
     1143{
     1144    return torrentGetIdleSecs( tor ) > ( tr_sessionGetQueueStalledMinutes( tor->session ) * 60 );
     1145}
     1146
    11101147
    11111148static double
     
    11461183    s->activity = tr_torrentGetActivity( tor );
    11471184    s->error = tor->error;
     1185    s->queuePosition = tor->queuePosition;
    11481186    tr_strlcpy( s->errorString, tor->errorString, sizeof( s->errorString ) );
    11491187
     
    11761214    s->secondsSeeding      = tor->secondsSeeding;
    11771215    s->secondsDownloading  = tor->secondsDownloading;
    1178 
    1179     if ((s->activity == TR_STATUS_DOWNLOAD || s->activity == TR_STATUS_SEED) && s->startDate != 0)
    1180         s->idleSecs = difftime(tr_time(), MAX(s->startDate, s->activityDate));
    1181     else
    1182         s->idleSecs = -1;
     1216    s->idleSecs            = torrentGetIdleSecs( tor );
    11831217
    11841218    s->corruptEver      = tor->corruptCur    + tor->corruptPrev;
     
    15061540**/
    15071541
     1542static void queueRemove( tr_torrent * tor );
     1543
    15081544static void
    15091545torrentStartImpl( void * vtor )
     
    15171553
    15181554    tr_torrentRecheckCompleteness( tor );
     1555    queueRemove( tor );
    15191556
    15201557    now = tr_time( );
     
    15571594}
    15581595
     1596static bool
     1597torrentShouldQueue( const tr_torrent * tor )
     1598{
     1599    const tr_direction dir = tr_torrentGetQueueDirection( tor );
     1600
     1601    return tr_sessionCountQueueFreeSlots( tor->session, dir ) == 0;
     1602}
     1603
     1604static void queueAppend( tr_torrent * tor );
     1605
    15591606static void
    1560 torrentStart( tr_torrent * tor )
    1561 {
    1562     /* already running... */
    1563     if( tor->isRunning )
    1564         return;
     1607torrentStart( tr_torrent * tor, bool bypass_queue )
     1608{
     1609    switch( torrentGetActivity( tor ) )
     1610    {
     1611        case TR_STATUS_SEED:
     1612        case TR_STATUS_DOWNLOAD:
     1613            return; /* already started */
     1614            break;
     1615
     1616        case TR_STATUS_SEED_WAIT:
     1617        case TR_STATUS_DOWNLOAD_WAIT:
     1618            if( !bypass_queue )
     1619                return; /* already queued */
     1620            break;
     1621
     1622        case TR_STATUS_CHECK:
     1623        case TR_STATUS_CHECK_WAIT:
     1624            /* verifying right now... wait until that's done so
     1625             * we'll know what completeness to use/announce */
     1626            tor->startAfterVerify = true;
     1627            return;
     1628            break;
     1629
     1630        case TR_STATUS_STOPPED:
     1631            if( !bypass_queue && torrentShouldQueue( tor ) ) {
     1632                queueAppend( tor );
     1633                return;
     1634            }
     1635            break;
     1636    }
    15651637
    15661638    /* don't allow the torrent to be started if the files disappeared */
    15671639    if( setLocalErrorIfFilesDisappeared( tor ) )
    15681640        return;
    1569 
    1570     /* verifying right now... wait until that's done so
    1571      * we'll know what completeness to use/announce */
    1572     if( tor->verifyState != TR_VERIFY_NONE ) {
    1573         tor->startAfterVerify = true;
    1574         return;
    1575     }
    15761641
    15771642    /* otherwise, start it now... */
     
    16011666{
    16021667    if( tr_isTorrent( tor ) )
    1603         torrentStart( tor );
     1668        torrentStart( tor, false );
     1669}
     1670
     1671void
     1672tr_torrentStartNow( tr_torrent * tor )
     1673{
     1674    if( tr_isTorrent( tor ) )
     1675        torrentStart( tor, true );
    16041676}
    16051677
     
    16141686    if( tor->startAfterVerify ) {
    16151687        tor->startAfterVerify = false;
    1616         torrentStart( tor );
     1688        torrentStart( tor, false );
    16171689    }
    16181690}
     
    16821754
    16831755    tr_verifyRemove( tor );
     1756    queueRemove( tor );
    16841757    tr_peerMgrStopTorrent( tor );
    16851758    tr_announcerTorrentStopped( tor );
     
    30863159    return tr_strdup_printf( "%s.part", tor->info.files[fileNum].name );
    30873160}
     3161
     3162/***
     3163****
     3164***/
     3165
     3166static int
     3167compareTorrentByQueuePosition( const void * va, const void * vb )
     3168{
     3169    const tr_torrent * a = * (const tr_torrent **) va;
     3170    const tr_torrent * b = * (const tr_torrent **) vb;
     3171
     3172    return a->queuePosition - b->queuePosition;
     3173}
     3174
     3175static bool
     3176queueIsSequenced( tr_torrent * tor )
     3177{
     3178    int i ;
     3179    int n ;
     3180    bool is_sequenced = true;
     3181    tr_session * session = tor->session;
     3182    tr_direction direction = tr_torrentGetQueueDirection( tor );
     3183    tr_torrent ** tmp = tr_new( tr_torrent *, session->torrentCount );
     3184
     3185    /* get all the torrents in that queue */
     3186    n = 0;
     3187    tor = NULL;
     3188    while(( tor = tr_torrentNext( session, tor )))
     3189        if( tr_torrentIsQueued( tor ) && ( direction == tr_torrentGetQueueDirection( tor ) ) )
     3190            tmp[n++] = tor;
     3191
     3192    /* sort them by position */
     3193    qsort( tmp, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
     3194
     3195#if 0
     3196    /* print them */
     3197    fprintf( stderr, "sequence: " );
     3198    for( i=0; i<n; ++i )
     3199        fprintf( stderr, "%d ", tmp[i]->queuePosition );
     3200    fprintf( stderr, "\n" );
     3201#endif
     3202
     3203    /* test them */
     3204    for( i=0; is_sequenced && i<n; ++i )
     3205        if( tmp[i]->queuePosition != i )
     3206            is_sequenced = false;
     3207
     3208    tr_free( tmp );
     3209    return is_sequenced;
     3210}
     3211
     3212int
     3213tr_torrentGetQueuePosition( const tr_torrent * tor )
     3214{
     3215    return tor->queuePosition;
     3216}
     3217
     3218void
     3219tr_torrentSetQueuePosition( tr_torrent * tor, int pos )
     3220{
     3221    if( tr_torrentIsQueued( tor ) )
     3222    {
     3223        int back = -1;
     3224        tr_torrent * walk;
     3225        const tr_direction direction = tr_torrentGetQueueDirection( tor );
     3226        const int old_pos = tor->queuePosition;
     3227        const time_t now = tr_time( );
     3228
     3229        if( pos < 0 )
     3230            pos = 0;
     3231
     3232        tor->queuePosition = -1;
     3233
     3234        walk = NULL;
     3235        while(( walk = tr_torrentNext( tor->session, walk )))
     3236        {
     3237            if( tr_torrentIsQueued( walk ) && ( tr_torrentGetQueueDirection( walk ) == direction ) )
     3238            {
     3239                if( old_pos < pos ) {
     3240                    if( ( old_pos <= walk->queuePosition ) && ( walk->queuePosition <= pos ) ) {
     3241                        walk->queuePosition--;
     3242                        walk->anyDate = now;
     3243                    }
     3244                }
     3245
     3246                if( old_pos > pos ) {
     3247                    if( ( pos <= walk->queuePosition ) && ( walk->queuePosition < old_pos ) ) {
     3248                        walk->queuePosition++;
     3249                        walk->anyDate = now;
     3250                    }
     3251                }
     3252
     3253                if( back < walk->queuePosition )
     3254                    back = walk->queuePosition;
     3255            }
     3256        }
     3257
     3258        tor->queuePosition = MIN( pos, (back+1) );
     3259        tor->anyDate = now;
     3260    }
     3261
     3262    assert( queueIsSequenced( tor ) );
     3263}
     3264
     3265void
     3266tr_torrentsQueueMoveTop( tr_torrent ** torrents_in, int n )
     3267{
     3268    int i;
     3269    tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
     3270    qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
     3271    for( i=n-1; i>=0; --i )
     3272        tr_torrentSetQueuePosition( torrents[i], 0 );
     3273    tr_free( torrents );
     3274}
     3275
     3276void
     3277tr_torrentsQueueMoveUp( tr_torrent ** torrents_in, int n )
     3278{
     3279    int i;
     3280    tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
     3281    qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
     3282    for( i=0; i<n; ++i )
     3283        tr_torrentSetQueuePosition( torrents[i], torrents[i]->queuePosition - 1 );
     3284    tr_free( torrents );
     3285}
     3286
     3287void
     3288tr_torrentsQueueMoveDown( tr_torrent ** torrents_in, int n )
     3289{
     3290    int i;
     3291    tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
     3292    qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
     3293    for( i=n-1; i>=0; --i )
     3294        tr_torrentSetQueuePosition( torrents[i], torrents[i]->queuePosition + 1 );
     3295    tr_free( torrents );
     3296}
     3297
     3298void
     3299tr_torrentsQueueMoveBottom( tr_torrent ** torrents_in, int n )
     3300{
     3301    int i;
     3302    tr_torrent ** torrents = tr_memdup( torrents_in, sizeof( tr_torrent * ) * n );
     3303    qsort( torrents, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
     3304    for( i=0; i<n; ++i )
     3305        tr_torrentSetQueuePosition( torrents[i], INT_MAX );
     3306    tr_free( torrents );
     3307}
     3308
     3309/* Ensure that the torrents queued for downloads have queuePositions contiguous from [0...n] */
     3310static void
     3311queueResequence( tr_session * session, tr_direction direction )
     3312{
     3313    int i;
     3314    int n;
     3315    tr_torrent * tor = NULL;
     3316    tr_torrent ** tmp = tr_new( tr_torrent *, session->torrentCount );
     3317    const time_t now = tr_time( );
     3318
     3319    assert( tr_isSession( session ) );
     3320    assert( tr_isDirection( direction ) );
     3321
     3322    /* get all the torrents in that queue */
     3323    n = 0;
     3324    while(( tor = tr_torrentNext( session, tor ))) {
     3325        if( direction == tr_torrentGetQueueDirection( tor )) {
     3326            const int position = tr_torrentGetQueuePosition( tor );
     3327            if( position >= 0 )
     3328                tmp[n++] = tor;
     3329        }
     3330    }
     3331
     3332    /* sort them by position */
     3333    qsort( tmp, n, sizeof( tr_torrent * ), compareTorrentByQueuePosition );
     3334
     3335    /* sequence them... */
     3336    for( i=0; i<n; ++i ) {
     3337        tr_torrent * tor = tmp[i];
     3338        if( tor->queuePosition != i ) {
     3339            tor->queuePosition = i;
     3340            tor->anyDate = now;
     3341        }
     3342    }
     3343
     3344    tr_free( tmp );
     3345}
     3346
     3347static void
     3348queueRemove( tr_torrent * tor )
     3349{
     3350    if( tr_torrentIsQueued( tor ) )
     3351    {
     3352        tor->queuePosition = -1;
     3353        queueResequence( tor->session, tr_torrentGetQueueDirection( tor ) );
     3354    }
     3355}
     3356
     3357static void
     3358queueAppend( tr_torrent * tor )
     3359{
     3360    if( !tr_torrentIsQueued( tor ) )
     3361    {
     3362        /* tr_torrentSetQueuePosition() requres the torrent to be queued,
     3363           so init tor->queuePosition to the back... */
     3364        tor->queuePosition = INT_MAX;
     3365
     3366        tr_torrentSetQueuePosition( tor, INT_MAX );
     3367    }
     3368}
  • trunk/libtransmission/torrent.h

    r12296 r12607  
    222222    int                        secondsDownloading;
    223223    int                        secondsSeeding;
     224
     225    int                        queuePosition;
    224226
    225227    tr_torrent_metadata_func  * metadata_func;
     
    427429uint64_t tr_torrentGetCurrentSizeOnDisk( const tr_torrent * tor );
    428430
     431bool tr_torrentIsStalled( const tr_torrent * tor );
     432
     433static inline bool
     434tr_torrentIsQueued( const tr_torrent * tor )
     435{
     436    return tor->queuePosition >= 0;
     437}
     438
     439static inline tr_direction
     440tr_torrentGetQueueDirection( const tr_torrent * tor )
     441{
     442    return tr_torrentIsSeed( tor ) ? TR_UP : TR_DOWN;
     443}
    429444
    430445#endif
  • trunk/libtransmission/transmission.h

    r12577 r12607  
    157157#define TR_DEFAULT_PEER_LIMIT_TORRENT_STR        "60"
    158158
    159 #define TR_PREFS_KEY_ALT_SPEED_ENABLED            "alt-speed-enabled"
    160 #define TR_PREFS_KEY_ALT_SPEED_UP_KBps            "alt-speed-up"
    161 #define TR_PREFS_KEY_ALT_SPEED_DOWN_KBps          "alt-speed-down"
    162 #define TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN         "alt-speed-time-begin"
    163 #define TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED       "alt-speed-time-enabled"
    164 #define TR_PREFS_KEY_ALT_SPEED_TIME_END           "alt-speed-time-end"
    165 #define TR_PREFS_KEY_ALT_SPEED_TIME_DAY           "alt-speed-time-day"
    166 #define TR_PREFS_KEY_BIND_ADDRESS_IPV4            "bind-address-ipv4"
    167 #define TR_PREFS_KEY_BIND_ADDRESS_IPV6            "bind-address-ipv6"
    168 #define TR_PREFS_KEY_BLOCKLIST_ENABLED            "blocklist-enabled"
    169 #define TR_PREFS_KEY_BLOCKLIST_URL                "blocklist-url"
    170 #define TR_PREFS_KEY_MAX_CACHE_SIZE_MB            "cache-size-mb"
    171 #define TR_PREFS_KEY_DHT_ENABLED                  "dht-enabled"
    172 #define TR_PREFS_KEY_UTP_ENABLED                  "utp-enabled"
    173 #define TR_PREFS_KEY_LPD_ENABLED                  "lpd-enabled"
    174 #define TR_PREFS_KEY_PREFETCH_ENABLED             "prefetch-enabled"
    175 #define TR_PREFS_KEY_DOWNLOAD_DIR                 "download-dir"
    176 #define TR_PREFS_KEY_ENCRYPTION                   "encryption"
    177 #define TR_PREFS_KEY_IDLE_LIMIT                   "idle-seeding-limit"
    178 #define TR_PREFS_KEY_IDLE_LIMIT_ENABLED           "idle-seeding-limit-enabled"
    179 #define TR_PREFS_KEY_INCOMPLETE_DIR               "incomplete-dir"
    180 #define TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED       "incomplete-dir-enabled"
    181 #define TR_PREFS_KEY_MSGLEVEL                     "message-level"
    182 #define TR_PREFS_KEY_PEER_LIMIT_GLOBAL            "peer-limit-global"
    183 #define TR_PREFS_KEY_PEER_LIMIT_TORRENT           "peer-limit-per-torrent"
    184 #define TR_PREFS_KEY_PEER_PORT                    "peer-port"
    185 #define TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START    "peer-port-random-on-start"
    186 #define TR_PREFS_KEY_PEER_PORT_RANDOM_LOW         "peer-port-random-low"
    187 #define TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH        "peer-port-random-high"
    188 #define TR_PREFS_KEY_PEER_SOCKET_TOS              "peer-socket-tos"
    189 #define TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM    "peer-congestion-algorithm"
    190 #define TR_PREFS_KEY_PEX_ENABLED                  "pex-enabled"
    191 #define TR_PREFS_KEY_PORT_FORWARDING              "port-forwarding-enabled"
    192 #define TR_PREFS_KEY_PREALLOCATION                "preallocation"
    193 #define TR_PREFS_KEY_RATIO                        "ratio-limit"
    194 #define TR_PREFS_KEY_RATIO_ENABLED                "ratio-limit-enabled"
    195 #define TR_PREFS_KEY_RENAME_PARTIAL_FILES         "rename-partial-files"
    196 #define TR_PREFS_KEY_RPC_AUTH_REQUIRED            "rpc-authentication-required"
    197 #define TR_PREFS_KEY_RPC_BIND_ADDRESS             "rpc-bind-address"
    198 #define TR_PREFS_KEY_RPC_ENABLED                  "rpc-enabled"
    199 #define TR_PREFS_KEY_RPC_PASSWORD                 "rpc-password"
    200 #define TR_PREFS_KEY_RPC_PORT                     "rpc-port"
    201 #define TR_PREFS_KEY_RPC_USERNAME                 "rpc-username"
    202 #define TR_PREFS_KEY_RPC_URL                      "rpc-url"
    203 #define TR_PREFS_KEY_RPC_WHITELIST_ENABLED        "rpc-whitelist-enabled"
    204 #define TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS       "scrape-paused-torrents-enabled"
    205 #define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME "script-torrent-done-filename"
    206 #define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED  "script-torrent-done-enabled"
    207 #define TR_PREFS_KEY_RPC_WHITELIST                "rpc-whitelist"
    208 #define TR_PREFS_KEY_DSPEED_KBps                  "speed-limit-down"
    209 #define TR_PREFS_KEY_DSPEED_ENABLED               "speed-limit-down-enabled"
    210 #define TR_PREFS_KEY_USPEED_KBps                  "speed-limit-up"
    211 #define TR_PREFS_KEY_USPEED_ENABLED               "speed-limit-up-enabled"
    212 #define TR_PREFS_KEY_UMASK                        "umask"
    213 #define TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT     "upload-slots-per-torrent"
    214 #define TR_PREFS_KEY_START                        "start-added-torrents"
    215 #define TR_PREFS_KEY_TRASH_ORIGINAL               "trash-original-torrent-files"
     159#define TR_PREFS_KEY_ALT_SPEED_ENABLED                  "alt-speed-enabled"
     160#define TR_PREFS_KEY_ALT_SPEED_UP_KBps                  "alt-speed-up"
     161#define TR_PREFS_KEY_ALT_SPEED_DOWN_KBps                "alt-speed-down"
     162#define TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN               "alt-speed-time-begin"
     163#define TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED             "alt-speed-time-enabled"
     164#define TR_PREFS_KEY_ALT_SPEED_TIME_END                 "alt-speed-time-end"
     165#define TR_PREFS_KEY_ALT_SPEED_TIME_DAY                 "alt-speed-time-day"
     166#define TR_PREFS_KEY_BIND_ADDRESS_IPV4                  "bind-address-ipv4"
     167#define TR_PREFS_KEY_BIND_ADDRESS_IPV6                  "bind-address-ipv6"
     168#define TR_PREFS_KEY_BLOCKLIST_ENABLED                  "blocklist-enabled"
     169#define TR_PREFS_KEY_BLOCKLIST_URL                      "blocklist-url"
     170#define TR_PREFS_KEY_MAX_CACHE_SIZE_MB                  "cache-size-mb"
     171#define TR_PREFS_KEY_DHT_ENABLED                        "dht-enabled"
     172#define TR_PREFS_KEY_UTP_ENABLED                        "utp-enabled"
     173#define TR_PREFS_KEY_LPD_ENABLED                        "lpd-enabled"
     174#define TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE                "download-queue-size"
     175#define TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED             "download-queue-enabled"
     176#define TR_PREFS_KEY_PREFETCH_ENABLED                   "prefetch-enabled"
     177#define TR_PREFS_KEY_DOWNLOAD_DIR                       "download-dir"
     178#define TR_PREFS_KEY_ENCRYPTION                         "encryption"
     179#define TR_PREFS_KEY_IDLE_LIMIT                         "idle-seeding-limit"
     180#define TR_PREFS_KEY_IDLE_LIMIT_ENABLED                 "idle-seeding-limit-enabled"
     181#define TR_PREFS_KEY_INCOMPLETE_DIR                     "incomplete-dir"
     182#define TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED             "incomplete-dir-enabled"
     183#define TR_PREFS_KEY_MSGLEVEL                           "message-level"
     184#define TR_PREFS_KEY_PEER_LIMIT_GLOBAL                  "peer-limit-global"
     185#define TR_PREFS_KEY_PEER_LIMIT_TORRENT                 "peer-limit-per-torrent"
     186#define TR_PREFS_KEY_PEER_PORT                          "peer-port"
     187#define TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START          "peer-port-random-on-start"
     188#define TR_PREFS_KEY_PEER_PORT_RANDOM_LOW               "peer-port-random-low"
     189#define TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH              "peer-port-random-high"
     190#define TR_PREFS_KEY_PEER_SOCKET_TOS                    "peer-socket-tos"
     191#define TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM          "peer-congestion-algorithm"
     192#define TR_PREFS_KEY_PEX_ENABLED                        "pex-enabled"
     193#define TR_PREFS_KEY_PORT_FORWARDING                    "port-forwarding-enabled"
     194#define TR_PREFS_KEY_PREALLOCATION                      "preallocation"
     195#define TR_PREFS_KEY_RATIO                              "ratio-limit"
     196#define TR_PREFS_KEY_RATIO_ENABLED                      "ratio-limit-enabled"
     197#define TR_PREFS_KEY_RENAME_PARTIAL_FILES               "rename-partial-files"
     198#define TR_PREFS_KEY_RPC_AUTH_REQUIRED                  "rpc-authentication-required"
     199#define TR_PREFS_KEY_RPC_BIND_ADDRESS                   "rpc-bind-address"
     200#define TR_PREFS_KEY_RPC_ENABLED                        "rpc-enabled"
     201#define TR_PREFS_KEY_RPC_PASSWORD                       "rpc-password"
     202#define TR_PREFS_KEY_RPC_PORT                           "rpc-port"
     203#define TR_PREFS_KEY_RPC_USERNAME                       "rpc-username"
     204#define TR_PREFS_KEY_RPC_URL                            "rpc-url"
     205#define TR_PREFS_KEY_RPC_WHITELIST_ENABLED              "rpc-whitelist-enabled"
     206#define TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS             "scrape-paused-torrents-enabled"
     207#define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME       "script-torrent-done-filename"
     208#define TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED        "script-torrent-done-enabled"
     209#define TR_PREFS_KEY_SEED_QUEUE_SIZE                    "seed-queue-size"
     210#define TR_PREFS_KEY_SEED_QUEUE_ENABLED                 "seed-queue-enabled"
     211#define TR_PREFS_KEY_RPC_WHITELIST                      "rpc-whitelist"
     212#define TR_PREFS_KEY_QUEUE_STALLED_MINUTES              "queue-stalled-minutes"
     213#define TR_PREFS_KEY_DSPEED_KBps                        "speed-limit-down"
     214#define TR_PREFS_KEY_DSPEED_ENABLED                     "speed-limit-down-enabled"
     215#define TR_PREFS_KEY_USPEED_KBps                        "speed-limit-up"
     216#define TR_PREFS_KEY_USPEED_ENABLED                     "speed-limit-up-enabled"
     217#define TR_PREFS_KEY_UMASK                              "umask"
     218#define TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT           "upload-slots-per-torrent"
     219#define TR_PREFS_KEY_START                              "start-added-torrents"
     220#define TR_PREFS_KEY_TRASH_ORIGINAL                     "trash-original-torrent-files"
    216221
    217222
     
    736741tr_priority_t   tr_torrentGetPriority( const tr_torrent * );
    737742void            tr_torrentSetPriority( tr_torrent *, tr_priority_t );
     743
     744/***
     745****
     746****  Torrent Queueing
     747****
     748****  There are independent queues for seeding (TR_UP) and leeching (TR_DOWN).
     749****
     750****  If the session already has enough non-stalled seeds/leeches when
     751****  tr_torrentStart() is called, the torrent will be moved into the
     752****  appropriate queue and its state will be TR_STATUS_{DOWNLOAD,SEED}_WAIT.
     753****
     754****  To bypass the queue and unconditionally start the torrent use
     755****  tr_torrentStartNow().
     756****
     757****  Torrents can be moved in the queue using the simple functions
     758****  tr_torrentQueueMove{Top,Up,Down,Bottom}. They can be moved to
     759****  arbitrary points in the queue with tr_torrentSetQueuePosition().
     760**** 
     761***/
     762
     763
     764/** @brief Like tr_torrentStart(), but resumes right away regardless of the queues. */
     765void tr_torrentStartNow         ( tr_torrent * );
     766
     767/** @brief Return the queued torrent's position in the queue it's in. [0...n) */
     768int  tr_torrentGetQueuePosition ( const tr_torrent * );
     769
     770/** @brief Set the queued torrent's position in the queue it's in.
     771 * Special cases: pos <= 0 moves to the front; pos >= queue length moves to the back */
     772void tr_torrentSetQueuePosition ( tr_torrent *, int queuePosition );
     773
     774/**
     775**/
     776
     777/** @brief Convenience function for moving a batch of torrents to the front of their queue(s) */
     778void tr_torrentsQueueMoveTop    ( tr_torrent ** torrents, int torrentCount );
     779
     780/** @brief Convenience function for moving a batch of torrents ahead one step in their queue(s) */
     781void tr_torrentsQueueMoveUp     ( tr_torrent ** torrents, int torrentCount );
     782
     783/** @brief Convenience function for moving a batch of torrents back one step in their queue(s) */
     784void tr_torrentsQueueMoveDown   ( tr_torrent ** torrents, int torrentCount );
     785
     786/** @brief Convenience function for moving a batch of torrents to the back of their queue(s) */
     787void tr_torrentsQueueMoveBottom ( tr_torrent ** torrents, int torrentCount );
     788
     789/**
     790**/
     791
     792/** @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 */
     793void tr_sessionSetQueueSize     ( tr_session *, tr_direction, int max_simultaneous_seed_torrents );
     794
     795/** @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 */
     796int  tr_sessionGetQueueSize     ( const tr_session *, tr_direction );
     797
     798/** @brief Set whether or not to limit how many torrents can download (TR_DOWN) or seed (TR_UP) at the same time  */
     799void tr_sessionSetQueueEnabled  ( tr_session *, tr_direction, bool do_limit_simultaneous_seed_torrents );
     800
     801/** @brief Return true if we're limiting how many torrents can concurrently download (TR_DOWN) or seed (TR_UP) at the same time */
     802bool tr_sessionGetQueueEnabled  ( const tr_session *, tr_direction );
     803
     804/** @brief Consider torrent as 'stalled' when it's been inactive for N minutes.
     805    Stalled torrents are left running but are not counted by tr_sessionGetQueueSize(). */
     806void tr_sessionSetQueueStalledMinutes( tr_session *, int minutes );
     807
     808/** @return the number of minutes a torrent can be idle before being considered as stalled */
     809int  tr_sessionGetQueueStalledMinutes( const tr_session * );
     810
     811
     812/***
     813****
     814****
     815***/
    738816
    739817/**
     
    17241802typedef enum
    17251803{
    1726     TR_STATUS_CHECK_WAIT   = ( 1 << 0 ), /* Waiting in queue to check files */
    1727     TR_STATUS_CHECK        = ( 1 << 1 ), /* Checking files */
    1728     TR_STATUS_DOWNLOAD     = ( 1 << 2 ), /* Downloading */
    1729     TR_STATUS_SEED         = ( 1 << 3 ), /* Seeding */
    1730     TR_STATUS_STOPPED      = ( 1 << 4 )  /* Torrent is stopped */
     1804    TR_STATUS_STOPPED        = 0, /* Torrent is stopped */
     1805    TR_STATUS_CHECK_WAIT     = 1, /* Queued to check files */
     1806    TR_STATUS_CHECK          = 2, /* Checking files */
     1807    TR_STATUS_DOWNLOAD_WAIT  = 3, /* Queued to download */
     1808    TR_STATUS_DOWNLOAD       = 4, /* Downloading */
     1809    TR_STATUS_SEED_WAIT      = 5, /* Queued to seed */
     1810    TR_STATUS_SEED           = 6  /* Seeding */
    17311811}
    17321812tr_torrent_activity;
     
    19171997        As a result, only paused torrents can be finished. */
    19181998    bool   finished;
     1999
     2000    /** The position of this torrent in the download queue.
     2001        This will be >= 0 if the torrent is queued; -1 otherwise. */
     2002    int queuePosition;
    19192003}
    19202004tr_stat;
  • trunk/qt/filterbar.cc

    r12549 r12607  
    246246    row = new QStandardItem( blankIcon, tr( "Finished" ) );
    247247    row->setData( FilterMode::SHOW_FINISHED, ActivityRole );
    248     model->appendRow( row );
    249 
    250     row = new QStandardItem( blankIcon, tr( "Queued" ) );
    251     row->setData( FilterMode::SHOW_QUEUED, ActivityRole );
    252248    model->appendRow( row );
    253249
  • trunk/qt/filters.cc

    r11196 r12607  
    2121    "show-paused",
    2222    "show-finished",
    23     "show-queued",
    2423    "show-verifying",
    2524    "show-error",
  • trunk/qt/filters.h

    r11196 r12607  
    2727        static const QString names[];
    2828        enum { SHOW_ALL, SHOW_ACTIVE, SHOW_DOWNLOADING, SHOW_SEEDING, SHOW_PAUSED,
    29                SHOW_FINISHED, SHOW_QUEUED, SHOW_VERIFYING, SHOW_ERROR, NUM_MODES };
     29               SHOW_FINISHED, SHOW_VERIFYING, SHOW_ERROR, NUM_MODES };
    3030        static int modeFromName( const QString& name );
    3131        static const QString& nameFromMode( int mode ) { return names[mode]; }
  • trunk/qt/mainwin.cc

    r12594 r12607  
    113113    ui.action_OpenFolder->setIcon( getStockIcon( "folder-open", QStyle::SP_DirOpenIcon ) );
    114114    ui.action_Start->setIcon( getStockIcon( "media-playback-start", QStyle::SP_MediaPlay ) );
     115    ui.action_StartNow->setIcon( getStockIcon( "media-playback-start", QStyle::SP_MediaPlay ) );
    115116    ui.action_Announce->setIcon( getStockIcon( "network-transmit-receive" ) );
    116117    ui.action_Pause->setIcon( getStockIcon( "media-playback-pause", QStyle::SP_MediaPause ) );
     
    125126    ui.action_Contents->setIcon( getStockIcon( "help-contents", QStyle::SP_DialogHelpButton ) );
    126127    ui.action_About->setIcon( getStockIcon( "help-about" ) );
     128    ui.action_QueueMoveTop->setIcon( getStockIcon( "go-top" ) );
     129    ui.action_QueueMoveUp->setIcon( getStockIcon( "go-up", QStyle::SP_ArrowUp ) );
     130    ui.action_QueueMoveDown->setIcon( getStockIcon( "go-down", QStyle::SP_ArrowDown ) );
     131    ui.action_QueueMoveBottom->setIcon( getStockIcon( "go-bottom" ) );
    127132
    128133    // ui signals
     
    141146    connect( ui.action_ReverseSortOrder, SIGNAL(toggled(bool)), this, SLOT(setSortAscendingPref(bool)));
    142147    connect( ui.action_Start, SIGNAL(triggered()), this, SLOT(startSelected()));
     148    connect( ui.action_QueueMoveTop,    SIGNAL(triggered()), this, SLOT(queueMoveTop()));
     149    connect( ui.action_QueueMoveUp,     SIGNAL(triggered()), this, SLOT(queueMoveUp()));
     150    connect( ui.action_QueueMoveDown,   SIGNAL(triggered()), this, SLOT(queueMoveDown()));
     151    connect( ui.action_QueueMoveBottom, SIGNAL(triggered()), this, SLOT(queueMoveBottom()));
     152    connect( ui.action_StartNow, SIGNAL(triggered()), this, SLOT(startSelectedNow()));
    143153    connect( ui.action_Pause, SIGNAL(triggered()), this, SLOT(pauseSelected()));
    144154    connect( ui.action_Remove, SIGNAL(triggered()), this, SLOT(removeSelected()));
     
    162172    connect( ui.action_SessionDialog, SIGNAL(triggered()), mySessionDialog, SLOT(show()));
    163173    connect( ui.listView, SIGNAL(activated(const QModelIndex&)), ui.action_Properties, SLOT(trigger()));
    164 
    165     QAction * sep2 = new QAction( this );
    166     sep2->setSeparator( true );
    167     QAction * sep3 = new QAction( this );
    168     sep3->setSeparator( true );
    169 
    170     // context menu
    171     QList<QAction*> actions;
    172     actions << ui.action_Properties
    173             << ui.action_OpenFolder
    174             << sep2
    175             << ui.action_Start
    176             << ui.action_Announce
    177             << ui.action_Pause
    178             << ui.action_CopyMagnetToClipboard
    179             << sep3
    180             << ui.action_Verify
    181             << ui.action_SetLocation
    182             << sep
    183             << ui.action_Remove
    184             << ui.action_Delete;
    185     addActions( actions );
    186     setContextMenuPolicy( Qt::ActionsContextMenu );
    187174
    188175    // signals
     
    726713    int selected( 0 );
    727714    int paused( 0 );
     715    int queued( 0 );
    728716    int selectedAndPaused( 0 );
     717    int selectedAndQueued( 0 );
    729718    int canAnnounce( 0 );
    730719    const QAbstractItemModel * model( ui.listView->model( ) );
     
    740729            const bool isSelected( selectionModel->isSelected( modelIndex ) );
    741730            const bool isPaused( tor->isPaused( ) );
    742             if( isSelected )
    743                 ++selected;
    744             if( isPaused )
    745                 ++ paused;
    746             if( isSelected && isPaused )
    747                 ++selectedAndPaused;
    748             if( tor->canManualAnnounce( ) )
    749                 ++canAnnounce;
     731            const bool isQueued( tor->isQueued( ) );
     732            if( isSelected ) ++selected;
     733            if( isQueued ) ++queued;
     734            if( isPaused ) ++ paused;
     735            if( isSelected && isPaused ) ++selectedAndPaused;
     736            if( isSelected && isQueued ) ++selectedAndQueued;
     737            if( tor->canManualAnnounce( ) ) ++canAnnounce;
    750738        }
    751739    }
     
    767755    ui.action_PauseAll->setEnabled( paused < rowCount );
    768756    ui.action_Start->setEnabled( selectedAndPaused > 0 );
     757    ui.action_StartNow->setEnabled( selectedAndPaused + selectedAndQueued > 0 );
    769758    ui.action_Pause->setEnabled( selectedAndPaused < selected );
    770759    ui.action_Announce->setEnabled( selected > 0 && ( canAnnounce == selected ) );
     760
     761    ui.action_QueueMoveTop->setEnabled( selectedAndQueued > 0 );
     762    ui.action_QueueMoveUp->setEnabled( selectedAndQueued > 0 );
     763    ui.action_QueueMoveDown->setEnabled( selectedAndQueued > 0 );
     764    ui.action_QueueMoveBottom->setEnabled( selectedAndQueued > 0 );
    771765
    772766    if( myDetailsDialog )
     
    804798}
    805799void
     800TrMainWindow :: startSelectedNow( )
     801{
     802    mySession.startTorrentsNow( getSelectedTorrents( ) );
     803}
     804void
    806805TrMainWindow :: pauseSelected( )
    807806{
    808807    mySession.pauseTorrents( getSelectedTorrents( ) );
     808}
     809void
     810TrMainWindow :: queueMoveTop( )
     811{
     812    mySession.queueMoveTop( getSelectedTorrents( ) );
     813}
     814void
     815TrMainWindow :: queueMoveUp( )
     816{
     817    mySession.queueMoveUp( getSelectedTorrents( ) );
     818}
     819void
     820TrMainWindow :: queueMoveDown( )
     821{
     822    mySession.queueMoveDown( getSelectedTorrents( ) );
     823}
     824void
     825TrMainWindow :: queueMoveBottom( )
     826{
     827    mySession.queueMoveBottom( getSelectedTorrents( ) );
    809828}
    810829void
     
    12971316    dynamic_cast<MyApp*>(QApplication::instance())->addTorrent( key );
    12981317}
     1318
     1319/***
     1320****
     1321***/
     1322
     1323void
     1324TrMainWindow :: contextMenuEvent( QContextMenuEvent * event )
     1325{
     1326    QMenu * menu = new QMenu( this );
     1327
     1328    menu->addAction( ui.action_Properties );
     1329    menu->addAction( ui.action_OpenFolder );
     1330
     1331    QAction * sep = new QAction( this );
     1332    sep->setSeparator( true );
     1333    menu->addAction( sep );
     1334    menu->addAction( ui.action_Start );
     1335    menu->addAction( ui.action_StartNow );
     1336    menu->addAction( ui.action_Announce );
     1337    QMenu * queueMenu = menu->addMenu( tr( "Queue" ) );
     1338        queueMenu->addAction( ui.action_QueueMoveTop );
     1339        queueMenu->addAction( ui.action_QueueMoveUp );
     1340        queueMenu->addAction( ui.action_QueueMoveDown );
     1341        queueMenu->addAction( ui.action_QueueMoveBottom );
     1342    menu->addAction( ui.action_Pause );
     1343
     1344    sep = new QAction( this );
     1345    sep->setSeparator( true );
     1346    menu->addAction( sep );
     1347    menu->addAction( ui.action_Verify );
     1348    menu->addAction( ui.action_SetLocation );
     1349    menu->addAction( ui.action_CopyMagnetToClipboard );
     1350
     1351    sep = new QAction( this );
     1352    sep->setSeparator( true );
     1353    menu->addAction( sep );
     1354    menu->addAction( ui.action_Remove );
     1355    menu->addAction( ui.action_Delete );
     1356
     1357    menu->popup( event->globalPos( ) );
     1358}
  • trunk/qt/mainwin.h

    r12557 r12607  
    162162        void startAll( );
    163163        void startSelected( );
     164        void startSelectedNow( );
    164165        void pauseAll( );
    165166        void pauseSelected( );
     
    167168        void deleteSelected( );
    168169        void verifySelected( );
     170        void queueMoveTop( );
     171        void queueMoveUp( );
     172        void queueMoveDown( );
     173        void queueMoveBottom( );
    169174        void reannounceSelected( );
    170175        void addTorrent( const QString& filename );
     
    188193
    189194    protected:
     195        virtual void contextMenuEvent( QContextMenuEvent * );
    190196        virtual void dragEnterEvent( QDragEnterEvent * );
    191197        virtual void dropEvent( QDropEvent * );
  • trunk/qt/mainwin.ui

    r11726 r12607  
    5252     <y>0</y>
    5353     <width>792</width>
    54      <height>23</height>
     54     <height>25</height>
    5555    </rect>
    5656   </property>
     
    6565     <string>&amp;Torrent</string>
    6666    </property>
     67    <widget class="QMenu" name="menuQueue">
     68     <property name="title">
     69      <string>Queue</string>
     70     </property>
     71     <addaction name="action_QueueMoveTop"/>
     72     <addaction name="action_QueueMoveUp"/>
     73     <addaction name="action_QueueMoveDown"/>
     74     <addaction name="action_QueueMoveBottom"/>
     75    </widget>
    6776    <addaction name="separator"/>
    6877    <addaction name="action_Properties"/>
     
    7079    <addaction name="separator"/>
    7180    <addaction name="action_Start"/>
     81    <addaction name="action_StartNow"/>
     82    <addaction name="menuQueue"/>
    7283    <addaction name="action_Announce"/>
    7384    <addaction name="action_Pause"/>
    74     <addaction name="action_CopyMagnetToClipboard"/>
    7585    <addaction name="separator"/>
    7686    <addaction name="action_SetLocation"/>
    7787    <addaction name="action_Verify"/>
     88    <addaction name="action_CopyMagnetToClipboard"/>
    7889    <addaction name="separator"/>
    7990    <addaction name="action_Remove"/>
     
    588599   </property>
    589600  </action>
     601  <action name="action_StartNow">
     602   <property name="text">
     603    <string>Start &amp;Now</string>
     604   </property>
     605   <property name="toolTip">
     606    <string>Bypass the queue and start now</string>
     607   </property>
     608   <property name="shortcut">
     609    <string>Ctrl+Shift+S</string>
     610   </property>
     611   <property name="priority">
     612    <enum>QAction::LowPriority</enum>
     613   </property>
     614  </action>
     615  <action name="action_QueueMoveTop">
     616   <property name="text">
     617    <string>Move to &amp;Top</string>
     618   </property>
     619  </action>
     620  <action name="action_QueueMoveUp">
     621   <property name="text">
     622    <string>Move &amp;Up</string>
     623   </property>
     624  </action>
     625  <action name="action_QueueMoveDown">
     626   <property name="text">
     627    <string>Move &amp;Down</string>
     628   </property>
     629  </action>
     630  <action name="action_QueueMoveBottom">
     631   <property name="text">
     632    <string>Move to &amp;Bottom</string>
     633   </property>
     634  </action>
    590635 </widget>
    591636 <resources>
  • trunk/qt/prefs-dialog.cc

    r12550 r12607  
    533533    hig->addSectionTitle( tr( "Adding" ) );
    534534
     535        hig->addWideControl( checkBoxNew( tr( "Show &options dialog" ), Prefs::OPTIONS_PROMPT ) );
     536        hig->addWideControl( checkBoxNew( tr( "&Start when added" ), Prefs::START ) );
     537        hig->addWideControl( checkBoxNew( tr( "Mo&ve .torrent file to the trash" ), Prefs::TRASH_ORIGINAL ) );
     538
    535539        l = checkBoxNew( tr( "Automatically &add torrents from:" ), Prefs::DIR_WATCH_ENABLED );
    536540        QPushButton * b = myWatchButton = new QPushButton;
     
    541545        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
    542546
    543         hig->addWideControl( checkBoxNew( tr( "Show &options dialog" ), Prefs::OPTIONS_PROMPT ) );
    544         hig->addWideControl( checkBoxNew( tr( "&Start when added" ), Prefs::START ) );
    545         hig->addWideControl( checkBoxNew( tr( "Mo&ve .torrent file to the trash" ), Prefs::TRASH_ORIGINAL ) );
    546 
    547547    hig->addSectionDivider( );
    548     hig->addSectionTitle( tr( "Downloading" ) );
    549 
    550         hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) );
    551 
    552         b = myDestinationButton = new QPushButton;
     548    hig->addSectionTitle( tr( "Seeding Limits" ) );
     549
     550        l = checkBoxNew( tr( "Stop seeding at &ratio:" ), Prefs::RATIO_ENABLED );
     551        r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 );
     552        hig->addRow( l, r );
     553        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
     554
     555        l = checkBoxNew( tr( "Stop seeding if idle for &N minutes:" ), Prefs::IDLE_LIMIT_ENABLED );
     556        r = spinBoxNew( Prefs::IDLE_LIMIT, 1, INT_MAX, 5 );
     557        hig->addRow( l, r );
     558        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
     559
     560    hig->finish( );
     561    return hig;
     562}
     563
     564QWidget *
     565PrefsDialog :: createDownloadTab( )
     566{
     567    const int iconSize( style( )->pixelMetric( QStyle :: PM_SmallIconSize ) );
     568    const QFileIconProvider iconProvider;
     569    const QIcon folderIcon = iconProvider.icon( QFileIconProvider::Folder );
     570    const QPixmap folderPixmap = folderIcon.pixmap( iconSize );
     571    const QIcon fileIcon = iconProvider.icon( QFileIconProvider::File );
     572    const QPixmap filePixmap = fileIcon.pixmap( iconSize );
     573
     574    QWidget *l;
     575    HIG * hig = new HIG( this );
     576    hig->addSectionTitle( tr( "Location" ) );
     577
     578        QPushButton * b = myDestinationButton = new QPushButton;
    553579        b->setIcon( folderPixmap );
    554580        b->setStyleSheet( "text-align: left; padding-left: 5; padding-right: 5" );
    555581        connect( b, SIGNAL(clicked(bool)), this, SLOT(onDestinationClicked(void)) );
    556582        hig->addRow( tr( "Save to &Location:" ), b );
     583
     584    hig->addSectionDivider( );
     585    hig->addSectionTitle( tr( "Queue" ) );
     586   
     587        hig->addRow( tr( "Maximum active &downloads:" ), spinBoxNew( Prefs::DOWNLOAD_QUEUE_SIZE, 1, FD_SETSIZE, 5 ) );
     588        hig->addRow( tr( "E&xempt torrents if idle for N minutes:" ), spinBoxNew( Prefs::QUEUE_STALLED_MINUTES, 1, FD_SETSIZE, 5 ) );
     589
     590    hig->addSectionDivider( );
     591    hig->addSectionTitle( tr( "Incomplete" ) );
     592
     593        hig->addWideControl( checkBoxNew( tr( "Append \".&part\" to incomplete files' names" ), Prefs::RENAME_PARTIAL_FILES ) );
    557594
    558595        l = myIncompleteCheckbox = checkBoxNew( tr( "Keep &incomplete files in:" ), Prefs::INCOMPLETE_DIR_ENABLED );
     
    572609        enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), b );
    573610
    574     hig->addSectionDivider( );
    575     hig->addSectionTitle( tr( "Seeding Limits" ) );
    576 
    577         l = checkBoxNew( tr( "Stop seeding at &ratio:" ), Prefs::RATIO_ENABLED );
    578         r = doubleSpinBoxNew( Prefs::RATIO, 0, INT_MAX, 0.5, 2 );
    579         hig->addRow( l, r );
    580         enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
    581 
    582         l = checkBoxNew( tr( "Stop seeding if idle for &N minutes:" ), Prefs::IDLE_LIMIT_ENABLED );
    583         r = spinBoxNew( Prefs::IDLE_LIMIT, 1, INT_MAX, 5 );
    584         hig->addRow( l, r );
    585         enableBuddyWhenChecked( qobject_cast<QCheckBox*>(l), r );
    586 
    587611    hig->finish( );
    588612    return hig;
     
    604628    QTabWidget * t = new QTabWidget( this );
    605629    t->addTab( createTorrentsTab( ),     tr( "Torrents" ) );
     630    t->addTab( createDownloadTab( ),     tr( "Download" ) );
    606631    t->addTab( createSpeedTab( ),        tr( "Speed" ) );
    607632    t->addTab( createPrivacyTab( ),      tr( "Privacy" ) );
  • trunk/qt/prefs-dialog.h

    r11452 r12607  
    7979        bool isAllowed( int key ) const;
    8080        QWidget * createTorrentsTab( );
     81        QWidget * createDownloadTab( );
    8182        QWidget * createSpeedTab( );
    8283        QWidget * createPrivacyTab( );
  • trunk/qt/prefs.cc

    r12518 r12607  
    8080    { DSPEED_ENABLED, TR_PREFS_KEY_DSPEED_ENABLED, QVariant::Bool },
    8181    { DOWNLOAD_DIR, TR_PREFS_KEY_DOWNLOAD_DIR, QVariant::String },
     82    { DOWNLOAD_QUEUE_ENABLED, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED, QVariant::Bool },
     83    { DOWNLOAD_QUEUE_SIZE, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE, QVariant::Int },
    8284    { ENCRYPTION, TR_PREFS_KEY_ENCRYPTION, QVariant::Int },
    8385    { IDLE_LIMIT, TR_PREFS_KEY_IDLE_LIMIT, QVariant::Int },
     
    9294    { PEER_PORT_RANDOM_LOW, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW, QVariant::Int },
    9395    { PEER_PORT_RANDOM_HIGH, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH, QVariant::Int },
     96    { QUEUE_STALLED_MINUTES, TR_PREFS_KEY_QUEUE_STALLED_MINUTES, QVariant::Int },
    9497    { SCRIPT_TORRENT_DONE_ENABLED, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED, QVariant::Bool },
    9598    { SCRIPT_TORRENT_DONE_FILENAME, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME, QVariant::String },
  • trunk/qt/prefs.h

    r12518 r12607  
    8585            DSPEED_ENABLED,
    8686            DOWNLOAD_DIR,
     87            DOWNLOAD_QUEUE_ENABLED,
     88            DOWNLOAD_QUEUE_SIZE,
    8789            ENCRYPTION,
    8890            IDLE_LIMIT,
     
    9799            PEER_PORT_RANDOM_LOW,
    98100            PEER_PORT_RANDOM_HIGH,
     101            QUEUE_STALLED_MINUTES,
    99102            SCRIPT_TORRENT_DONE_ENABLED,
    100103            SCRIPT_TORRENT_DONE_FILENAME,
  • trunk/qt/session.cc

    r12461 r12607  
    152152        case Prefs :: DHT_ENABLED:
    153153        case Prefs :: DOWNLOAD_DIR:
     154        case Prefs :: DOWNLOAD_QUEUE_ENABLED:
     155        case Prefs :: DOWNLOAD_QUEUE_SIZE:
    154156        case Prefs :: DSPEED:
    155157        case Prefs :: DSPEED_ENABLED:
     
    537539}
    538540
    539 void
    540 Session :: pauseTorrents( const QSet<int>& ids )
    541 {
    542     sendTorrentRequest( "torrent-stop", ids );
    543 }
    544 
    545 void
    546 Session :: startTorrents( const QSet<int>& ids )
    547 {
    548     sendTorrentRequest( "torrent-start", ids );
    549 }
     541void Session :: pauseTorrents    ( const QSet<int>& ids ) { sendTorrentRequest( "torrent-stop", ids ); }
     542void Session :: startTorrents    ( const QSet<int>& ids ) { sendTorrentRequest( "torrent-start", ids ); }
     543void Session :: startTorrentsNow ( const QSet<int>& ids ) { sendTorrentRequest( "torrent-start-now", ids ); }
     544void Session :: queueMoveTop     ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-top", ids ); }
     545void Session :: queueMoveUp      ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-up", ids ); }
     546void Session :: queueMoveDown    ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-down", ids ); }
     547void Session :: queueMoveBottom  ( const QSet<int>& ids ) { sendTorrentRequest( "queue-move-bottom", ids ); }
    550548
    551549void
  • trunk/qt/session.h

    r11616 r12607  
    106106        void pauseTorrents( const QSet<int>& torrentIds = QSet<int>() );
    107107        void startTorrents( const QSet<int>& torrentIds = QSet<int>() );
     108        void startTorrentsNow( const QSet<int>& torrentIds = QSet<int>() );
     109        void queueMoveTop( const QSet<int>& torrentIds = QSet<int>() );
     110        void queueMoveUp( const QSet<int>& torrentIds = QSet<int>() );
     111        void queueMoveDown( const QSet<int>& torrentIds = QSet<int>() );
     112        void queueMoveBottom( const QSet<int>& torrentIds = QSet<int>() );
    108113        void refreshSessionInfo( );
    109114        void refreshSessionStats( );
  • trunk/qt/torrent-filter.cc

    r11519 r12607  
    102102            if( !val ) val = compare( a->hasError(), b->hasError() );
    103103            if( !val ) val = compare( a->getActivity(), b->getActivity() );
     104            if( !val ) val = a->compareQueue( *b );
    104105            // fall through
    105106        case SortMode :: SORT_BY_PROGRESS:
    106107            if( !val ) val = compare( a->percentComplete(), b->percentComplete() );
    107108            if( !val ) val = a->compareSeedRatio( *b );
    108             // fall through
     109            if( !val ) val = a->compareQueue( *b );
    109110        case SortMode :: SORT_BY_RATIO:
    110111            if( !val ) val = a->compareRatio( *b );
     
    145146            break;
    146147        case FilterMode::SHOW_DOWNLOADING:
    147             accepts = tor->isDownloading( );
     148            accepts = tor->isDownloading( ) || tor->isWaitingToDownload( );
    148149            break;
    149150        case FilterMode::SHOW_SEEDING:
    150             accepts = tor->isSeeding( );
     151            accepts = tor->isSeeding( ) || tor->isWaitingToSeed( );
    151152            break;
    152153        case FilterMode::SHOW_PAUSED:
     
    155156        case FilterMode::SHOW_FINISHED:
    156157            accepts = tor->isFinished( );
    157             break;
    158         case FilterMode::SHOW_QUEUED:
    159             accepts = tor->isWaitingToVerify( );
    160158            break;
    161159        case FilterMode::SHOW_VERIFYING:
  • trunk/qt/torrent.cc

    r12595 r12607  
    108108    { PEERS, "peers", TrTypes::PeerList, STAT_EXTRA },
    109109    { TORRENT_FILE, "torrentFile", QVariant::String, STAT_EXTRA },
    110     { BANDWIDTH_PRIORITY, "bandwidthPriority", QVariant::Int, STAT_EXTRA }
     110    { BANDWIDTH_PRIORITY, "bandwidthPriority", QVariant::Int, STAT_EXTRA },
     111    { QUEUE_POSITION, "queuePosition", QVariant::Int, STAT }
    111112};
    112113
     
    367368            return true;
    368369    return false;
     370}
     371
     372int
     373Torrent :: compareQueue( const Torrent& that ) const
     374{
     375    const bool a_is_queued = isQueued( );
     376    const bool b_is_queued = that.isQueued( );
     377
     378    if( a_is_queued != b_is_queued )
     379        return a_is_queued ? -1 : 1;
     380
     381    return that.queuePosition() - queuePosition();
    369382}
    370383
     
    702715    switch( getActivity( ) )
    703716    {
    704         case TR_STATUS_CHECK_WAIT: str = tr( "Waiting to verify local data" ); break;
    705         case TR_STATUS_CHECK:      str = tr( "Verifying local data" ); break;
    706         case TR_STATUS_DOWNLOAD:   str = tr( "Downloading" ); break;
    707         case TR_STATUS_SEED:       str = tr( "Seeding" ); break;
    708         case TR_STATUS_STOPPED:    str = isFinished() ? tr( "Finished" ): tr( "Paused" ); break;
     717        case TR_STATUS_STOPPED:       str = isFinished() ? tr( "Finished" ): tr( "Paused" ); break;
     718        case TR_STATUS_CHECK_WAIT:    str = tr( "Waiting to verify local data" ); break;
     719        case TR_STATUS_CHECK:         str = tr( "Verifying local data" ); break;
     720        case TR_STATUS_DOWNLOAD_WAIT: str = tr( "Download queue #%1" ).arg( queuePosition() + 1 ); break;
     721        case TR_STATUS_DOWNLOAD:      str = tr( "Downloading" );
     722        case TR_STATUS_SEED_WAIT:     str = tr( "Seed queue #%1" ).arg( queuePosition() + 1 ); break;
     723        case TR_STATUS_SEED:          str = tr( "Seeding" ); break;
    709724    }
    710725
  • trunk/qt/torrent.h

    r12595 r12607  
    173173            TORRENT_FILE,
    174174            BANDWIDTH_PRIORITY,
     175            QUEUE_POSITION,
    175176
    176177            PROPERTY_COUNT
     
    272273        int compareSeedRatio( const Torrent& ) const;
    273274        int compareRatio( const Torrent& ) const;
     275        int compareQueue( const Torrent& ) const;
    274276        int compareETA( const Torrent& ) const;
    275277        bool hasETA( ) const { return getETA( ) >= 0; }
     
    305307        PeerList peers( ) const{ return myValues[PEERS].value<PeerList>(); }
    306308        const FileList& files( ) const { return myFiles; }
     309        int queuePosition( ) const { return getInt( QUEUE_POSITION ); }
     310        bool isQueued( ) const { return queuePosition( ) >= 0; }
    307311
    308312    public:
     
    314318        bool isVerifying( ) const { return getActivity( ) == TR_STATUS_CHECK; }
    315319        bool isDownloading( ) const { return getActivity( ) == TR_STATUS_DOWNLOAD; }
     320        bool isWaitingToDownload( ) const { return getActivity( ) == TR_STATUS_DOWNLOAD_WAIT; }
    316321        bool isSeeding( ) const { return getActivity( ) == TR_STATUS_SEED; }
     322        bool isWaitingToSeed( ) const { return getActivity( ) == TR_STATUS_SEED_WAIT; }
    317323        bool isReadyToTransfer( ) const { return getActivity()==TR_STATUS_DOWNLOAD || getActivity()==TR_STATUS_SEED; }
    318324        void notifyComplete( ) const;
  • trunk/web/index.html

    r12495 r12607  
    527527                                                                <li id="sort_by_percent_completed">Progress</li>
    528528                                                                <li id="sort_by_ratio">Ratio</li>
    529                                                                 <li id="sort_by_queue_order">Queue Order</li>
    530529                                                                <li id="sort_by_state">State</li>
    531530                                                                <li class="separator"></li>
     
    544543                <div class="contextMenu" id="torrent_context_menu">
    545544                        <ul>
    546                                 <li id="context_pause_selected" class="disabled context_pause_selected">Pause Selected</li>
    547                                 <li id="context_resume_selected" class="disabled context_resume_selected">Resume Selected</li>
     545                                <li id="context_pause_selected" class="disabled context_pause_selected">Pause</li>
     546                                <li id="context_resume_selected" class="disabled context_resume_selected">Resume</li>
     547                                <li id="context_resume_now_selected" class="disabled context_resume_selected">Resume Now</li>
    548548                                <li class="separator"></li>
    549549                                <li id="context_remove">Remove From List...</li>
  • trunk/web/javascript/common.js

    r12495 r12607  
    233233Prefs._SortByAge          = 'age';
    234234Prefs._SortByActivity     = 'activity';
    235 Prefs._SortByQueue        = 'queue_order';
    236235Prefs._SortByName         = 'name';
    237236Prefs._SortByProgress     = 'percent_completed';
  • trunk/web/javascript/torrent.js

    r12495 r12607  
    1212
    1313// Constants
     14Torrent._StatusStopped         = 0; /* torrent is stopped */
     15Torrent._StatusCheckWait       = 1; /* waiting in queue to check files */
     16Torrent._StatusCheck           = 2; /* checking files */
     17Torrent._StatusDownloadWait    = 3; /* queued to download */
     18Torrent._StatusDownload        = 4; /* downloading */
     19Torrent._StatusSeedWait        = 5; /* queeud to seed */
     20Torrent._StatusSeed            = 6; /* seeding */
     21
     22/*
    1423Torrent._StatusWaitingToCheck  = 1;
    1524Torrent._StatusChecking        = 2;
    1625Torrent._StatusDownloading     = 4;
    1726Torrent._StatusSeeding         = 8;
    18 Torrent._StatusPaused          = 16;
     27*/
     28
    1929Torrent._InfiniteTimeRemaining = 215784000; // 999 Hours - may as well be infinite
    2030
     
    2838Torrent._ErrLocalError         = 3;
    2939
    30 Torrent._TrackerInactive         = 0;
    31 Torrent._TrackerWaiting          = 1;
    32 Torrent._TrackerQueued           = 2;
    33 Torrent._TrackerActive           = 3;
     40Torrent._TrackerInactive       = 0;
     41Torrent._TrackerWaiting        = 1;
     42Torrent._TrackerQueued         = 2;
     43Torrent._TrackerActive         = 3;
    3444
    3545
     
    4050
    4151Torrent._DynamicFields = [ 'downloadedEver', 'error', 'errorString', 'eta',
    42     'haveUnchecked', 'haveValid', 'leftUntilDone', 'metadataPercentComplete', 'peers',
    43     'peersConnected', 'peersGettingFromUs', 'peersSendingToUs', 'rateDownload', 'rateUpload',
    44     'recheckProgress', 'sizeWhenDone', 'status', 'trackerStats', 'desiredAvailable',
    45     'uploadedEver', 'uploadRatio', 'seedRatioLimit', 'seedRatioMode', 'downloadDir', 'isFinished' ]
     52    'haveUnchecked', 'haveValid', 'leftUntilDone', 'metadataPercentComplete',
     53    'peers', 'peersConnected', 'peersGettingFromUs', 'peersSendingToUs',
     54    'queuePosition', 'rateDownload', 'rateUpload', 'recheckProgress',
     55    'sizeWhenDone', 'status', 'trackerStats', 'desiredAvailable',
     56    'uploadedEver', 'uploadRatio', 'seedRatioLimit', 'seedRatioMode',
     57    'downloadDir', 'isFinished' ]
    4658
    4759Torrent.prototype =
     
    234246                                         || this.peersSendingToUs() > 0
    235247                                         || this.webseedsSendingToUs() > 0
    236                                          || this.state() == Torrent._StatusChecking; },
    237         isActive: function() { return this.state() != Torrent._StatusPaused; },
    238         isDownloading: function() { return this.state() == Torrent._StatusDownloading; },
     248                                         || this.state() == Torrent._StatusCheck; },
     249        isActive: function() { return this.state() != Torrent._StatusStopped; },
     250        isDownloading: function() { return this.state() == Torrent._StatusDownload; },
    239251        isFinished: function() { return this._isFinishedSeeding; },
    240         isSeeding: function() { return this.state() == Torrent._StatusSeeding; },
     252        isSeeding: function() { return this.state() == Torrent._StatusSeed; },
    241253        name: function() { return this._name; },
     254        queuePosition: function() { return this._queue_position; },
     255        isQueued: function() { return this.queuePosition() >= 0; },
    242256        webseedsSendingToUs: function() { return this._webseeds_sending_to_us; },
    243257        peersSendingToUs: function() { return this._peers_sending_to_us; },
     
    256270        stateStr: function() {
    257271                switch( this.state() ) {
    258                         case Torrent._StatusSeeding:        return 'Seeding';
    259                         case Torrent._StatusDownloading:    return 'Downloading';
    260                         case Torrent._StatusPaused:         return this.isFinished() ? 'Seeding complete' : 'Paused';
    261                         case Torrent._StatusChecking:       return 'Verifying local data';
    262                         case Torrent._StatusWaitingToCheck: return 'Waiting to verify';
     272                        case Torrent._StatusStopped:        return this.isFinished() ? 'Seeding complete' : 'Paused';
     273                        case Torrent._StatusCheckWait:      return 'Waiting to verify local data';
     274                        case Torrent._StatusCheck:          return 'Verifying local data';
     275                        case Torrent._StatusDownloadWait:   return 'Waiting to download #' + (this.queuePosition()+1);
     276                        case Torrent._StatusDownload:       return 'Downloading';
     277                        case Torrent._StatusSeedWait:       return 'Waiting to seed #' + (this.queuePosition()+1);
     278                        case Torrent._StatusSeed:           return 'Seeding';
    263279                        default:                            return 'error';
    264280                }
     
    398414                this._peers_getting_from_us   = data.peersGettingFromUs;
    399415                this._peers_sending_to_us     = data.peersSendingToUs;
     416                this._queue_position          = data.queuePosition;
    400417                this._webseeds_sending_to_us  = data.webseedsSendingToUs;
    401418                this._sizeWhenDone            = data.sizeWhenDone;
     
    456473                switch( st )
    457474                {
    458                         case Torrent._StatusPaused:
    459                         case Torrent._StatusWaitingToCheck:
     475                        case Torrent._StatusStopped:
     476                        case Torrent._StatusCheckWait:
     477                        case Torrent._StatusDownloadWait:
     478                        case Torrent._StatusSeedWait:
    460479                                c = this.stateStr( );
    461480                                break;
    462481
    463                         case Torrent._StatusDownloading:
     482                        case Torrent._StatusDownload:
    464483                                var a = [ ];
    465484                                if(!compact_mode)
     
    469488                                break;
    470489
    471                         case Torrent._StatusSeeding:
     490                        case Torrent._StatusSeed:
    472491                                if(compact_mode){
    473492                                        c = this.formatUL();
     
    478497                                break;
    479498
    480                         case Torrent._StatusChecking:
     499                        case Torrent._StatusCheck:
    481500                                // 'Verifying local data (40% tested)'
    482501                                c = [ 'Verifying local data (', Transmission.fmt.percentString( 100.0 * this._recheckProgress ), '% tested)' ].join('');
     
    648667                // Update the peer details and pause/resume button
    649668                e = root._pause_resume_button_image;
    650                 if ( this.state() === Torrent._StatusPaused ) {
     669                if ( this.state() === Torrent._StatusStopped ) {
    651670                        e.alt = 'Resume';
    652671                        e.className = "torrent_resume"+compact;
     
    702721        {
    703722                var pass = false;
     723                var s = this.state( );
    704724
    705725                switch( filter )
     
    709729                                break;
    710730                        case Prefs._FilterSeeding:
    711                                 pass = this.isSeeding();
     731                                pass = ( s == Torrent._StatusSeed ) || ( s == Torrent._StatusSeedWait );
    712732                                break;
    713733                        case Prefs._FilterDownloading:
    714                                 pass = this.isDownloading();
     734                                pass = ( s == Torrent._StatusDownload ) || ( s == Torrent._StatusDownloadWait );
    715735                                break;
    716736                        case Prefs._FilterPaused:
     
    741761
    742762/** Helper function for sortTorrents(). */
    743 Torrent.compareByAge = function( a, b ) {
    744         return a.dateAdded() - b.dateAdded();
     763Torrent.compareByName = function( a, b ) {
     764        var i = a._name_lc.compareTo( b._name_lc );
     765        if( i )
     766                return i;
     767        return Torrent.compareById( a, b );
    745768};
    746769
    747770/** Helper function for sortTorrents(). */
    748 Torrent.compareByName = function( a, b ) {
    749         return a._name_lc.compareTo( b._name_lc );
     771Torrent.compareByQueue = function( a, b )
     772{
     773        var a_is_queued = a.isQueued( );
     774        var b_is_queued = b.isQueued( );
     775        if( a_is_queued != b_is_queued )
     776                return a_is_queued ? -1 : 1;
     777
     778        var a_pos = a.queuePosition( );
     779        var b_pos = b.queuePosition( );
     780        if( a_pos != b_pos )
     781                return a_pos - b_pos;
     782
     783        return Torrent.compareByName( a, b );
    750784};
    751785
    752786/** Helper function for sortTorrents(). */
    753 Torrent.compareByState = function( a, b ) {
    754         return a.state() - b.state();
     787Torrent.compareByAge = function( a, b )
     788{
     789        var a_age = a.dateAdded();
     790        var b_age = b.dateAdded();
     791        if( a_age != b_age )
     792                return a_age - b_age;
     793
     794        return Torrent.compareByQueue( a, b );
    755795};
    756796
    757797/** Helper function for sortTorrents(). */
    758 Torrent.compareByActivity = function( a, b ) {
    759         return a.activity() - b.activity();
     798Torrent.compareByState = function( a, b )
     799{
     800        var a_state = a.state( );
     801        var b_state = b.state( );
     802        if( a_state != b_state )
     803                return b_state - a_state;
     804
     805        return Torrent.compareByQueue( a, b );
     806};
     807
     808/** Helper function for sortTorrents(). */
     809Torrent.compareByActivity = function( a, b )
     810{
     811        var a_activity = a.activity( );
     812        var b_activity = b.activity( );
     813        if( a_activity != b_activity )
     814                return a_activity - b_activity;
     815
     816        return Torrent.compareByState( a, b );
    760817};
    761818
     
    764821        var a_ratio = Math.ratio( a._upload_total, a._download_total );
    765822        var b_ratio = Math.ratio( b._upload_total, b._download_total );
    766         return a_ratio - b_ratio;
    767 };
    768 
    769 /** Helper function for sortTorrents(). */
     823        if( a_ratio != b_ratio )
     824                return a_ratio - b_ratio;
     825        return Torrent.compareByState( a, b );
     826};
     827
    770828Torrent.compareByProgress = function( a, b ) {
    771829        if( a.getPercentDone() !== b.getPercentDone() )
    772830                return a.getPercentDone() - b.getPercentDone();
    773         return this.compareByRatio( a, b );
     831        return Torrent.compareByRatio( a, b );
    774832};
    775833
     
    788846                case Prefs._SortByAge:
    789847                        torrents.sort( this.compareByAge );
    790                         break;
    791                 case Prefs._SortByQueue:
    792                         torrents.sort( this.compareById );
    793848                        break;
    794849                case Prefs._SortByProgress:
  • trunk/web/javascript/transmission.js

    r12573 r12607  
    101101                this._context_pause_button     = $('li#context_pause_selected')[0];
    102102                this._context_start_button     = $('li#context_resume_selected')[0];
     103                this._context_start_now_button = $('li#context_resume_now_selected')[0];
    103104
    104105                var ti = '#torrent_inspector_';
     
    282283        },
    283284        contextStartSelected: function( ) {
    284                 this.startSelectedTorrents( );
     285                this.startSelectedTorrents( false );
     286        },
     287        contextStartNowSelected: function( ) {
     288                this.startSelectedTorrents( true );
    285289        },
    286290        contextRemoveSelected: function( ) {
     
    312316                var tr = this;
    313317                var bindings = {
    314                         context_pause_selected:    function(e){ tr.contextStopSelected(e); },
    315                         context_resume_selected:   function(e){ tr.contextStartSelected(e); },
    316                         context_remove:            function(e){ tr.contextRemoveSelected(e); },
    317                         context_removedata:        function(e){ tr.contextRemoveDataSelected(e); },
    318                         context_verify:            function(e){ tr.contextVerifySelected(e); },
    319                         context_reannounce:        function(e){ tr.contextReannounceSelected(e); },
    320                         context_toggle_inspector:  function(e){ tr.contextToggleInspector(e); },
    321                         context_select_all:        function(e){ tr.contextSelectAll(e); },
    322                         context_deselect_all:      function(e){ tr.contextDeselectAll(e); }
     318                        context_pause_selected:       function(e){ tr.contextStopSelected(e); },
     319                        context_resume_selected:      function(e){ tr.contextStartSelected(e); },
     320                        context_resume_now_selected:  function(e){ tr.contextStartNowSelected(e); },
     321                        context_remove:               function(e){ tr.contextRemoveSelected(e); },
     322                        context_removedata:           function(e){ tr.contextRemoveDataSelected(e); },
     323                        context_verify:               function(e){ tr.contextVerifySelected(e); },
     324                        context_reannounce:           function(e){ tr.contextReannounceSelected(e); },
     325                        context_toggle_inspector:     function(e){ tr.contextToggleInspector(e); },
     326                        context_select_all:           function(e){ tr.contextSelectAll(e); },
     327                        context_deselect_all:         function(e){ tr.contextDeselectAll(e); }
    323328                };
    324329
     
    619624                var tr = this;
    620625                if( tr.isButtonEnabled( event ) ) {
    621                         tr.startSelectedTorrents( );
     626                        tr.startSelectedTorrents( false );
    622627                        tr.hideiPhoneAddressbar( );
    623628                }
     
    19952000        },
    19962001
    1997         startSelectedTorrents: function( ) {
    1998                 this.startTorrents( this.getSelectedTorrents( ) );
     2002        startSelectedTorrents: function( force ) {
     2003                this.startTorrents( this.getSelectedTorrents( ), force );
    19992004        },
    20002005        startAllTorrents: function( ) {
    2001                 this.startTorrents( this.getAllTorrents( ) );
     2006                this.startTorrents( this.getAllTorrents( ), false );
    20022007        },
    20032008        startTorrent: function( torrent ) {
    2004                 this.startTorrents( [ torrent ] );
    2005         },
    2006         startTorrents: function( torrents ) {
     2009                this.startTorrents( [ torrent ], false );
     2010        },
     2011        startTorrents: function( torrents, force ) {
    20072012                var torrent_ids = jQuery.map(torrents, function(t) { return t.id(); } );
    20082013                var tr = this;
    2009                 this.remote.startTorrents( torrent_ids, function(){ tr.refreshTorrents(torrent_ids) } );
     2014                this.remote.startTorrents( torrent_ids, force, function(){ tr.refreshTorrents(torrent_ids) } );
    20102015        },
    20112016        verifyTorrent: function( torrent ) {
     
    21382143                        this.setEnabled( this._toolbar_start_button, havePausedSelection );
    21392144                        this.setEnabled( this._context_start_button, havePausedSelection );
     2145                        this.setEnabled( this._context_start_now_button, havePausedSelection );
    21402146                        this.setEnabled( this._toolbar_remove_button, haveSelection );
    21412147                        this.setEnabled( this._toolbar_pause_all_button, haveActive );
  • trunk/web/javascript/transmission.remote.js

    r12501 r12607  
    2929RPC._TurtleTimeEnd          = 'alt-speed-time-end';
    3030RPC._TurtleTimeDay          = 'alt-speed-time-day';
    31 RPC._PeerLimitGlobal            = 'peer-limit-global';
    32 RPC._PeerLimitPerTorrent        = 'peer-limit-per-torrent';
    33 RPC._PexEnabled                         = 'pex-enabled';
    34 RPC._DhtEnabled                         = 'dht-enabled';
    35 RPC._LpdEnabled                         = 'lpd-enabled';
    36 RPC._BlocklistEnabled           = 'blocklist-enabled';
    37 RPC._BlocklistURL                       = 'blocklist-url';
    38 RPC._BlocklistSize                      = 'blocklist-size';
    39 RPC._UtpEnabled                         = 'utp-enabled';
    40 RPC._PeerPortRandom                     = 'peer-port-random-on-start';
    41 RPC._PortForwardingEnabled      = 'port-forwarding-enabled';
     31RPC._PeerLimitGlobal        = 'peer-limit-global';
     32RPC._PeerLimitPerTorrent    = 'peer-limit-per-torrent';
     33RPC._PexEnabled             = 'pex-enabled';
     34RPC._DhtEnabled             = 'dht-enabled';
     35RPC._LpdEnabled             = 'lpd-enabled';
     36RPC._BlocklistEnabled       = 'blocklist-enabled';
     37RPC._BlocklistURL           = 'blocklist-url';
     38RPC._BlocklistSize          = 'blocklist-size';
     39RPC._UtpEnabled             = 'utp-enabled';
     40RPC._PeerPortRandom         = 'peer-port-random-on-start';
     41RPC._PortForwardingEnabled  = 'port-forwarding-enabled';
    4242RPC._StartAddedTorrent      = 'start-added-torrents';
    4343
     
    216216        },
    217217
    218         startTorrents: function( torrent_ids, callback ) {
    219                 this.sendTorrentActionRequests( 'torrent-start', torrent_ids, callback );
     218        startTorrents: function( torrent_ids, noqueue, callback ) {
     219                var name = noqueue ? 'torrent-start-now' : 'torrent-start';
     220                this.sendTorrentActionRequests( name, torrent_ids, callback );
    220221        },
    221222        stopTorrents: function( torrent_ids, callback ) {
Note: See TracChangeset for help on using the changeset viewer.