From c32c517d465ebdd113010ba9bafdc404e4cfba31 Mon Sep 17 00:00:00 2001 From: Josh Elsasser Date: Wed, 23 May 2007 01:47:42 +0000 Subject: [PATCH] Preparation for eliminating TrBackend: move the TrBackend instance into TrCore and add wrapper functions. --- gtk/dialogs.h | 8 ---- gtk/main.c | 57 +++++++-------------------- gtk/tr_core.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++ gtk/tr_core.h | 41 ++++++++++++++++++++ 4 files changed, 159 insertions(+), 52 deletions(-) diff --git a/gtk/dialogs.h b/gtk/dialogs.h index c347c25e3..70c895d1a 100644 --- a/gtk/dialogs.h +++ b/gtk/dialogs.h @@ -25,17 +25,9 @@ #ifndef TG_PREFS_H #define TG_PREFS_H -#include "tr_backend.h" #include "tr_torrent.h" #include "util.h" -GtkWidget * -makeprefwindow(GtkWindow *parent, TrBackend *back); - -/* set various things based on saved prefs */ -void -applyprefs(TrBackend *back); - /* show the "add a torrent" dialog */ void makeaddwind(GtkWindow *parent, add_torrents_func_t addfunc, void *cbdata); diff --git a/gtk/main.c b/gtk/main.c index 93e8c57e7..8e7d1b99e 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -40,7 +40,6 @@ #include "dialogs.h" #include "ipc.h" #include "msgwin.h" -#include "tr_backend.h" #include "tr_cell_renderer_progress.h" #include "tr_core.h" #include "tr_icon.h" @@ -66,7 +65,6 @@ #define SIGCOUNT_MAX 3 struct cbdata { - TrBackend * back; GtkWindow * wind; TrCore * core; TrIcon * icon; @@ -377,7 +375,6 @@ appsetup( TrWindow * wind, benc_val_t * state, GList * args, gboolean paused ) /* fill out cbdata */ cbdata = g_new0( struct cbdata, 1 ); - cbdata->back = tr_backend_new(); cbdata->wind = NULL; cbdata->core = tr_core_new(); cbdata->icon = NULL; @@ -506,9 +503,6 @@ wannaquit( void * vdata ) { struct cbdata * data; struct exitdata *edata; - GtkTreeModel * model; - GtkTreeIter iter; - TrTorrent *tor; data = vdata; if( data->closing ) @@ -522,27 +516,8 @@ wannaquit( void * vdata ) g_source_remove(data->timer); data->timer = 0; - /* - Add a reference to all torrents in the list, which will be removed - when the politely-stopped signal is emitted. This is necessary - because a reference is added when a torrent is removed - from the model and tr_torrent_stop_polite() is called on it. - */ - model = tr_core_model( data->core ); - if( gtk_tree_model_get_iter_first( model, &iter) ) - { - do - { - gtk_tree_model_get( model, &iter, MC_TORRENT, &tor, -1 ); - } - while( gtk_tree_model_iter_next( model, &iter ) ); - } - - /* try to politely stop all the torrents */ - tr_backend_stop_torrents(data->back); - - /* shut down nat traversal */ - tr_natTraversalEnable(tr_backend_handle(data->back), 0); + /* pause torrents and stop nat traversal */ + tr_core_quit( data->core ); /* set things up to wait for torrents to stop */ edata = g_new0(struct exitdata, 1); @@ -564,18 +539,14 @@ exitcheck( gpointer gdata ) { struct exitdata * edata; struct cbdata * cbdata; - tr_handle_status_t * hstat; edata = gdata; cbdata = edata->cbdata; - hstat = tr_handleStatus( tr_backend_handle( cbdata->back ) ); - /* keep going if we haven't hit the exit timeout and - we either have torrents left or nat traversal is active */ + /* keep waiting until we're ready to quit or we hit the exit timeout */ if( time( NULL ) - edata->started < TRACKER_EXIT_TIMEOUT ) { - if( !tr_backend_torrents_stopped( cbdata->back, FALSE ) || - TR_NAT_TRAVERSAL_DISABLED != hstat->natTraversalStatus ) + if( !tr_core_did_quit( cbdata->core ) ) { updatemodel( cbdata ); return TRUE; @@ -583,8 +554,8 @@ exitcheck( gpointer gdata ) } else { - /* time the remaining torrents out so they signal politely-stopped */ - tr_backend_torrents_stopped( cbdata->back, TRUE ); + /* oh well */ + tr_core_force_quit( cbdata->core ); } /* exit otherwise */ @@ -594,12 +565,11 @@ exitcheck( gpointer gdata ) } g_free( edata ); /* The prefs window need to be destroyed first as destroying it may - trigger callbacks that use cbdata->back. Ick. */ + trigger callbacks that use cbdata->core. Ick. */ if( NULL != cbdata->prefs ) { gtk_widget_destroy( GTK_WIDGET( cbdata->prefs ) ); } - g_object_unref( G_OBJECT( cbdata->back ) ); if( NULL != cbdata->wind ) { gtk_widget_destroy( GTK_WIDGET( cbdata->wind ) ); @@ -743,7 +713,7 @@ prefschanged( GtkWidget * widget SHUTUP, int id, gpointer data ) gboolean boolval; cbdata = data; - tr = tr_backend_handle( cbdata->back ); + tr = tr_core_handle( cbdata->core ); switch( id ) { @@ -851,14 +821,14 @@ updatemodel(gpointer gdata) { /* update the main window's statusbar and toolbar buttons */ if( NULL != data->wind ) { - tr_torrentRates( tr_backend_handle( data->back ), &down, &up ); + tr_torrentRates( tr_core_handle( data->core ), &down, &up ); tr_window_update( TR_WINDOW( data->wind ), down, up ); } /* check for politely stopped torrents unless we're exiting */ if( !data->closing ) { - tr_backend_torrents_stopped( data->back, FALSE ); + tr_core_reap( data->core ); } /* update the message window */ @@ -1051,7 +1021,7 @@ addtorrents(void *vdata, void *state, GList *files, if( NULL != state ) { - torlist = tr_backend_load_state( data->back, state, flags, &errlist ); + torlist = tr_core_load( data->core, state, &errlist ); } if(NULL != files) { @@ -1067,8 +1037,7 @@ addtorrents(void *vdata, void *state, GList *files, } for(ii = g_list_first(files); NULL != ii; ii = ii->next) { errstr = NULL; - tor = tr_torrent_new(G_OBJECT(data->back), ii->data, dir, - flags, &errstr); + tor = tr_core_new_torrent( data->core, ii->data, dir, flags, &errstr); if(NULL != tor) torlist = g_list_append(torlist, tor); if(NULL != errstr) @@ -1112,7 +1081,7 @@ savetorrents( struct cbdata *data ) { char * errstr; - tr_backend_save_state( data->back, &errstr ); + tr_core_save( data->core, &errstr ); if( NULL != errstr ) { errmsg( data->wind, "%s", errstr ); diff --git a/gtk/tr_core.c b/gtk/tr_core.c index 687b49c4e..23b315ff9 100644 --- a/gtk/tr_core.c +++ b/gtk/tr_core.c @@ -27,6 +27,9 @@ #include #include +#include "bencode.h" + +#include "tr_backend.h" #include "tr_core.h" #include "tr_torrent.h" #include "util.h" @@ -100,6 +103,8 @@ tr_core_init( GTypeInstance * instance, gpointer g_class SHUTUP ) store = gtk_list_store_newv( MC_ROW_COUNT, types ); self->model = GTK_TREE_MODEL( store ); + self->backend = tr_backend_new(); + self->quitting = FALSE; self->disposed = FALSE; } @@ -116,6 +121,7 @@ tr_core_dispose( GObject * obj ) self->disposed = TRUE; g_object_unref( self->model ); + g_object_unref( self->backend ); /* Chain up to the parent class */ parent = g_type_class_peek( g_type_parent( TR_CORE_TYPE ) ); @@ -135,3 +141,102 @@ tr_core_model( TrCore * self ) return self->model; } + +tr_handle_t * +tr_core_handle( TrCore * self ) +{ + TR_IS_CORE( self ); + + return tr_backend_handle( self->backend ); +} + +void +tr_core_quit( TrCore * self ) +{ + GtkTreeIter iter; + TrTorrent * tor; + + TR_IS_CORE( self ); + + g_assert( !self->quitting ); + self->quitting = TRUE; + + /* + Add a reference to all torrents in the list, which will be + removed when the politely-stopped signal is emitted. This is + necessary because a reference is added when a torrent is removed + from the model and tr_torrent_stop_polite() is called on it. + */ + if( gtk_tree_model_get_iter_first( self->model, &iter) ) + { + do + { + gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 ); + } + while( gtk_tree_model_iter_next( self->model, &iter ) ); + } + + /* try to politely stop all the torrents */ + tr_backend_stop_torrents( self->backend ); + + /* shut down nat traversal */ + tr_natTraversalEnable( tr_backend_handle( self->backend ), 0 ); +} + +gboolean +tr_core_did_quit( TrCore * self ) +{ + tr_handle_status_t * hstat; + + TR_IS_CORE( self ); + g_assert( self->quitting ); + + hstat = tr_handleStatus( tr_backend_handle( self->backend ) ); + + return ( tr_backend_torrents_stopped( self->backend, FALSE ) && + TR_NAT_TRAVERSAL_DISABLED == hstat->natTraversalStatus ); +} + +void +tr_core_force_quit( TrCore * self ) +{ + TR_IS_CORE( self ); + g_assert( self->quitting ); + + /* time the remaining torrents out so they signal politely-stopped */ + tr_backend_torrents_stopped( self->backend, TRUE ); +} + +void +tr_core_reap( TrCore * self ) +{ + TR_IS_CORE( self ); + + tr_backend_torrents_stopped( self->backend, FALSE ); +} + +GList * +tr_core_load( TrCore * self, benc_val_t * state, GList ** errors ) +{ + TR_IS_CORE( self ); + + return tr_backend_load_state( self->backend, state, 0, errors ); +} + +void +tr_core_save( TrCore * self, char ** error ) +{ + TR_IS_CORE( self ); + + tr_backend_save_state( self->backend, error ); +} + +TrTorrent * +tr_core_new_torrent( TrCore * self, const char * torrent, const char * dir, + guint flags, char ** err ) +{ + TR_IS_CORE( self ); + + return tr_torrent_new( G_OBJECT( self->backend ), + torrent, dir, flags, err ); +} diff --git a/gtk/tr_core.h b/gtk/tr_core.h index 7a7f05b02..8469af8dd 100644 --- a/gtk/tr_core.h +++ b/gtk/tr_core.h @@ -25,9 +25,13 @@ #ifndef TR_CORE_H #define TR_CORE_H +#include + #include #include +#include "bencode.h" + #define TR_CORE_TYPE ( tr_core_get_type() ) #define TR_CORE( obj ) \ @@ -53,6 +57,8 @@ struct _TrCore { GObject parent; GtkTreeModel * model; + struct _TrBackend * backend; + gboolean quitting; gboolean disposed; }; @@ -67,9 +73,44 @@ tr_core_get_type( void ); TrCore * tr_core_new( void ); +/* Return the model used without incrementing the reference count */ GtkTreeModel * tr_core_model( TrCore * self ); +/* Returns the libtransmission handle */ +tr_handle_t * +tr_core_handle( TrCore * self ); + +/* Try to politely stop all torrents and nat traversal */ +void +tr_core_quit( TrCore * self ); + +/* Returns true if tr_core_quit() has been called and we are ready to quit */ +gboolean +tr_core_did_quit( TrCore * self ); + +/* Destroy any torrents that haven't stopped already */ +void +tr_core_force_quit( TrCore * self ); + +/* Reap any dead torrents */ +void +tr_core_reap( TrCore * self ); + +/* Load saved state, return list of TrTorrent*. A char* is appended to + *errors for each error which occurs, these must be freed. */ +GList * +tr_core_load( TrCore * self, benc_val_t * state, GList ** errors ); + +/* Save state. Set *error to any error which occurs, this must be freed. */ +void +tr_core_save( TrCore * self, char ** error ); + +/* XXX temporary hack for transition away from TrBackend */ +struct _TrTorrent * +tr_core_new_torrent( TrCore * self, const char * torrent, const char * dir, + guint flags, char ** err ); + /* column names for the model used to store torrent information */ /* keep this in sync with the type array in tr_core_init() in tr_core.c */ enum {