Untangle the gordian references between TrCore and TrTorrent.

This commit is contained in:
Josh Elsasser 2007-05-23 06:25:15 +00:00
parent 4567bc0b3f
commit 787e17135a
5 changed files with 239 additions and 246 deletions

View File

@ -517,7 +517,7 @@ wannaquit( void * vdata )
data->timer = 0;
/* pause torrents and stop nat traversal */
tr_core_quit( data->core );
tr_core_shutdown( data->core );
/* set things up to wait for torrents to stop */
edata = g_new0(struct exitdata, 1);
@ -546,17 +546,12 @@ exitcheck( gpointer gdata )
/* keep waiting until we're ready to quit or we hit the exit timeout */
if( time( NULL ) - edata->started < TRACKER_EXIT_TIMEOUT )
{
if( !tr_core_did_quit( cbdata->core ) )
if( !tr_core_quiescent( cbdata->core ) )
{
updatemodel( cbdata );
return TRUE;
}
}
else
{
/* oh well */
tr_core_force_quit( cbdata->core );
}
/* exit otherwise */
if( 0 < edata->timer )
@ -574,7 +569,6 @@ exitcheck( gpointer gdata )
{
gtk_widget_destroy( GTK_WIDGET( cbdata->wind ) );
}
tr_core_clear( cbdata->core ); /* XXX god these circular references suck */
g_object_unref( cbdata->core );
if( NULL != cbdata->icon )
{
@ -803,12 +797,6 @@ updatemodel(gpointer gdata) {
tr_window_update( TR_WINDOW( data->wind ), down, up );
}
/* check for stopped torrents unless we're exiting */
if( !data->closing )
{
tr_core_reap( data->core );
}
/* update the message window */
msgwin_update();
@ -942,7 +930,7 @@ handleaction( struct cbdata * data, int act )
changed = TRUE;
break;
case ACT_DELETE:
tr_core_delete_torrent( data->core, tor, &iter );
tr_core_delete_torrent( data->core, &iter );
changed = TRUE;
break;
case ACT_INFO:

View File

@ -44,10 +44,10 @@ static void
tr_core_class_init( gpointer g_class, gpointer g_class_data );
static void
tr_core_dispose( GObject * obj );
static void
tr_core_torrent_finalized( gpointer gdata, GObject * tor );
static int
tr_core_check_torrents( TrCore * self, gboolean timeout );
tr_core_check_torrents( TrCore * self );
static int
tr_core_check_zombies( TrCore * self );
static void
tr_core_insert( TrCore * self, TrTorrent * tor );
@ -108,13 +108,17 @@ tr_core_init( GTypeInstance * instance, gpointer g_class SHUTUP )
TR_TRACKER_BOXED_TYPE, TR_TORRENT_TYPE,
};
#ifdef REFDBG
fprintf( stderr, "core %p init\n", self );
#endif
/* create the model used to store torrent data */
g_assert( ALEN( types ) == MC_ROW_COUNT );
store = gtk_list_store_newv( MC_ROW_COUNT, types );
self->model = GTK_TREE_MODEL( store );
self->handle = tr_init( "gtk" );
self->torrents = NULL;
self->zombies = NULL;
self->quitting = FALSE;
self->disposed = FALSE;
}
@ -124,7 +128,9 @@ tr_core_dispose( GObject * obj )
{
TrCore * self = (TrCore *) obj;
GObjectClass * parent;
GtkTreeIter iter;
GList * ii;
TrTorrent * tor;
if( self->disposed )
{
@ -132,22 +138,39 @@ tr_core_dispose( GObject * obj )
}
self->disposed = TRUE;
if( NULL != self->model )
{
g_object_unref( self->model );
self->model = NULL;
}
#ifdef REFDBG
fprintf( stderr, "core %p dispose\n", self );
#endif
if( NULL != self->torrents )
/* sever all remaining torrents in the model */
if( gtk_tree_model_get_iter_first( self->model, &iter ) )
{
for( ii = g_list_first( self->torrents ); NULL != ii; ii = ii->next )
do
{
g_object_weak_unref( ii->data, tr_core_torrent_finalized, self );
gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
tr_torrent_sever( tor );
g_object_unref( tor );
}
g_list_free( self->torrents );
self->torrents = NULL;
while( gtk_tree_model_iter_next( self->model, &iter ) );
}
g_object_unref( self->model );
/* sever and unref all remaining zombie torrents */
if( NULL != self->zombies )
{
for( ii = g_list_first( self->zombies ); NULL != ii; ii = ii->next )
{
tr_torrent_sever( ii->data );
g_object_unref( ii->data );
}
g_list_free( self->zombies );
}
#ifdef REFDBG
fprintf( stderr, "core %p dead\n", self );
#endif
/* close the libtransmission instance */
tr_close( self->handle );
/* Chain up to the parent class */
@ -155,16 +178,6 @@ tr_core_dispose( GObject * obj )
parent->dispose( obj );
}
void
tr_core_torrent_finalized( gpointer gdata, GObject * tor )
{
TrCore * self = gdata;
TR_IS_CORE( self );
self->torrents = g_list_remove( self->torrents, tor );
}
TrCore *
tr_core_new( void )
{
@ -176,6 +189,11 @@ tr_core_model( TrCore * self )
{
TR_IS_CORE( self );
if( self->disposed )
{
return NULL;
}
return self->model;
}
@ -184,122 +202,149 @@ tr_core_handle( TrCore * self )
{
TR_IS_CORE( self );
if( self->disposed )
{
return NULL;
}
return self->handle;
}
void
tr_core_quit( TrCore * self )
tr_core_shutdown( TrCore * self )
{
GtkTreeIter iter;
TrTorrent * tor;
GList * ii;
tr_stat_t * st;
TR_IS_CORE( self );
if( self->disposed )
{
return;
}
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.
*/
/* try to stop all the torrents nicely */
if( gtk_tree_model_get_iter_first( self->model, &iter) )
{
do
{
gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
st = tr_torrent_stat( tor );
if( TR_STATUS_ACTIVE & st->status )
{
tr_torrentStop( tr_torrent_handle( tor ) );
}
g_object_unref( tor );
}
while( gtk_tree_model_iter_next( self->model, &iter ) );
}
/* try to politely stop all the torrents */
for( ii = g_list_first( self->torrents ); NULL != ii; ii = ii->next )
{
tr_torrent_stop_politely( ii->data );
}
/* shut down nat traversal */
tr_natTraversalEnable( self->handle, 0 );
}
gboolean
tr_core_did_quit( TrCore * self )
tr_core_quiescent( TrCore * self )
{
tr_handle_status_t * hstat;
TR_IS_CORE( self );
g_assert( self->quitting );
if( self->disposed )
{
return TRUE;
}
if( 0 < tr_core_check_torrents( self ) )
{
return FALSE;
}
hstat = tr_handleStatus( self->handle );
return ( 0 == tr_core_check_torrents( self, 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_core_check_torrents( self, TRUE );
}
void
tr_core_clear( TrCore * self )
{
TR_IS_CORE( self );
if( NULL != self->model )
{
g_object_unref( self->model );
self->model = NULL;
}
}
void
tr_core_reap( TrCore * self )
{
TR_IS_CORE( self );
tr_core_check_torrents( self, FALSE );
return TR_NAT_TRAVERSAL_DISABLED == hstat->natTraversalStatus;
}
int
tr_core_check_torrents( TrCore * self, gboolean timeout )
tr_core_check_torrents( TrCore * self )
{
GtkTreeIter iter;
tr_stat_t * st;
GList * ii, * list;
int count;
TrTorrent * tor;
g_assert( !self->disposed && self->quitting );
count = 0;
list = g_list_copy( self->torrents );
for( ii = g_list_first( list ); NULL != ii; ii = ii->next )
if( gtk_tree_model_get_iter_first( self->model, &iter) )
{
st = tr_torrent_stat_polite( ii->data, timeout );
if( NULL == st || !( TR_STATUS_PAUSE & st->status ) )
do
{
count++;
gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
st = tr_torrent_stat( tor );
if( !( TR_STATUS_PAUSE & st->status ) )
{
count++;
}
g_object_unref( tor );
}
while( gtk_tree_model_iter_next( self->model, &iter ) );
}
g_list_free( list );
count += tr_core_check_zombies( self );
return count;
}
int
tr_core_check_zombies( TrCore * self )
{
GList * ii, * next;
tr_stat_t * st;
for( ii = g_list_first( self->zombies ); NULL != ii; ii = next )
{
next = ii->next;
st = tr_torrent_stat( ii->data );
if( TR_STATUS_PAUSE & st->status )
{
tr_torrent_sever( ii->data );
g_object_unref( ii->data );
/* XXX is this safe to do? */
self->zombies = g_list_delete_link( self->zombies, ii );
}
}
return g_list_length( self->zombies );
}
void
tr_core_save( TrCore * self, char ** error )
{
benc_val_t state;
GList * ii;
benc_val_t state;
int count;
GtkTreeIter iter;
TrTorrent * tor;
TR_IS_CORE( self );
if( gtk_tree_model_get_iter_first( self->model, &iter) )
{
do
{
count++;
}
while( gtk_tree_model_iter_next( self->model, &iter ) );
}
tr_bencInit( &state, TYPE_LIST );
if( tr_bencListReserve( &state, g_list_length( self->torrents ) ) )
if( tr_bencListReserve( &state, count ) )
{
if( NULL != error )
{
@ -308,17 +353,29 @@ tr_core_save( TrCore * self, char ** error )
return;
}
for( ii = g_list_first( self->torrents ); NULL != ii; ii = ii->next )
if( gtk_tree_model_get_iter_first( self->model, &iter) )
{
tr_torrent_get_state( ii->data, tr_bencListAdd( &state ) );
do
{
gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
tr_torrent_get_state( tor, tr_bencListAdd( &state ) );
g_object_unref( tor );
}
while( gtk_tree_model_iter_next( self->model, &iter ) );
}
cf_savestate( &state, error );
tr_bencFree( &state );
for( ii = g_list_first( self->torrents ); NULL != ii; ii = ii->next )
if( gtk_tree_model_get_iter_first( self->model, &iter) )
{
tr_torrent_state_saved( ii->data );
do
{
gtk_tree_model_get( self->model, &iter, MC_TORRENT, &tor, -1 );
tr_torrent_state_saved( tor );
g_object_unref( tor );
}
while( gtk_tree_model_iter_next( self->model, &iter ) );
}
}
@ -340,8 +397,8 @@ tr_core_load( TrCore * self, benc_val_t * state, GList ** errors )
for( ii = 0; ii < state->val.l.count; ii++ )
{
errstr = NULL;
tor = tr_torrent_new_with_state( G_OBJECT( self ),
state->val.l.vals + ii, 0, &errstr );
tor = tr_torrent_new_with_state( self->handle, state->val.l.vals + ii,
0, &errstr );
if( NULL != errstr )
{
*errors = g_list_append( *errors, errstr );
@ -364,7 +421,7 @@ tr_core_add_torrent( TrCore * self, const char * torrent, const char * dir,
TR_IS_CORE( self );
tor = tr_torrent_new( G_OBJECT( self ), torrent, dir, flags, err );
tor = tr_torrent_new( self->handle, torrent, dir, flags, err );
if( NULL == tor )
{
return FALSE;
@ -376,19 +433,32 @@ tr_core_add_torrent( TrCore * self, const char * torrent, const char * dir,
}
void
tr_core_delete_torrent( TrCore * self, void * torrent,
GtkTreeIter * iter )
tr_core_delete_torrent( TrCore * self, GtkTreeIter * iter )
{
TrTorrent * tor;
tr_stat_t * st;
TR_IS_CORE( self );
/* tor will be unref'd in the politely_stopped handler */
g_object_ref( torrent );
tr_torrent_stop_politely( torrent );
if( TR_FLAG_SAVE & tr_torrent_info( torrent )->flags )
{
tr_torrentRemoveSaved( tr_torrent_handle( torrent ) );
}
gtk_tree_model_get( self->model, iter, MC_TORRENT, &tor, -1 );
gtk_list_store_remove( GTK_LIST_STORE( self->model ), iter );
if( TR_FLAG_SAVE & tr_torrent_info( tor )->flags )
{
tr_torrentRemoveSaved( tr_torrent_handle( tor ) );
}
st = tr_torrent_stat( tor );
if( TR_STATUS_ACTIVE & st->status )
{
tr_torrentStop( tr_torrent_handle( tor ) );
self->zombies = g_list_append( self->zombies, tor );
}
else
{
tr_torrent_sever( tor );
g_object_unref( tor );
}
}
void
@ -397,23 +467,13 @@ tr_core_insert( TrCore * self, TrTorrent * tor )
GtkTreeIter iter;
tr_info_t * inf;
g_object_weak_ref( G_OBJECT( tor ), tr_core_torrent_finalized, self );
self->torrents = g_list_append( self->torrents, tor );
gtk_list_store_append( GTK_LIST_STORE( self->model ), &iter );
inf = tr_torrent_info( tor );
/* inserting the torrent into the model adds a reference */
gtk_list_store_set( GTK_LIST_STORE( self->model ), &iter,
MC_NAME, inf->name,
MC_SIZE, inf->totalSize,
MC_TORRENT, tor,
-1);
/* we will always ref a torrent before politely stopping it */
g_signal_connect( tor, "politely_stopped",
G_CALLBACK( g_object_unref ), NULL );
g_object_unref( tor );
}
@ -457,4 +517,9 @@ tr_core_update( TrCore * self )
}
while( gtk_tree_model_iter_next( self->model, &iter ) );
}
if( !self->quitting )
{
tr_core_check_zombies( self );
}
}

View File

@ -58,14 +58,14 @@ struct _TrCore
GObject parent;
GtkTreeModel * model;
tr_handle_t * handle;
GList * torrents;
GList * zombies;
gboolean quitting;
gboolean disposed;
};
struct _TrCoreClass
{
GObjectClass parent;
GObjectClass parent;
};
GType
@ -84,23 +84,11 @@ tr_core_handle( TrCore * self );
/* Try to politely stop all torrents and nat traversal */
void
tr_core_quit( TrCore * self );
tr_core_shutdown( TrCore * self );
/* Returns true if tr_core_quit() has been called and we are ready to quit */
/* Returns true if the shutdown has completed */
gboolean
tr_core_did_quit( TrCore * self );
/* Destroy any torrents that haven't stopped already */
void
tr_core_force_quit( TrCore * self );
/* XXX temporary hack to deal with circular references */
void
tr_core_clear( TrCore * self );
/* Check for stopped torrents */
void
tr_core_reap( TrCore * self );
tr_core_quiescent( TrCore * self );
/* Save state. If error is not NULL is will be set to any error which
occurs, this must be freed. */
@ -121,9 +109,9 @@ tr_core_add_torrent( TrCore * self, const char * torrent, const char * dir,
/* remove a torrent, waiting for it to pause if necessary */
void
tr_core_delete_torrent( TrCore * self, void * torrent,
GtkTreeIter * iter /* XXX */ );
tr_core_delete_torrent( TrCore * self, GtkTreeIter * iter /* XXX */ );
/* update the model with current torrent status */
void
tr_core_update( TrCore * self );

View File

@ -34,14 +34,12 @@
/* XXX */
#define TR_WANT_TORRENT_PRIVATE
#include "tr_core.h"
#include "tr_prefs.h"
#include "tr_torrent.h"
#include "util.h"
enum {
TR_TORRENT_HANDLE = 1,
TR_TORRENT_BACKEND,
TR_TORRENT_DIR,
TR_TORRENT_PAUSED,
};
@ -114,7 +112,6 @@ tr_torrent_get_type(void) {
static void
tr_torrent_class_init(gpointer g_class, gpointer g_class_data SHUTUP) {
GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
TrTorrentClass *klass = TR_TORRENT_CLASS(g_class);
GParamSpec *pspec;
gobject_class->set_property = tr_torrent_set_property;
@ -126,12 +123,6 @@ tr_torrent_class_init(gpointer g_class, gpointer g_class_data SHUTUP) {
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property(gobject_class, TR_TORRENT_HANDLE, pspec);
pspec = g_param_spec_object("backend", "Backend",
"Libtransmission backend object",
TR_CORE_TYPE,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
g_object_class_install_property(gobject_class, TR_TORRENT_BACKEND, pspec);
pspec = g_param_spec_string("download-directory", "Download directory",
"Directory to download files to", NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
@ -141,23 +132,20 @@ tr_torrent_class_init(gpointer g_class, gpointer g_class_data SHUTUP) {
"Is the torrent paused or running", TRUE,
G_PARAM_READWRITE);
g_object_class_install_property(gobject_class, TR_TORRENT_PAUSED, pspec);
klass->paused_signal_id = g_signal_newv("politely-stopped",
G_TYPE_FROM_CLASS(g_class),
G_SIGNAL_RUN_LAST, NULL, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0, NULL);
}
static void
tr_torrent_init(GTypeInstance *instance, gpointer g_class SHUTUP) {
TrTorrent *self = (TrTorrent *)instance;
#ifdef REFDBG
fprintf( stderr, "torrent %p init\n", self );
#endif
self->handle = NULL;
self->core = NULL;
self->dir = NULL;
self->closing = FALSE;
self->delfile = NULL;
self->severed = FALSE;
self->disposed = FALSE;
}
@ -166,7 +154,7 @@ tr_torrent_set_property(GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec) {
TrTorrent *self = (TrTorrent*)object;
if(self->disposed)
if(self->severed)
return;
switch(property_id) {
@ -176,10 +164,6 @@ tr_torrent_set_property(GObject *object, guint property_id,
if(NULL != self->handle && NULL != self->dir)
tr_torrent_set_folder(self);
break;
case TR_TORRENT_BACKEND:
g_assert(NULL == self->core);
self->core = g_object_ref( g_value_get_object( value ) );
break;
case TR_TORRENT_DIR:
g_assert(NULL == self->dir);
self->dir = g_value_dup_string(value);
@ -203,16 +187,13 @@ tr_torrent_get_property(GObject *object, guint property_id,
GValue *value, GParamSpec *pspec) {
TrTorrent *self = (TrTorrent*)object;
if(self->disposed)
if(self->severed)
return;
switch(property_id) {
case TR_TORRENT_HANDLE:
g_value_set_pointer(value, self->handle);
break;
case TR_TORRENT_BACKEND:
g_value_set_object( value, self->core );
break;
case TR_TORRENT_DIR:
g_value_set_string(value, (NULL != self->dir ? self->dir :
tr_torrentGetFolder(self->handle)));
@ -235,17 +216,13 @@ tr_torrent_dispose(GObject *obj) {
return;
self->disposed = TRUE;
if(NULL != self->handle) {
if(!tr_torrent_paused(self))
tr_torrentStop(self->handle);
tr_torrentClose( self->handle );
self->handle = NULL;
}
#ifdef REFDBG
fprintf( stderr, "torrent %p dispose\n", self );
#endif
if( NULL != self->core )
if( !self->severed )
{
g_object_unref( self->core );
self->core = NULL;
tr_torrent_sever( self );
}
if(NULL != self->delfile)
@ -255,11 +232,39 @@ tr_torrent_dispose(GObject *obj) {
parent->dispose(obj);
}
void
tr_torrent_sever( TrTorrent * self )
{
TR_IS_TORRENT( self );
if( self->severed )
{
return;
}
#ifdef REFDBG
fprintf( stderr, "torrent %p sever\n", self );
#endif
if( NULL == self->handle )
{
self->severed = TRUE;
return;
}
if( !tr_torrent_paused( self ) )
{
tr_torrentStop( self->handle );
}
tr_torrentClose( self->handle );
self->severed = TRUE;
}
tr_torrent_t *
tr_torrent_handle(TrTorrent *tor) {
TR_IS_TORRENT(tor);
if(tor->disposed)
if(tor->severed)
return NULL;
return tor->handle;
@ -269,7 +274,7 @@ tr_stat_t *
tr_torrent_stat(TrTorrent *tor) {
TR_IS_TORRENT(tor);
if(tor->disposed)
if(tor->severed)
return NULL;
return tr_torrentStat(tor->handle);
@ -279,27 +284,24 @@ tr_info_t *
tr_torrent_info(TrTorrent *tor) {
TR_IS_TORRENT(tor);
if(tor->disposed)
if(tor->severed)
return NULL;
return tr_torrentInfo(tor->handle);
}
TrTorrent *
tr_torrent_new( GObject * core, const char *torrent, const char *dir,
tr_torrent_new( tr_handle_t * back, const char *torrent, const char *dir,
guint flags, char **err) {
TrTorrent *ret;
tr_torrent_t *handle;
tr_handle_t *back;
int errcode, trflags;
gboolean boolval;
TR_IS_CORE( core );
g_assert(NULL != dir);
*err = NULL;
back = tr_core_handle( TR_CORE( core ) );
trflags = 0;
if((TR_TORNEW_SAVE_COPY|TR_TORNEW_SAVE_MOVE) & flags)
trflags |= TR_FLAG_SAVE;
@ -331,7 +333,7 @@ tr_torrent_new( GObject * core, const char *torrent, const char *dir,
tr_torrentDisablePex( handle, !boolval );
ret = g_object_new(TR_TORRENT_TYPE, "torrent-handle", handle,
"backend", core, "download-directory", dir, NULL);
"download-directory", dir, NULL);
g_object_set(ret, "paused", (TR_TORNEW_PAUSED & flags ? TRUE : FALSE), NULL);
@ -342,7 +344,7 @@ tr_torrent_new( GObject * core, const char *torrent, const char *dir,
}
TrTorrent *
tr_torrent_new_with_state( GObject * core, benc_val_t * state,
tr_torrent_new_with_state( tr_handle_t * back, benc_val_t * state,
guint forcedflags, char ** err)
{
int ii;
@ -396,7 +398,7 @@ tr_torrent_new_with_state( GObject * core, benc_val_t * state,
flags |= forcedflags;
}
return tr_torrent_new( core, torrent, dir, flags, err );
return tr_torrent_new( back, torrent, dir, flags, err );
}
#define SETSTRVAL(vv, ss) \
@ -412,10 +414,7 @@ tr_torrent_get_state(TrTorrent *tor, benc_val_t *state) {
TR_IS_TORRENT(tor);
if(tor->disposed)
return;
if(tor->closing)
if(tor->severed)
return;
state->type = TYPE_DICT;
@ -441,7 +440,7 @@ void
tr_torrent_state_saved(TrTorrent *tor) {
TR_IS_TORRENT(tor);
if(tor->disposed)
if(tor->severed)
return;
if(NULL != tor->delfile) {
@ -471,45 +470,3 @@ tr_torrent_paused(TrTorrent *tor) {
return (TR_STATUS_INACTIVE & st->status ? TRUE : FALSE);
}
void
tr_torrent_stop_politely(TrTorrent *tor) {
tr_stat_t *st;
TR_IS_TORRENT(tor);
if(tor->disposed)
return;
if(!tor->closing) {
st = tr_torrent_stat(tor);
tor->closing = TRUE;
if(TR_STATUS_ACTIVE & st->status)
tr_torrentStop(tor->handle);
}
}
tr_stat_t *
tr_torrent_stat_polite( TrTorrent * tor, gboolean timeout )
{
TrTorrentClass * klass;
tr_stat_t * st;
TR_IS_TORRENT( tor );
if( tor->disposed )
{
return NULL;
}
st = tr_torrentStat( tor->handle );
if( tor->closing && ( TR_STATUS_PAUSE & st->status || timeout ) )
{
tor->closing = FALSE;
klass = g_type_class_peek( TR_TORRENT_TYPE );
g_signal_emit( tor, klass->paused_signal_id, 0, NULL );
return tr_torrent_stat_polite( tor, FALSE );
}
return st;
}

View File

@ -54,16 +54,14 @@ typedef struct _TrTorrentClass TrTorrentClass;
struct _TrTorrent {
GObject parent;
tr_torrent_t *handle;
GObject *core;
char *dir;
gboolean closing;
char *delfile;
gboolean severed;
gboolean disposed;
};
struct _TrTorrentClass {
GObjectClass parent;
int paused_signal_id;
};
GType
@ -91,25 +89,22 @@ tr_torrent_info(TrTorrent *tor);
#ifdef TR_WANT_TORRENT_PRIVATE
TrTorrent *
tr_torrent_new(GObject *backend, const char *torrent, const char *dir,
guint flags, char **err);
tr_torrent_new( tr_handle_t * handle, const char *torrent, const char *dir,
guint flags, char **err);
TrTorrent *
tr_torrent_new_with_state( GObject * backend, benc_val_t * state,
tr_torrent_new_with_state( tr_handle_t * handle, benc_val_t * state,
guint flags, char ** err );
void
tr_torrent_stop_politely(TrTorrent *tor);
tr_stat_t *
tr_torrent_stat_polite( TrTorrent * tor, gboolean timeout );
void
tr_torrent_get_state(TrTorrent *tor, benc_val_t *state);
void
tr_torrent_state_saved(TrTorrent *tor);
void
tr_torrent_sever( TrTorrent * tor );
#endif /* TR_WANT_TORRENT_PRIVATE */
#endif