Changeset 3434


Ignore:
Timestamp:
Oct 16, 2007, 2:16:01 PM (14 years ago)
Author:
charles
Message:

make upload speed a secondary sort key when sorting by progress.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/tr_core.c

    r3426 r3434  
    4040
    4141static void
    42 tr_core_init( GTypeInstance * instance, gpointer g_class );
    43 static void
    44 tr_core_class_init( gpointer g_class, gpointer g_class_data );
    45 static void
    46 tr_core_marshal_err( GClosure * closure, GValue * ret, guint count,
    47                      const GValue * vals, gpointer hint, gpointer marshal );
    48 void
    49 tr_core_marshal_prompt( GClosure * closure, GValue * ret, guint count,
    50                         const GValue * vals, gpointer hint, gpointer marshal );
    51 void
    52 tr_core_marshal_data( GClosure * closure, GValue * ret, guint count,
    53                       const GValue * vals, gpointer hint, gpointer marshal );
    54 static void
    55 tr_core_dispose( GObject * obj );
    56 static void
    57 tr_core_insert( TrCore * self, TrTorrent * tor );
    58 static void
    59 tr_core_errsig( TrCore * self, enum tr_core_err type, const char * msg );
    60 
    61 GType
    62 tr_core_get_type( void )
    63 {
    64     static GType type = 0;
    65 
    66     if( 0 == type )
    67     {
    68         static const GTypeInfo info =
    69         {
    70             sizeof( TrCoreClass ),
    71             NULL,                       /* base_init */
    72             NULL,                       /* base_finalize */
    73             tr_core_class_init,         /* class_init */
    74             NULL,                       /* class_finalize */
    75             NULL,                       /* class_data */
    76             sizeof( TrCore ),
    77             0,                          /* n_preallocs */
    78             tr_core_init,               /* instance_init */
    79             NULL,
    80         };
    81         type = g_type_register_static( G_TYPE_OBJECT, "TrCore", &info, 0 );
    82     }
    83 
    84     return type;
    85 }
    86 
    87 void
     42tr_core_marshal_err( GClosure * closure, GValue * ret SHUTUP, guint count,
     43                     const GValue * vals, gpointer hint SHUTUP,
     44                     gpointer marshal )
     45{
     46    typedef void (*TRMarshalErr)
     47        ( gpointer, enum tr_core_err, const char *, gpointer );
     48    TRMarshalErr     callback;
     49    GCClosure      * cclosure = (GCClosure*) closure;
     50    enum tr_core_err errcode;
     51    const char     * errstr;
     52    gpointer         inst, gdata;
     53
     54    g_return_if_fail( 3 == count );
     55
     56    inst    = g_value_peek_pointer( vals );
     57    errcode = g_value_get_int( vals + 1 );
     58    errstr  = g_value_get_string( vals + 2 );
     59    gdata   = closure->data;
     60
     61    callback = (TRMarshalErr) ( NULL == marshal ?
     62                                cclosure->callback : marshal );
     63    callback( inst, errcode, errstr, gdata );
     64}
     65
     66static void
     67tr_core_marshal_prompt( GClosure * closure, GValue * ret SHUTUP, guint count,
     68                        const GValue * vals, gpointer hint SHUTUP,
     69                        gpointer marshal )
     70{
     71    typedef void (*TRMarshalPrompt)
     72        ( gpointer, GList *, enum tr_torrent_action, gboolean, gpointer );
     73    TRMarshalPrompt        callback;
     74    GCClosure            * cclosure = (GCClosure*) closure;
     75    GList                * paths;
     76    enum tr_torrent_action action;
     77    gboolean               paused;
     78    gpointer               inst, gdata;
     79
     80    g_return_if_fail( 4 == count );
     81
     82    inst    = g_value_peek_pointer( vals );
     83    paths   = g_value_get_pointer( vals + 1 );
     84    action  = g_value_get_int( vals + 2 );
     85    paused  = g_value_get_boolean( vals + 3 );
     86    gdata   = closure->data;
     87
     88    callback = (TRMarshalPrompt) ( NULL == marshal ?
     89                                   cclosure->callback : marshal );
     90    callback( inst, paths, action, paused, gdata );
     91}
     92
     93static void
     94tr_core_marshal_data( GClosure * closure, GValue * ret SHUTUP, guint count,
     95                      const GValue * vals, gpointer hint SHUTUP,
     96                      gpointer marshal )
     97{
     98    typedef void (*TRMarshalPrompt)
     99        ( gpointer, uint8_t *, size_t, gboolean, gpointer );
     100    TRMarshalPrompt        callback;
     101    GCClosure            * cclosure = (GCClosure*) closure;
     102    uint8_t              * data;
     103    size_t                 size;
     104    gboolean               paused;
     105    gpointer               inst, gdata;
     106
     107    g_return_if_fail( 4 == count );
     108
     109    inst    = g_value_peek_pointer( vals );
     110    data    = (uint8_t *) g_value_get_string( vals + 1 );
     111    size    = g_value_get_uint( vals + 2 );
     112    paused  = g_value_get_boolean( vals + 3 );
     113    gdata   = closure->data;
     114
     115    callback = (TRMarshalPrompt) ( NULL == marshal ?
     116                                   cclosure->callback : marshal );
     117    callback( inst, data, size, paused, gdata );
     118}
     119
     120static void
     121tr_core_dispose( GObject * obj )
     122{
     123    TrCore       * self = (TrCore *) obj;
     124    GObjectClass * parent;
     125    GtkTreeIter    iter;
     126    TrTorrent    * tor;
     127
     128    if( self->disposed )
     129    {
     130        return;
     131    }
     132    self->disposed = TRUE;
     133
     134    pref_save( NULL );
     135
     136#ifdef REFDBG
     137    fprintf( stderr, "core    %p dispose\n", self );
     138#endif
     139
     140    /* sever all remaining torrents in the model */
     141    if( gtk_tree_model_get_iter_first( self->model, &iter ) ) do
     142    {
     143        gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
     144        tr_torrent_sever( tor );
     145        g_object_unref( tor );
     146    }
     147    while( gtk_tree_model_iter_next( self->model, &iter ) );
     148    g_object_unref( self->model );
     149
     150#ifdef REFDBG
     151    fprintf( stderr, "core    %p dead\n", self );
     152#endif
     153
     154    /* close the libtransmission instance */
     155    tr_close( self->handle );
     156
     157    /* Chain up to the parent class */
     158    parent = g_type_class_peek( g_type_parent( TR_CORE_TYPE ) );
     159    parent->dispose( obj );
     160}
     161
     162
     163static void
    88164tr_core_class_init( gpointer g_class, gpointer g_class_data SHUTUP )
    89165{
     
    122198}
    123199
    124 void
    125 tr_core_marshal_err( GClosure * closure, GValue * ret SHUTUP, guint count,
    126                      const GValue * vals, gpointer hint SHUTUP,
    127                      gpointer marshal )
    128 {
    129     typedef void (*TRMarshalErr)
    130         ( gpointer, enum tr_core_err, const char *, gpointer );
    131     TRMarshalErr     callback;
    132     GCClosure      * cclosure = (GCClosure*) closure;
    133     enum tr_core_err errcode;
    134     const char     * errstr;
    135     gpointer         inst, gdata;
    136 
    137     g_return_if_fail( 3 == count );
    138 
    139     inst    = g_value_peek_pointer( vals );
    140     errcode = g_value_get_int( vals + 1 );
    141     errstr  = g_value_get_string( vals + 2 );
    142     gdata   = closure->data;
    143 
    144     callback = (TRMarshalErr) ( NULL == marshal ?
    145                                 cclosure->callback : marshal );
    146     callback( inst, errcode, errstr, gdata );
    147 }
    148 
    149 void
    150 tr_core_marshal_prompt( GClosure * closure, GValue * ret SHUTUP, guint count,
    151                         const GValue * vals, gpointer hint SHUTUP,
    152                         gpointer marshal )
    153 {
    154     typedef void (*TRMarshalPrompt)
    155         ( gpointer, GList *, enum tr_torrent_action, gboolean, gpointer );
    156     TRMarshalPrompt        callback;
    157     GCClosure            * cclosure = (GCClosure*) closure;
    158     GList                * paths;
    159     enum tr_torrent_action action;
    160     gboolean               paused;
    161     gpointer               inst, gdata;
    162 
    163     g_return_if_fail( 4 == count );
    164 
    165     inst    = g_value_peek_pointer( vals );
    166     paths   = g_value_get_pointer( vals + 1 );
    167     action  = g_value_get_int( vals + 2 );
    168     paused  = g_value_get_boolean( vals + 3 );
    169     gdata   = closure->data;
    170 
    171     callback = (TRMarshalPrompt) ( NULL == marshal ?
    172                                    cclosure->callback : marshal );
    173     callback( inst, paths, action, paused, gdata );
    174 }
    175 
    176 void
    177 tr_core_marshal_data( GClosure * closure, GValue * ret SHUTUP, guint count,
    178                       const GValue * vals, gpointer hint SHUTUP,
    179                       gpointer marshal )
    180 {
    181     typedef void (*TRMarshalPrompt)
    182         ( gpointer, uint8_t *, size_t, gboolean, gpointer );
    183     TRMarshalPrompt        callback;
    184     GCClosure            * cclosure = (GCClosure*) closure;
    185     uint8_t              * data;
    186     size_t                 size;
    187     gboolean               paused;
    188     gpointer               inst, gdata;
    189 
    190     g_return_if_fail( 4 == count );
    191 
    192     inst    = g_value_peek_pointer( vals );
    193     data    = (uint8_t *) g_value_get_string( vals + 1 );
    194     size    = g_value_get_uint( vals + 2 );
    195     paused  = g_value_get_boolean( vals + 3 );
    196     gdata   = closure->data;
    197 
    198     callback = (TRMarshalPrompt) ( NULL == marshal ?
    199                                    cclosure->callback : marshal );
    200     callback( inst, data, size, paused, gdata );
    201 }
    202 
    203 void
     200static int
     201compareProgress( GtkTreeModel   * model,
     202                 GtkTreeIter    * a,
     203                 GtkTreeIter    * b,
     204                 gpointer         user_data UNUSED )
     205{
     206    gfloat rateUpA, rateUpB;
     207    gfloat rateDownA, rateDownB;
     208    gfloat percentDoneA, percentDoneB;
     209    int ia, ib;
     210
     211    gtk_tree_model_get( model, a, MC_PROG_D, &percentDoneA,
     212                                  MC_DRATE, &rateDownA,
     213                                  MC_URATE, &rateUpA,
     214                                  -1 );
     215    gtk_tree_model_get( model, b, MC_PROG_D, &percentDoneB,
     216                                  MC_DRATE, &rateDownB,
     217                                  MC_URATE, &rateUpB,
     218                                  -1 );
     219    ia = (int)( 100.0 * percentDoneA );
     220    ib = (int)( 100.0 * percentDoneB );
     221    if( ia != ib )
     222        return ia - ib;
     223
     224    ia = (int)( rateUpA + rateDownA );
     225    ib = (int)( rateUpB + rateDownB );
     226    if( ia != ib )
     227        return ia - ib;
     228
     229    return 0;
     230}
     231
     232static void
    204233tr_core_init( GTypeInstance * instance, gpointer g_class SHUTUP )
    205234{
     
    231260    store = gtk_list_store_newv( MC_ROW_COUNT, types );
    232261
     262    gtk_tree_sortable_set_sort_func( GTK_TREE_SORTABLE(store),
     263                                     MC_PROG_D,
     264                                     compareProgress,
     265                                     NULL, NULL );
     266
    233267    self->model    = GTK_TREE_MODEL( store );
    234268    self->handle   = tr_init( "gtk" );
     
    238272}
    239273
    240 void
    241 tr_core_dispose( GObject * obj )
    242 {
    243     TrCore       * self = (TrCore *) obj;
    244     GObjectClass * parent;
    245     GtkTreeIter    iter;
    246     TrTorrent    * tor;
    247 
    248     if( self->disposed )
    249     {
    250         return;
    251     }
    252     self->disposed = TRUE;
    253 
    254     pref_save( NULL );
    255 
    256 #ifdef REFDBG
    257     fprintf( stderr, "core    %p dispose\n", self );
    258 #endif
    259 
    260     /* sever all remaining torrents in the model */
    261     if( gtk_tree_model_get_iter_first( self->model, &iter ) ) do
    262     {
    263         gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
    264         tr_torrent_sever( tor );
    265         g_object_unref( tor );
    266     }
    267     while( gtk_tree_model_iter_next( self->model, &iter ) );
    268     g_object_unref( self->model );
    269 
    270 #ifdef REFDBG
    271     fprintf( stderr, "core    %p dead\n", self );
    272 #endif
    273 
    274     /* close the libtransmission instance */
    275     tr_close( self->handle );
    276 
    277     /* Chain up to the parent class */
    278     parent = g_type_class_peek( g_type_parent( TR_CORE_TYPE ) );
    279     parent->dispose( obj );
    280 }
     274GType
     275tr_core_get_type( void )
     276{
     277    static GType type = 0;
     278
     279    if( 0 == type )
     280    {
     281        static const GTypeInfo info =
     282        {
     283            sizeof( TrCoreClass ),
     284            NULL,                       /* base_init */
     285            NULL,                       /* base_finalize */
     286            tr_core_class_init,         /* class_init */
     287            NULL,                       /* class_finalize */
     288            NULL,                       /* class_data */
     289            sizeof( TrCore ),
     290            0,                          /* n_preallocs */
     291            tr_core_init,               /* instance_init */
     292            NULL,
     293        };
     294        type = g_type_register_static( G_TYPE_OBJECT, "TrCore", &info, 0 );
     295    }
     296
     297    return type;
     298}
     299
     300/**
     301***
     302**/
    281303
    282304TrCore *
     
    345367}
    346368
    347 int
    348 tr_core_load( TrCore * self, gboolean paused )
    349 {
    350     int i;
    351     int count = 0;
    352     tr_torrent ** torrents;
    353     char * path;
    354 
    355     TR_IS_CORE( self );
    356 
    357     path = getdownloaddir( );
    358 
    359     torrents = tr_loadTorrents ( self->handle, NULL, paused, &count );
    360     for( i=0; i<count; ++i )
    361         tr_core_insert( self, tr_torrent_new_preexisting( torrents[i] ) );
    362     tr_free( torrents );
    363 
    364     g_free( path );
    365     return count;
    366 }
    367 
    368 gboolean
    369 tr_core_add( TrCore * self, const char * path, enum tr_torrent_action act,
    370              gboolean paused )
    371 {
    372     GList * list;
    373     int     ret;
    374 
    375     TR_IS_CORE( self );
    376 
    377     list = g_list_append( NULL, (void *) path );
    378     ret  = tr_core_add_list( self, list, act, paused );
    379     g_list_free( list );
    380 
    381     return 1 == ret;
    382 }
    383 
    384 gboolean
    385 tr_core_add_dir( TrCore * self, const char * path, const char * dir,
    386                  enum tr_torrent_action act, gboolean paused )
    387 {
    388     TrTorrent * tor;
    389     char      * errstr;
    390 
    391     TR_IS_CORE( self );
    392 
    393     errstr = NULL;
    394     tor = tr_torrent_new( self->handle, path, dir, act, paused, &errstr );
    395     if( NULL == tor )
    396     {
    397         tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
    398         g_free( errstr );
    399         return FALSE;
    400     }
    401     g_assert( NULL == errstr );
    402 
    403     tr_core_insert( self, tor );
    404 
    405     return TRUE;
    406 }
    407 
    408 int
    409 tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
    410                   gboolean paused )
    411 {
    412     char * dir;
    413     int count;
    414 
    415     TR_IS_CORE( self );
    416 
    417     if( pref_flag_get( PREF_KEY_DIR_ASK ) )
    418     {
    419         TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
    420         g_signal_emit( self, class->promptsig, 0, paths, act, paused );
    421         return 0;
    422     }
    423 
    424     dir = getdownloaddir();
    425     count = 0;
    426     for( ; paths; paths=paths->next )
    427         if( tr_core_add_dir( self, paths->data, dir, act, paused ) )
    428             count++;
    429 
    430     g_free( dir );
    431     return count;
    432 }
    433 
    434 gboolean
    435 tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused )
    436 {
    437     gboolean ret;
    438     char * path;
    439     TR_IS_CORE( self );
    440 
    441     if( pref_flag_get( PREF_KEY_DIR_ASK ) )
    442     {
    443         TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
    444         g_signal_emit( self, class->promptdatasig, 0, data, size, paused );
    445         return FALSE;
    446     }
    447 
    448     path = getdownloaddir( );
    449     ret = tr_core_add_data_dir( self, data, size, path, paused );
    450     g_free( path );
    451     return ret;
    452 }
    453 
    454 gboolean
    455 tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
    456                       const char * dir, gboolean paused )
    457 {
    458     TrTorrent * tor;
    459     char      * errstr = NULL;
    460 
    461     TR_IS_CORE( self );
    462 
    463     tor = tr_torrent_new_with_data( self->handle, data, size, dir,
    464                                     paused, &errstr );
    465     if( NULL == tor )
    466     {
    467         tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
    468         g_free( errstr );
    469         return FALSE;
    470     }
    471     g_assert( NULL == errstr );
    472 
    473     tr_core_insert( self, tor );
    474 
    475     return TRUE;
    476 }
    477 
    478 void
    479 tr_core_torrents_added( TrCore * self )
    480 {
    481     TR_IS_CORE( self );
    482 
    483     tr_core_update( self );
    484     tr_core_errsig( self, TR_CORE_ERR_NO_MORE_TORRENTS, NULL );
    485 }
    486 
    487 void
    488 tr_core_delete_torrent( TrCore * self, GtkTreeIter * iter )
    489 {
    490     TrTorrent * tor;
    491 
    492     TR_IS_CORE( self );
    493 
    494     gtk_tree_model_get( self->model, iter, MC_TORRENT, &tor, -1 );
    495     gtk_list_store_remove( GTK_LIST_STORE( self->model ), iter );
    496     tr_torrentRemoveSaved( tr_torrent_handle( tor ) );
    497 
    498     tr_torrent_sever( tor );
    499 }
    500 
    501 void
     369static void
    502370tr_core_insert( TrCore * self, TrTorrent * tor )
    503371{
     
    516384    g_object_unref( tor );
    517385    self->nextid++;
     386}
     387
     388int
     389tr_core_load( TrCore * self, gboolean paused )
     390{
     391    int i;
     392    int count = 0;
     393    tr_torrent ** torrents;
     394    char * path;
     395
     396    TR_IS_CORE( self );
     397
     398    path = getdownloaddir( );
     399
     400    torrents = tr_loadTorrents ( self->handle, NULL, paused, &count );
     401    for( i=0; i<count; ++i )
     402        tr_core_insert( self, tr_torrent_new_preexisting( torrents[i] ) );
     403    tr_free( torrents );
     404
     405    g_free( path );
     406    return count;
     407}
     408
     409gboolean
     410tr_core_add( TrCore * self, const char * path, enum tr_torrent_action act,
     411             gboolean paused )
     412{
     413    GList * list;
     414    int     ret;
     415
     416    TR_IS_CORE( self );
     417
     418    list = g_list_append( NULL, (void *) path );
     419    ret  = tr_core_add_list( self, list, act, paused );
     420    g_list_free( list );
     421
     422    return 1 == ret;
     423}
     424
     425static void
     426tr_core_errsig( TrCore * self, enum tr_core_err type, const char * msg )
     427{
     428    TrCoreClass * class;
     429
     430    class = g_type_class_peek( TR_CORE_TYPE );
     431    g_signal_emit( self, class->errsig, 0, type, msg );
     432}
     433
     434gboolean
     435tr_core_add_dir( TrCore * self, const char * path, const char * dir,
     436                 enum tr_torrent_action act, gboolean paused )
     437{
     438    TrTorrent * tor;
     439    char      * errstr;
     440
     441    TR_IS_CORE( self );
     442
     443    errstr = NULL;
     444    tor = tr_torrent_new( self->handle, path, dir, act, paused, &errstr );
     445    if( NULL == tor )
     446    {
     447        tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
     448        g_free( errstr );
     449        return FALSE;
     450    }
     451    g_assert( NULL == errstr );
     452
     453    tr_core_insert( self, tor );
     454
     455    return TRUE;
     456}
     457
     458int
     459tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
     460                  gboolean paused )
     461{
     462    char * dir;
     463    int count;
     464
     465    TR_IS_CORE( self );
     466
     467    if( pref_flag_get( PREF_KEY_DIR_ASK ) )
     468    {
     469        TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
     470        g_signal_emit( self, class->promptsig, 0, paths, act, paused );
     471        return 0;
     472    }
     473
     474    dir = getdownloaddir();
     475    count = 0;
     476    for( ; paths; paths=paths->next )
     477        if( tr_core_add_dir( self, paths->data, dir, act, paused ) )
     478            count++;
     479
     480    g_free( dir );
     481    return count;
     482}
     483
     484gboolean
     485tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused )
     486{
     487    gboolean ret;
     488    char * path;
     489    TR_IS_CORE( self );
     490
     491    if( pref_flag_get( PREF_KEY_DIR_ASK ) )
     492    {
     493        TrCoreClass * class = g_type_class_peek( TR_CORE_TYPE );
     494        g_signal_emit( self, class->promptdatasig, 0, data, size, paused );
     495        return FALSE;
     496    }
     497
     498    path = getdownloaddir( );
     499    ret = tr_core_add_data_dir( self, data, size, path, paused );
     500    g_free( path );
     501    return ret;
     502}
     503
     504gboolean
     505tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
     506                      const char * dir, gboolean paused )
     507{
     508    TrTorrent * tor;
     509    char      * errstr = NULL;
     510
     511    TR_IS_CORE( self );
     512
     513    tor = tr_torrent_new_with_data( self->handle, data, size, dir,
     514                                    paused, &errstr );
     515    if( NULL == tor )
     516    {
     517        tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
     518        g_free( errstr );
     519        return FALSE;
     520    }
     521    g_assert( NULL == errstr );
     522
     523    tr_core_insert( self, tor );
     524
     525    return TRUE;
     526}
     527
     528void
     529tr_core_torrents_added( TrCore * self )
     530{
     531    TR_IS_CORE( self );
     532
     533    tr_core_update( self );
     534    tr_core_errsig( self, TR_CORE_ERR_NO_MORE_TORRENTS, NULL );
     535}
     536
     537void
     538tr_core_delete_torrent( TrCore * self, GtkTreeIter * iter )
     539{
     540    TrTorrent * tor;
     541
     542    TR_IS_CORE( self );
     543
     544    gtk_tree_model_get( self->model, iter, MC_TORRENT, &tor, -1 );
     545    gtk_list_store_remove( GTK_LIST_STORE( self->model ), iter );
     546    tr_torrentRemoveSaved( tr_torrent_handle( tor ) );
     547
     548    tr_torrent_sever( tor );
    518549}
    519550
     
    559590
    560591void
    561 tr_core_errsig( TrCore * self, enum tr_core_err type, const char * msg )
    562 {
    563     TrCoreClass * class;
    564 
    565     class = g_type_class_peek( TR_CORE_TYPE );
    566     g_signal_emit( self, class->errsig, 0, type, msg );
    567 }
    568 
    569 void
    570592tr_core_quit( TrCore * self )
    571593{
Note: See TracChangeset for help on using the changeset viewer.