Changeset 8174


Ignore:
Timestamp:
Apr 7, 2009, 8:13:08 PM (14 years ago)
Author:
charles
Message:

(trunk gtk) use the RPC API for updating the blocklist and for testing the port.

Location:
trunk/gtk
Files:
2 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/gtk/Makefile.am

    r8152 r8174  
    3838    actions.h \
    3939    add-dialog.h \
    40     blocklist.h \
    4140    conf.h \
    4241    details.h \
     
    7271    actions.c \
    7372    add-dialog.c \
    74     blocklist.c \
    7573    conf.c \
    7674    details.c \
  • trunk/gtk/main.c

    r8172 r8174  
    4343#include "actions.h"
    4444#include "add-dialog.h"
    45 #include "blocklist.h"
    4645#include "conf.h"
    4746#include "details.h"
     
    447446        appsetup( win, argfiles, cbdata, startpaused, startminimized );
    448447        tr_sessionSetRPCCallback( session, onRPCChanged, cbdata );
    449         gtr_blocklist_maybe_autoupdate( cbdata->core );
     448
     449        /* on startup, check & see if it's time to update the blocklist */
     450        if( pref_flag_get( PREF_KEY_BLOCKLIST_UPDATES_ENABLED )
     451            && ( time( NULL ) - pref_int_get( "blocklist-date" ) > ( 60 * 60 * 24 * 7 ) ) )
     452                tr_core_blocklist_update( cbdata->core );
    450453
    451454        gtk_main( );
  • trunk/gtk/tr-core.c

    r8122 r8174  
    3535
    3636#include <libtransmission/transmission.h>
     37#include <libtransmission/bencode.h>
     38#include <libtransmission/rpcimpl.h>
     39#include <libtransmission/json.h>
    3740#include <libtransmission/utils.h> /* tr_free */
    3841
     
    97100}
    98101
    99 static void
    100 tr_core_marshal_blocklist( GClosure *     closure,
    101                            GValue * ret   UNUSED,
    102                            guint          count,
    103                            const GValue * vals,
    104                            gpointer hint  UNUSED,
    105                            gpointer       marshal )
    106 {
    107     typedef void ( *TRMarshalErr )
    108                                 ( gpointer, enum tr_core_err, const char *,
    109                                 gpointer );
    110     TRMarshalErr callback;
    111     GCClosure *  cclosure = (GCClosure*) closure;
    112     gboolean     flag;
    113     const char * str;
    114     gpointer     inst, gdata;
    115 
    116     g_return_if_fail( count == 3 );
    117 
    118     inst    = g_value_peek_pointer( vals );
    119     flag    = g_value_get_boolean( vals + 1 );
    120     str     = g_value_get_string( vals + 2 );
    121     gdata   = closure->data;
    122 
    123     callback = (TRMarshalErr)( marshal ? marshal : cclosure->callback );
    124     callback( inst, flag, str, gdata );
    125 }
    126 
    127 static void
    128 tr_core_marshal_prompt( GClosure *     closure,
    129                         GValue * ret   UNUSED,
    130                         guint          count,
    131                         const GValue * vals,
    132                         gpointer hint  UNUSED,
    133                         gpointer       marshal )
    134 {
    135     typedef void ( *TRMarshalPrompt )( gpointer, tr_ctor *, gpointer );
    136     TRMarshalPrompt callback;
    137     GCClosure *     cclosure = (GCClosure*) closure;
    138     gpointer        ctor;
    139     gpointer        inst, gdata;
    140 
    141     g_return_if_fail( count == 2 );
    142 
    143     inst      = g_value_peek_pointer( vals );
    144     ctor      = g_value_peek_pointer( vals + 1 );
    145     gdata     = closure->data;
    146 
    147     callback = (TRMarshalPrompt)( marshal ? marshal : cclosure->callback );
    148     callback( inst, ctor, gdata );
    149 }
    150 
    151102static int
    152103isDisposed( const TrCore * core )
     
    176127{
    177128    GObjectClass * gobject_class;
    178     TrCoreClass *  core_class;
     129    TrCoreClass *  cc;
    179130
    180131    g_type_class_add_private( g_class, sizeof( struct TrCorePrivate ) );
     
    183134    gobject_class->dispose = tr_core_dispose;
    184135
    185 
    186     core_class = TR_CORE_CLASS( g_class );
    187     core_class->blocksig = g_signal_new( "blocklist-status",
    188                                          G_TYPE_FROM_CLASS(
    189                                              g_class ),
    190                                          G_SIGNAL_RUN_LAST, 0, NULL, NULL,
    191                                          tr_core_marshal_blocklist,
    192                                          G_TYPE_NONE,
    193                                          2, G_TYPE_BOOLEAN, G_TYPE_STRING );
    194     core_class->errsig = g_signal_new( "error", G_TYPE_FROM_CLASS( g_class ),
    195                                        G_SIGNAL_RUN_LAST, 0, NULL, NULL,
    196                                        tr_core_marshal_err, G_TYPE_NONE,
    197                                        2, G_TYPE_INT, G_TYPE_STRING );
    198     core_class->promptsig = g_signal_new( "add-torrent-prompt",
    199                                           G_TYPE_FROM_CLASS(
    200                                               g_class ),
    201                                           G_SIGNAL_RUN_LAST, 0, NULL, NULL,
    202                                           tr_core_marshal_prompt,
    203                                           G_TYPE_NONE,
    204                                           1, G_TYPE_POINTER );
    205     core_class->quitsig = g_signal_new( "quit", G_TYPE_FROM_CLASS( g_class ),
    206                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
    207                                         g_cclosure_marshal_VOID__VOID,
    208                                         G_TYPE_NONE, 0 );
    209     core_class->prefsig = g_signal_new( "prefs-changed",
    210                                         G_TYPE_FROM_CLASS( g_class ),
    211                                         G_SIGNAL_RUN_LAST, 0, NULL, NULL,
    212                                         g_cclosure_marshal_VOID__STRING,
    213                                         G_TYPE_NONE, 1, G_TYPE_STRING );
     136    cc = TR_CORE_CLASS( g_class );
     137
     138    cc->blocklistSignal = g_signal_new( "blocklist-updated",          /* name */
     139                                        G_TYPE_FROM_CLASS( g_class ), /* applies to TrCore */
     140                                        G_SIGNAL_RUN_FIRST,           /* when to invoke */
     141                                        0, NULL, NULL,                /* accumulator */
     142                                        g_cclosure_marshal_VOID__INT, /* marshaler */
     143                                        G_TYPE_NONE,                  /* return type */
     144                                        1, G_TYPE_INT );              /* signal arguments */
     145
     146    cc->portSignal = g_signal_new( "port-tested",
     147                                   G_TYPE_FROM_CLASS( g_class ),
     148                                   G_SIGNAL_RUN_LAST,
     149                                   0, NULL, NULL,
     150                                   g_cclosure_marshal_VOID__BOOLEAN,
     151                                   G_TYPE_NONE,
     152                                   1, G_TYPE_BOOLEAN );
     153
     154    cc->errsig = g_signal_new( "error",
     155                               G_TYPE_FROM_CLASS( g_class ),
     156                               G_SIGNAL_RUN_LAST,
     157                               0, NULL, NULL,
     158                               tr_core_marshal_err,
     159                               G_TYPE_NONE,
     160                               2, G_TYPE_INT, G_TYPE_STRING );
     161
     162    cc->promptsig = g_signal_new( "add-torrent-prompt",
     163                                  G_TYPE_FROM_CLASS( g_class ),
     164                                  G_SIGNAL_RUN_LAST,
     165                                  0, NULL, NULL,
     166                                  g_cclosure_marshal_VOID__POINTER,
     167                                  G_TYPE_NONE,
     168                                  1, G_TYPE_POINTER );
     169
     170    cc->quitsig = g_signal_new( "quit",
     171                                G_TYPE_FROM_CLASS( g_class ),
     172                                G_SIGNAL_RUN_LAST,
     173                                0, NULL, NULL,
     174                                g_cclosure_marshal_VOID__VOID,
     175                                G_TYPE_NONE,
     176                                0 );
     177
     178    cc->prefsig = g_signal_new( "prefs-changed",
     179                                G_TYPE_FROM_CLASS( g_class ),
     180                                G_SIGNAL_RUN_LAST,
     181                                0, NULL, NULL,
     182                                g_cclosure_marshal_VOID__STRING,
     183                                G_TYPE_NONE,
     184                                1, G_TYPE_STRING );
    214185
    215186#ifdef HAVE_DBUS_GLIB
     
    887858}
    888859
    889 void
    890 tr_core_blocksig( TrCore *     core,
    891                   gboolean     isDone,
    892                   const char * status )
    893 {
    894     g_signal_emit( core, TR_CORE_GET_CLASS(
    895                        core )->blocksig, 0, isDone, status );
     860static void
     861emitBlocklistUpdated( TrCore * core, int ruleCount )
     862{
     863    g_signal_emit( core, TR_CORE_GET_CLASS( core )->blocklistSignal, 0, ruleCount );
     864}
     865
     866static void
     867emitPortTested( TrCore * core, gboolean isOpen )
     868{
     869    g_signal_emit( core, TR_CORE_GET_CLASS( core )->portSignal, 0, isOpen );
    896870}
    897871
     
    10401014    if( findTorrentInModel( core, id, &iter ) )
    10411015    {
    1042         TrTorrent *    gtor;
     1016        TrTorrent * gtor;
    10431017        GtkTreeModel * model = tr_core_model( core );
    10441018        gtk_tree_model_get( model, &iter, MC_TORRENT, &gtor, -1 );
     
    13371311}
    13381312
     1313/***
     1314****
     1315****  RPC Interface
     1316****
     1317***/
     1318
     1319/* #define DEBUG_RPC */
     1320
     1321static int nextTag = 1;
     1322
     1323typedef void ( server_response_func )( TrCore * core, tr_benc * response, gpointer user_data );
     1324
     1325struct pending_request_data
     1326{
     1327    int tag;
     1328    TrCore * core;
     1329    server_response_func * responseFunc;
     1330    gpointer responseFuncUserData;
     1331};
     1332
     1333static GHashTable * pendingRequests = NULL;
     1334
     1335static gboolean
     1336readResponseIdle( void * vresponse )
     1337{
     1338    GByteArray * response;
     1339    tr_benc top;
     1340    int64_t intVal;
     1341    int tag;
     1342    struct pending_request_data * data;
     1343
     1344    response = vresponse;
     1345    tr_jsonParse( response->data, response->len, &top, NULL );
     1346    tr_bencDictFindInt( &top, "tag", &intVal );
     1347    tag = (int)intVal;
     1348
     1349    data = g_hash_table_lookup( pendingRequests, &tag );
     1350    if( data )
     1351        (*data->responseFunc)(data->core, &top, data->responseFuncUserData );
     1352
     1353    tr_bencFree( &top );
     1354    g_hash_table_remove( pendingRequests, &tag );
     1355    g_byte_array_free( response, TRUE );
     1356    return FALSE;
     1357}
     1358
     1359static void
     1360readResponse( tr_session  * session UNUSED,
     1361              const char  * response,
     1362              size_t        response_len,
     1363              void        * unused UNUSED )
     1364{
     1365    GByteArray * bytes = g_byte_array_new( );
     1366#ifdef DEBUG_RPC
     1367    g_message( "response: [%*.*s]", (int)response_len, (int)response_len, response );
     1368#endif
     1369    g_byte_array_append( bytes, (const uint8_t*)response, response_len );
     1370    g_idle_add( readResponseIdle, bytes );
     1371}
     1372
     1373static void
     1374sendRequest( TrCore * core, const char * json, int tag,
     1375             server_response_func * responseFunc, void * responseFuncUserData )
     1376{
     1377    tr_session * session = tr_core_session( core );
     1378
     1379    if( pendingRequests == NULL )
     1380    {
     1381        pendingRequests = g_hash_table_new_full( g_int_hash, g_int_equal, NULL, g_free );
     1382    }
     1383
     1384    if( session == NULL )
     1385    {
     1386        g_error( "GTK+ client doesn't support connections to remote servers yet." );
     1387    }
     1388    else
     1389    {
     1390        /* remember this request */
     1391        struct pending_request_data * data;
     1392        data = g_new0( struct pending_request_data, 1 );
     1393        data->core = core;
     1394        data->tag = tag;
     1395        data->responseFunc = responseFunc;
     1396        data->responseFuncUserData = responseFuncUserData;
     1397        g_hash_table_insert( pendingRequests, &data->tag, data );
     1398
     1399        /* make the request */
     1400#ifdef DEBUG_RPC
     1401        g_message( "request: [%s]", json );
     1402#endif
     1403        tr_rpc_request_exec_json( session, json, strlen( json ), readResponse, GINT_TO_POINTER(tag) );
     1404    }
     1405}
     1406
     1407/***
     1408****  Sending a test-port request via RPC
     1409***/
     1410
     1411static void
     1412portTestResponseFunc( TrCore * core, tr_benc * response, gpointer userData UNUSED )
     1413{
     1414    tr_benc * args;
     1415    tr_bool isOpen = FALSE;
     1416
     1417    if( tr_bencDictFindDict( response, "arguments", &args ) )
     1418        tr_bencDictFindBool( args, "port-is-open", &isOpen );
     1419
     1420    emitPortTested( core, isOpen );
     1421}
     1422
     1423void
     1424tr_core_port_test( TrCore * core )
     1425{
     1426    char buf[128];
     1427    const int tag = nextTag++;
     1428    g_snprintf( buf, sizeof( buf ), "{ \"method\": \"port-test\", \"tag\": %d }", tag );
     1429    sendRequest( core, buf, tag, portTestResponseFunc, NULL );
     1430}
     1431
     1432/***
     1433****  Updating a blocklist via RPC
     1434***/
     1435
     1436static void
     1437blocklistResponseFunc( TrCore * core, tr_benc * response, gpointer userData UNUSED )
     1438{
     1439    tr_benc * args;
     1440    int64_t ruleCount = 0;
     1441
     1442    if( tr_bencDictFindDict( response, "arguments", &args ) )
     1443        tr_bencDictFindInt( args, "blocklist-size", &ruleCount );
     1444
     1445    if( ruleCount > 0 )
     1446        pref_int_set( "blocklist-date", time( NULL ) );
     1447
     1448    emitBlocklistUpdated( core, ruleCount );
     1449}
     1450
     1451void
     1452tr_core_blocklist_update( TrCore * core )
     1453{
     1454    char buf[128];
     1455    const int tag = nextTag++;
     1456    g_snprintf( buf, sizeof( buf ), "{ \"method\": \"blocklist-update\", \"tag\": %d }", tag );
     1457    sendRequest( core, buf, tag, blocklistResponseFunc, NULL );
     1458}
  • trunk/gtk/tr-core.h

    r7888 r8174  
    6565    GObjectClass    parent;
    6666
    67     /* "blocklist" signal:
    68        void  handler( TrCore *, const char *, gpointer userData ); */
    69     int    blocksig;
    70 
    71     /* "error" signal:
    72        void handler( TrCore *, enum tr_core_err, const char *, gpointer ) */
    73     int    errsig;
    74 
    75     /* "add-torrent-prompt" signal:
    76        void handler( TrCore *, gpointer ctor, gpointer userData )
     67    /* "blocklist-updated" signal with a callback type of
     68        void (*callback )( TrCore*, int ruleCount, gpointer userData ). */
     69    int blocklistSignal;
     70
     71    /* "port-tested" signal with a callback type of
     72       void( *callback )( TrCore*, gboolean isOpen, gpointer userData ). */
     73    int portSignal;
     74
     75    /* "error" signal with a callback type of
     76       void( *callback )( TrCore*, enum tr_core_err, const char * humanReadable, gpointer userData ). */
     77    int errsig;
     78
     79    /* "add-torrent-prompt" signal with a callback type of
     80       void ( *callback)( TrCore *, gpointer ctor, gpointer userData )
    7781       The handler assumes ownership of ctor and must free when done */
    78     int    promptsig;
     82    int promptsig;
    7983
    8084    /* "quit" signal:
    8185       void handler( TrCore *, gpointer ) */
    82     int    quitsig;
     86    int quitsig;
    8387
    8488    /* "prefs-changed" signal:
    8589       void handler( TrCore *, int, gpointer ) */
    86     int    prefsig;
     90    int prefsig;
    8791}
    8892TrCoreClass;
     
    138142
    139143/** Add a torrent. */
    140 gboolean tr_core_add_file(
    141                  TrCore*,
    142     const char * filename,
    143     gboolean *
    144                  setme_success,
    145     GError **    err );
     144gboolean tr_core_add_file( TrCore*, const char * filename, gboolean * setme_success, GError **    err );
     145/** Add a torrent. */
     146void tr_core_add_torrent( TrCore*, TrTorrent* );
    146147
    147148/** Present the main window */
    148 gboolean tr_core_present_window(
    149               TrCore*,
    150     gboolean *
    151               setme_success,
    152     GError ** err );
    153 
    154 /** Add a torrent. */
    155 void     tr_core_add_torrent( TrCore*,
    156                               TrTorrent* );
     149gboolean tr_core_present_window( TrCore*, gboolean * setme_success, GError ** err );
     150
    157151
    158152/**
     
    168162/* we've gotten notice from RPC that a torrent has been destroyed;
    169163   update our gui accordingly */
    170 void     tr_core_torrent_destroyed( TrCore * self,
    171                                     int      id );
     164void  tr_core_torrent_destroyed( TrCore * self, int torrentId );
    172165
    173166/* remove a torrent */
    174 void     tr_core_remove_torrent( TrCore *    self,
    175                                  TrTorrent * gtor,
    176                                  int         deleteFiles );
     167void  tr_core_remove_torrent( TrCore * self, TrTorrent * gtor, int deleteFiles );
    177168
    178169/* update the model with current torrent status */
    179 void     tr_core_update( TrCore * self );
     170void  tr_core_update( TrCore * self );
    180171
    181172/* emit the "quit" signal */
    182 void     tr_core_quit( TrCore * self );
    183 
    184 /* emit the "blocklist changed" signal */
    185 void     tr_core_blocksig( TrCore *     core,
    186                            gboolean     isDone,
    187                            const char * status );
    188 
    189 /* Set a preference value, save the prefs file, and emit the
    190    "prefs-changed" signal */
    191 void     tr_core_set_pref( TrCore *     self,
    192                            const char * key,
    193                            const char * val );
    194 
    195 /* Set a boolean preference value, save the prefs file, and emit the
    196    "prefs-changed" signal */
    197 void     tr_core_set_pref_bool( TrCore *     self,
    198                                 const char * key,
    199                                 gboolean     val );
    200 
    201 /* Set an integer preference value, save the prefs file, and emit the
    202    "prefs-changed" signal */
    203 void     tr_core_set_pref_int( TrCore *     self,
    204                                const char * key,
    205                                int          val );
    206 
    207 /* Set a double preference value, save the prefs file, and emit the
    208    "prefs-changed" signal */
    209 void     tr_core_set_pref_double( TrCore *     self,
    210                                   const char * key,
    211                                   double       val );
     173void  tr_core_quit( TrCore * self );
     174
     175/**
     176***  Set a preference value, save the prefs file, and emit the "prefs-changed" signal
     177**/
     178
     179void tr_core_set_pref     ( TrCore * self, const char * key, const char * val );
     180void tr_core_set_pref_bool( TrCore * self, const char * key, gboolean val );
     181void tr_core_set_pref_int ( TrCore * self, const char * key, int val );
     182void tr_core_set_pref_double( TrCore * self, const char * key, double val );
     183
     184/**
     185***
     186**/
     187
     188void tr_core_port_test( TrCore * core );
     189
     190void tr_core_blocklist_update( TrCore * core );
    212191
    213192/**
  • trunk/gtk/tr-prefs.c

    r8173 r8174  
    1414#include <errno.h>
    1515#include <stdarg.h>
     16#include <limits.h> /* USHRT_MAX */
    1617#include <stdlib.h> /* free() */
    1718#include <unistd.h>
     
    2223#include <libtransmission/version.h>
    2324#include <libtransmission/web.h>
    24 #include "blocklist.h"
    2525#include "conf.h"
    2626#include "hig.h"
     
    357357struct blocklist_data
    358358{
    359     GtkWidget *  check;
    360     GtkWidget *  dialog;
    361     TrCore *     core;
    362     gulong       id;
    363     int          abortFlag;
    364     char         secondary[256];
     359    gulong      updateBlocklistTag;
     360    GtkWidget * updateBlocklistButton;
     361    GtkWidget * updateBlocklistDialog;
     362    GtkWidget * check;
     363    TrCore    * core;
    365364};
    366365
    367366static void
    368 updateBlocklistText( GtkWidget * w,
    369                      TrCore *    core )
     367updateBlocklistText( GtkWidget * w, TrCore * core )
    370368{
    371369    const int n = tr_blocklistGetRuleCount( tr_core_session( core ) );
    372370    char      buf[512];
    373 
    374371    g_snprintf( buf, sizeof( buf ),
    375372                ngettext( "Enable _blocklist (contains %'d rule)",
     
    378375}
    379376
    380 static void
    381 onBlocklistDialogResponse( GtkDialog *  d,
    382                            int response UNUSED,
    383                            gpointer     gdata )
     377/* prefs dialog is being destroyed, so stop listening to blocklist updates */
     378static void
     379peerPageDestroyed( gpointer gdata, GObject * dead UNUSED )
    384380{
    385381    struct blocklist_data * data = gdata;
    386 
    387     g_signal_handler_disconnect( data->core, data->id );
    388     gtk_widget_destroy( GTK_WIDGET( d ) );
    389 }
    390 
    391 static void
    392 onBlocklistStatus( TrCore * core UNUSED,
    393                    gboolean      isDone,
    394                    const char *  status,
    395                    gpointer      gdata )
     382    if( data->updateBlocklistTag > 0 )
     383        g_signal_handler_disconnect( data->core, data->updateBlocklistTag );
     384    g_free( data );
     385}
     386
     387/* user hit "close" in the blocklist-update dialog */
     388static void
     389onBlocklistUpdateResponse( GtkDialog * dialog, gint response UNUSED, gpointer gdata )
    396390{
    397391    struct blocklist_data * data = gdata;
    398 
    399     gdk_threads_enter( );
    400     gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( data-> dialog ),
    401                                               "%s", status );
    402     gtk_dialog_set_response_sensitive( GTK_DIALOG( data->dialog ),
    403                                        GTK_RESPONSE_CANCEL, !isDone );
    404     gtk_dialog_set_response_sensitive( GTK_DIALOG( data->dialog ),
    405                                        GTK_RESPONSE_CLOSE, isDone );
    406     if( isDone )
    407         updateBlocklistText( data->check, core );
    408     gdk_threads_leave( );
    409 }
    410 
    411 static void
    412 onUpdateBlocklistCB( GtkButton * w,
    413                      gpointer    gdata )
    414 {
    415     GtkWidget *             d;
     392    gtk_widget_destroy( GTK_WIDGET( dialog ) );
     393    gtk_widget_set_sensitive( data->updateBlocklistButton, TRUE );
     394    data->updateBlocklistDialog = NULL;
     395    g_signal_handler_disconnect( data->core, data->updateBlocklistTag );
     396}
     397
     398/* core says the blocklist was updated */
     399static void
     400onBlocklistUpdated( TrCore * core, int n, gpointer gdata )
     401{
     402    const char * s = ngettext( "Blocklist now has %'d rule.", "Blocklist now has %'d rules.", n );
    416403    struct blocklist_data * data = gdata;
    417 
    418     d =
    419         gtk_message_dialog_new( GTK_WINDOW( gtk_widget_get_toplevel(
    420                                                                     GTK_WIDGET(
    421                                                                         w ) ) ),
    422                                GTK_DIALOG_DESTROY_WITH_PARENT,
    423                                GTK_MESSAGE_INFO,
    424                                GTK_BUTTONS_NONE,
    425                                _( "Updating Blocklist" ) );
    426 
    427     data->dialog = d;
    428     data->id =
    429         g_signal_connect( data->core, "blocklist-status", G_CALLBACK(
    430                               onBlocklistStatus ), data );
    431 
    432     gtk_dialog_add_buttons( GTK_DIALOG( d ),
    433                             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
    434                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
    435                             NULL );
    436     gtk_dialog_set_response_sensitive( GTK_DIALOG(
    437                                            d ), GTK_RESPONSE_CLOSE, FALSE );
    438 
    439     g_signal_connect( d, "response", G_CALLBACK(
    440                           onBlocklistDialogResponse ), data );
     404    GtkMessageDialog * d = GTK_MESSAGE_DIALOG( data->updateBlocklistDialog );
     405    gtk_widget_set_sensitive( data->updateBlocklistButton, TRUE );
     406    gtk_message_dialog_set_markup( d, _( "<b>Update succeeded!</b>" ) );
     407    gtk_message_dialog_format_secondary_text( d, s, n );
     408    updateBlocklistText( data->check, core );
     409}
     410
     411/* user pushed a button to update the blocklist */
     412static void
     413onBlocklistUpdate( GtkButton * w, gpointer gdata )
     414{
     415    GtkWidget * d;
     416    struct blocklist_data * data = gdata;
     417    d = gtk_message_dialog_new( GTK_WINDOW( gtk_widget_get_toplevel( GTK_WIDGET( w ) ) ),
     418                                GTK_DIALOG_DESTROY_WITH_PARENT,
     419                                GTK_MESSAGE_INFO,
     420                                GTK_BUTTONS_CLOSE,
     421                               _( "Update Blocklist" ) );
     422    gtk_widget_set_sensitive( data->updateBlocklistButton, FALSE );
     423    gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( d ), _( "Getting new blocklist..." ) );
     424    data->updateBlocklistDialog = d;
     425    g_signal_connect( d, "response", G_CALLBACK(onBlocklistUpdateResponse), data );
    441426    gtk_widget_show( d );
    442 
    443     gtr_blocklist_update( data->core );
     427    tr_core_blocklist_update( data->core );
     428    data->updateBlocklistTag = g_signal_connect( data->core, "blocklist-updated", G_CALLBACK( onBlocklistUpdated ), data );
    444429}
    445430
     
    449434{
    450435    const int val = gtk_toggle_button_get_active( w )
    451                     ? TR_ENCRYPTION_REQUIRED
    452                     : TR_ENCRYPTION_PREFERRED;
    453 
     436                  ? TR_ENCRYPTION_REQUIRED
     437                  : TR_ENCRYPTION_PREFERRED;
    454438    tr_core_set_pref_int( TR_CORE( core ), TR_PREFS_KEY_ENCRYPTION, val );
    455439}
     
    476460    h = gtk_hbox_new( FALSE, GUI_PAD_BIG );
    477461    gtk_box_pack_start( GTK_BOX( h ), w, TRUE, TRUE, 0 );
    478     b = gtr_button_new_from_stock( GTK_STOCK_REFRESH, _( "_Update" ) );
     462    b = data->updateBlocklistButton = gtr_button_new_from_stock( GTK_STOCK_REFRESH, _( "_Update" ) );
    479463    data->check = w;
    480464    g_object_set_data( G_OBJECT( b ), "session",
    481465                      tr_core_session( TR_CORE( core ) ) );
    482     g_signal_connect( b, "clicked", G_CALLBACK( onUpdateBlocklistCB ), data );
     466    g_signal_connect( b, "clicked", G_CALLBACK( onBlocklistUpdate ), data );
    483467    gtk_box_pack_start( GTK_BOX( h ), b, FALSE, FALSE, 0 );
    484468    g_signal_connect( w, "toggled", G_CALLBACK( target_cb ), b );
     
    516500
    517501    hig_workarea_finish( t, &row );
     502    g_object_weak_ref( G_OBJECT( t ), peerPageDestroyed, data );
    518503    return t;
    519504}
     
    736721
    737722    /* port */
    738     w = new_spin_button( TR_PREFS_KEY_RPC_PORT, core, 0, 65535, 1 );
     723    w = new_spin_button( TR_PREFS_KEY_RPC_PORT, core, 0, USHRT_MAX, 1 );
    739724    page->widgets = g_slist_append( page->widgets, w );
    740725    w = hig_workarea_add_row( t, &row, _( "Listening _port:" ), w, NULL );
     
    941926    page->proxy_widgets = g_slist_append( page->proxy_widgets, w );
    942927
    943     w = new_spin_button( TR_PREFS_KEY_PROXY_PORT, core, 0, 65535, 1 );
     928    w = new_spin_button( TR_PREFS_KEY_PROXY_PORT, core, 0, USHRT_MAX, 1 );
    944929    page->proxy_widgets = g_slist_append( page->proxy_widgets, w );
    945930    w = hig_workarea_add_row( t, &row, _( "Proxy _port:" ), w, NULL );
     
    12311216****/
    12321217
    1233 struct test_port_data
    1234 {
    1235     GtkWidget *  label;
    1236     gboolean *   alive;
    1237     char text[128];
     1218struct network_page_data
     1219{
     1220    TrCore     * core;
     1221    GtkWidget  * portLabel;
     1222    GtkWidget  * portButton;
     1223    GtkWidget  * portSpin;
     1224    gulong       portTag;
     1225    gulong       prefsTag;
    12381226};
    12391227
    1240 /* this is invoked in the gtk main loop's thread */
    1241 static gboolean
    1242 testing_port_done_idle( gpointer gdata )
    1243 {
    1244     struct test_port_data * data = gdata;
    1245 
    1246     if( *data->alive )
    1247     {
    1248         gdk_threads_enter( );
    1249         gtk_label_set_markup( GTK_LABEL( data->label ), data->text );
    1250         gdk_threads_leave( );
    1251     }
    1252 
    1253     return FALSE;
    1254 }
    1255 
    1256 /* this is invoked in the libtransmission thread */
    1257 static void
    1258 testing_port_done( tr_session * session        UNUSED,
    1259                    long          response_code UNUSED,
    1260                    const void *                response,
    1261                    size_t                      response_len,
    1262                    void *                      gdata )
    1263 {
    1264     struct test_port_data * data = gdata;
    1265 
    1266     if( *data->alive )
    1267     {
    1268         const int isOpen = response_len && *(char*)response == '1';
    1269         g_snprintf( data->text, sizeof( data->text ), isOpen
    1270                     ? _( "Port is <b>open</b>" )
    1271                     : _( "Port is <b>closed</b>" ) );
    1272         g_idle_add( testing_port_done_idle, data );
    1273     }
    1274 }
    1275 
    1276 static gboolean
    1277 testing_port_begin( gpointer gdata )
    1278 {
    1279     struct test_port_data * data = gdata;
    1280 
    1281     if( *data->alive )
    1282     {
    1283         char            url[256];
    1284         GObject       * o       = G_OBJECT( data->label );
    1285         GtkSpinButton * spin    = g_object_get_data( o, "tr-port-spin" );
    1286         tr_session    * session = g_object_get_data( o, "session" );
    1287         const int       port    = gtk_spin_button_get_value_as_int( spin );
    1288         g_snprintf( url, sizeof( url ),
    1289                     "http://portcheck.transmissionbt.com/%d",
    1290                     port );
    1291         tr_webRun( session, url, NULL, testing_port_done, data );
    1292     }
    1293     return FALSE;
    1294 }
    1295 
    1296 struct network_page_data
    1297 {
    1298     gboolean *   alive;
    1299     GtkWidget *  label;
    1300     guint        id;
    1301     TrCore *     core;
    1302 };
    1303 
    1304 static void
    1305 onCorePrefsChanged( TrCore * core UNUSED,
    1306                     const char *  key,
    1307                     gpointer      gdata )
     1228static void
     1229onCorePrefsChanged( TrCore * core UNUSED, const char *  key, gpointer gdata )
    13081230{
    13091231    if( !strcmp( key, TR_PREFS_KEY_PEER_PORT ) )
    13101232    {
    1311         struct network_page_data * ndata = gdata;
    1312         struct test_port_data *    data;
    1313 
    1314         gtk_label_set_markup( GTK_LABEL( ndata->label ),
    1315                              _( "<i>Testing port...</i>" ) );
    1316 
    1317         /* wait three seconds to give the port forwarding time to kick in */
    1318         data = g_new0( struct test_port_data, 1 );
    1319         data->label = ndata->label;
    1320         data->alive = ndata->alive;
    1321         gtr_timeout_add_seconds( 3, testing_port_begin, data );
     1233        struct network_page_data * data = gdata;
     1234        gtk_label_set_text( GTK_LABEL( data->portLabel ), _( "Status unknown" ) );
     1235        gtk_widget_set_sensitive( data->portButton, TRUE );
     1236        gtk_widget_set_sensitive( data->portSpin, TRUE );
    13221237    }
    13231238}
    13241239
    13251240static void
    1326 networkPageDestroyed( gpointer       gdata,
    1327                       GObject * dead UNUSED )
     1241networkPageDestroyed( gpointer gdata, GObject * dead UNUSED )
    13281242{
    13291243    struct network_page_data * data = gdata;
    1330 
    1331     *data->alive = FALSE;
    1332     g_signal_handler_disconnect( data->core, data->id );
     1244    if( data->prefsTag > 0 )
     1245        g_signal_handler_disconnect( data->core, data->prefsTag );
     1246    if( data->portTag > 0 )
     1247        g_signal_handler_disconnect( data->core, data->portTag );
    13331248    g_free( data );
     1249}
     1250
     1251static void
     1252onPortTested( TrCore * core UNUSED, gboolean isOpen, gpointer vdata )
     1253{
     1254    struct network_page_data * data = vdata;
     1255    const char * markup = isOpen ? _( "Port is <b>open</b>" ) : _( "Port is <b>closed</b>" );
     1256    gtk_label_set_markup( GTK_LABEL( data->portLabel ), markup );
     1257    gtk_widget_set_sensitive( data->portButton, TRUE );
     1258    gtk_widget_set_sensitive( data->portSpin, TRUE );
     1259}
     1260
     1261static void
     1262onPortTest( GtkButton * button UNUSED, gpointer vdata )
     1263{
     1264    struct network_page_data * data = vdata;
     1265    gtk_widget_set_sensitive( data->portButton, FALSE );
     1266    gtk_widget_set_sensitive( data->portSpin, FALSE );
     1267    gtk_label_set_markup( GTK_LABEL( data->portLabel ), _( "<i>Testing...</i>" ) );
     1268    data->portTag = g_signal_connect( data->core, "port-tested", G_CALLBACK(onPortTested), data );
     1269    tr_core_port_test( data->core );
    13341270}
    13351271
     
    13411277    GtkWidget *                t;
    13421278    GtkWidget *                w;
    1343     GtkWidget *                w2;
    13441279    GtkWidget *                h;
    13451280    GtkWidget *                l;
    13461281    struct network_page_data * data;
    13471282
    1348     /* register to stop listening to core prefs changes when the page is
    1349       destroyed */
     1283    /* register to stop listening to core prefs changes when the page is destroyed */
    13501284    data = g_new0( struct network_page_data, 1 );
    13511285    data->core = TR_CORE( core );
    1352 
    1353     /* we leak this gboolean* s.t. we know it will still be alive when the port
    1354        check is done, whether the dialog was destroyed or not.  kind of
    1355        clumsy... */
    1356     data->alive = g_new( gboolean, 1 );
    1357     *data->alive = TRUE;
    13581286
    13591287    /* build the page */
     
    13611289    hig_workarea_add_section_title( t, &row, _( "Incoming Peers" ) );
    13621290
     1291    s = _( "_Port for incoming connections:" );
     1292    w = data->portSpin = new_spin_button( TR_PREFS_KEY_PEER_PORT, core, 1, USHRT_MAX, 1 );
     1293    hig_workarea_add_row( t, &row, s, w, NULL );
     1294
    13631295    h = gtk_hbox_new( FALSE, GUI_PAD_BIG );
    1364     w2 = new_spin_button( TR_PREFS_KEY_PEER_PORT, core, 1, 65535, 1 );
    1365     gtk_box_pack_start( GTK_BOX( h ), w2, FALSE, FALSE, 0 );
    1366     data->label = l = gtk_label_new( NULL );
     1296    l = data->portLabel = gtk_label_new( _( "Status unknown" ) );
    13671297    gtk_misc_set_alignment( GTK_MISC( l ), 0.0f, 0.5f );
    1368     gtk_box_pack_start( GTK_BOX( h ), l, FALSE, FALSE, 0 );
    1369     hig_workarea_add_row( t, &row, _( "Listening _port:" ), h, w2 );
    1370 
    1371     g_object_set_data( G_OBJECT( l ), "tr-port-spin", w2 );
    1372     g_object_set_data( G_OBJECT( l ), "session",
    1373                       tr_core_session( TR_CORE( core ) ) );
    1374     data->id = g_signal_connect( TR_CORE( core ), "prefs-changed",
    1375                                  G_CALLBACK( onCorePrefsChanged ), data );
    1376     onCorePrefsChanged( NULL, TR_PREFS_KEY_PEER_PORT, data );
     1298    gtk_box_pack_start_defaults( GTK_BOX( h ), l );
     1299    w = data->portButton = gtk_button_new_with_mnemonic( _( "_Test Port" ) );
     1300    gtk_box_pack_end( GTK_BOX( h ), w, FALSE, FALSE, 0 );
     1301    g_signal_connect( w, "clicked", G_CALLBACK(onPortTest), data );
     1302    hig_workarea_add_row( t, &row, NULL, h, NULL );
     1303    data->prefsTag = g_signal_connect( TR_CORE( core ), "prefs-changed", G_CALLBACK( onCorePrefsChanged ), data );
     1304    g_object_weak_ref( G_OBJECT( t ), networkPageDestroyed, data );
    13771305
    13781306    s = _( "Randomize the port every launch" );
     
    13851313
    13861314    hig_workarea_finish( t, &row );
    1387     g_object_weak_ref( G_OBJECT( t ), networkPageDestroyed, data );
    1388 
    13891315    return t;
    13901316}
     
    14221348                              gtk_label_new ( _( "Peers" ) ) );
    14231349    gtk_notebook_append_page( GTK_NOTEBOOK( n ),
     1350                              bandwidthPage( core ),
     1351                              gtk_label_new ( _( "Speed" ) ) );
     1352    gtk_notebook_append_page( GTK_NOTEBOOK( n ),
    14241353                              networkPage( core ),
    14251354                              gtk_label_new ( _( "Network" ) ) );
    1426     gtk_notebook_append_page( GTK_NOTEBOOK( n ),
    1427                               bandwidthPage( core ),
    1428                               gtk_label_new ( _( "Speed" ) ) );
    14291355    gtk_notebook_append_page( GTK_NOTEBOOK( n ),
    14301356                              desktopPage( core ),
Note: See TracChangeset for help on using the changeset viewer.