mirror of
https://github.com/transmission/transmission.git
synced 2025-12-24 20:35:36 +00:00
Implement addfiles-detailed message.
This commit is contained in:
@@ -61,6 +61,8 @@ struct dirdata
|
||||
GtkWidget * widget;
|
||||
TrCore * core;
|
||||
GList * files;
|
||||
uint8_t * data;
|
||||
size_t size;
|
||||
enum tr_torrent_action action;
|
||||
gboolean paused;
|
||||
};
|
||||
@@ -545,15 +547,24 @@ fmtpeercount( GtkLabel * label, int count )
|
||||
}
|
||||
|
||||
void
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files,
|
||||
enum tr_torrent_action act, gboolean paused )
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
|
||||
size_t size, enum tr_torrent_action act, gboolean paused )
|
||||
{
|
||||
struct dirdata * stuff;
|
||||
GtkWidget * wind;
|
||||
|
||||
stuff = g_new( struct dirdata, 1 );
|
||||
stuff = g_new0( struct dirdata, 1 );
|
||||
stuff->core = core;
|
||||
stuff->files = dupstrlist( files );
|
||||
if( NULL != files )
|
||||
{
|
||||
stuff->files = dupstrlist( files );
|
||||
}
|
||||
if( NULL != data )
|
||||
{
|
||||
stuff->data = g_new( uint8_t, size );
|
||||
memcpy( stuff->data, data, size );
|
||||
stuff->size = size;
|
||||
}
|
||||
stuff->action = act;
|
||||
stuff->paused = paused;
|
||||
|
||||
@@ -608,6 +619,11 @@ promptresp( GtkWidget * widget, gint resp, gpointer data )
|
||||
tr_core_add_dir( stuff->core, ii->data, dir,
|
||||
stuff->action, stuff->paused );
|
||||
}
|
||||
if( NULL != stuff->data )
|
||||
{
|
||||
tr_core_add_data_dir( stuff->core, stuff->data, stuff->size, dir,
|
||||
stuff->paused );
|
||||
}
|
||||
tr_core_torrents_added( stuff->core );
|
||||
g_free( dir );
|
||||
}
|
||||
@@ -618,6 +634,7 @@ promptresp( GtkWidget * widget, gint resp, gpointer data )
|
||||
}
|
||||
|
||||
freestrlist( stuff->files );
|
||||
g_free( stuff->data );
|
||||
g_free( stuff );
|
||||
gtk_widget_destroy( widget );
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ makeinfowind( GtkWindow * parent, GtkTreeModel * model, GtkTreePath * path,
|
||||
|
||||
/* prompt for a download directory for torrents, then add them */
|
||||
void
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files,
|
||||
enum tr_torrent_action act, gboolean paused );
|
||||
promptfordir( GtkWindow * parent, TrCore * core, GList * files, uint8_t * data,
|
||||
size_t size, enum tr_torrent_action act, gboolean paused );
|
||||
|
||||
/* prompt if the user wants to quit, calls func with cbdata if they do */
|
||||
void
|
||||
|
||||
66
gtk/ipc.c
66
gtk/ipc.c
@@ -103,6 +103,8 @@ cli_io_sent(GSource *source, unsigned int id, void *vdata);
|
||||
static void
|
||||
smsg_add( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg );
|
||||
static void
|
||||
smsg_addone( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg );
|
||||
static void
|
||||
smsg_quit( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg );
|
||||
static void
|
||||
smsg_info( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg );
|
||||
@@ -142,6 +144,7 @@ ipc_socket_setup( GtkWindow * parent, TrCore * core )
|
||||
con->msgs = ipc_initmsgs();
|
||||
if( NULL == con->msgs ||
|
||||
0 > ipc_addmsg( con->msgs, IPC_MSG_ADDMANYFILES, smsg_add ) ||
|
||||
0 > ipc_addmsg( con->msgs, IPC_MSG_ADDONEFILE, smsg_addone ) ||
|
||||
0 > ipc_addmsg( con->msgs, IPC_MSG_GETINFO, smsg_info ) ||
|
||||
0 > ipc_addmsg( con->msgs, IPC_MSG_GETINFOALL, smsg_infoall ) ||
|
||||
0 > ipc_addmsg( con->msgs, IPC_MSG_GETSTAT, smsg_info ) ||
|
||||
@@ -550,6 +553,69 @@ smsg_add( enum ipc_msg id SHUTUP, benc_val_t * val, int64_t tag, void * arg )
|
||||
simpleresp( con, tag, IPC_MSG_OK );
|
||||
}
|
||||
|
||||
static void
|
||||
smsg_addone( enum ipc_msg id SHUTUP, benc_val_t * val, int64_t tag,
|
||||
void * arg )
|
||||
{
|
||||
struct constate * con = arg;
|
||||
struct constate_serv * srv = &con->u.serv;
|
||||
enum tr_torrent_action action;
|
||||
benc_val_t * file, * data, * dir, * start;
|
||||
gboolean paused;
|
||||
|
||||
if( NULL == val || TYPE_DICT != val->type )
|
||||
{
|
||||
simpleresp( con, tag, IPC_MSG_NOTSUP );
|
||||
return;
|
||||
}
|
||||
|
||||
file = tr_bencDictFind( val, "file" );
|
||||
data = tr_bencDictFind( val, "data" );
|
||||
dir = tr_bencDictFind( val, "directory" );
|
||||
start = tr_bencDictFind( val, "autostart" );
|
||||
|
||||
if( ( NULL != file && TYPE_STR != file->type ) ||
|
||||
( NULL != data && TYPE_STR != data->type ) ||
|
||||
( NULL != dir && TYPE_STR != dir->type ) ||
|
||||
( NULL != start && TYPE_INT != start->type ) )
|
||||
{
|
||||
simpleresp( con, tag, IPC_MSG_NOTSUP );
|
||||
return;
|
||||
}
|
||||
|
||||
action = toraddaction( tr_prefs_get( PREF_ID_ADDIPC ) );
|
||||
paused = ( NULL == start || start->val.i ? FALSE : TRUE );
|
||||
if( NULL != file )
|
||||
{
|
||||
if( NULL == dir )
|
||||
{
|
||||
tr_core_add( srv->core, file->val.s.s, action, paused );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_core_add_dir( srv->core, file->val.s.s, dir->val.s.s,
|
||||
action, paused );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( NULL == dir )
|
||||
{
|
||||
tr_core_add_data( srv->core, data->val.s.s, data->val.s.i,
|
||||
paused );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_core_add_data_dir( srv->core, data->val.s.s, data->val.s.i,
|
||||
dir->val.s.s, paused );
|
||||
}
|
||||
}
|
||||
tr_core_torrents_added( TR_CORE( srv->core ) );
|
||||
|
||||
/* XXX should send info response back with torrent ids */
|
||||
simpleresp( con, tag, IPC_MSG_OK );
|
||||
}
|
||||
|
||||
static void
|
||||
smsg_quit( enum ipc_msg id SHUTUP, benc_val_t * val SHUTUP, int64_t tag SHUTUP,
|
||||
void * arg SHUTUP )
|
||||
|
||||
15
gtk/main.c
15
gtk/main.c
@@ -170,6 +170,8 @@ coreerr( TrCore * core, enum tr_core_err code, const char * msg,
|
||||
static void
|
||||
coreprompt( TrCore *, GList *, enum tr_torrent_action, gboolean, gpointer );
|
||||
static void
|
||||
corepromptdata( TrCore *, uint8_t *, size_t, gboolean, gpointer );
|
||||
static void
|
||||
readinitialprefs( struct cbdata * cbdata );
|
||||
static void
|
||||
prefschanged( GtkWidget * widget, int id, gpointer data );
|
||||
@@ -389,6 +391,8 @@ appsetup( TrWindow * wind, benc_val_t * state, GList * args, gboolean paused )
|
||||
g_signal_connect( cbdata->core, "error", G_CALLBACK( coreerr ), cbdata );
|
||||
g_signal_connect( cbdata->core, "directory-prompt",
|
||||
G_CALLBACK( coreprompt ), cbdata );
|
||||
g_signal_connect( cbdata->core, "directory-prompt-data",
|
||||
G_CALLBACK( corepromptdata ), cbdata );
|
||||
g_signal_connect_swapped( cbdata->core, "quit",
|
||||
G_CALLBACK( wannaquit ), cbdata );
|
||||
|
||||
@@ -740,7 +744,16 @@ coreprompt( TrCore * core, GList * paths, enum tr_torrent_action act,
|
||||
{
|
||||
struct cbdata * cbdata = gdata;
|
||||
|
||||
promptfordir( cbdata->wind, core, paths, act, paused );
|
||||
promptfordir( cbdata->wind, core, paths, NULL, 0, act, paused );
|
||||
}
|
||||
|
||||
void
|
||||
corepromptdata( TrCore * core, uint8_t * data, size_t size,
|
||||
gboolean paused, gpointer gdata )
|
||||
{
|
||||
struct cbdata * cbdata = gdata;
|
||||
|
||||
promptfordir( cbdata->wind, core, NULL, data, size, TR_TOR_LEAVE, paused );
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -49,6 +49,9 @@ tr_core_marshal_err( GClosure * closure, GValue * ret, guint count,
|
||||
void
|
||||
tr_core_marshal_prompt( GClosure * closure, GValue * ret, guint count,
|
||||
const GValue * vals, gpointer hint, gpointer marshal );
|
||||
void
|
||||
tr_core_marshal_data( GClosure * closure, GValue * ret, guint count,
|
||||
const GValue * vals, gpointer hint, gpointer marshal );
|
||||
static void
|
||||
tr_core_dispose( GObject * obj );
|
||||
static int
|
||||
@@ -109,6 +112,14 @@ tr_core_class_init( gpointer g_class, gpointer g_class_data SHUTUP )
|
||||
3, G_TYPE_POINTER, G_TYPE_INT,
|
||||
G_TYPE_BOOLEAN );
|
||||
|
||||
core_class = TR_CORE_CLASS( g_class );
|
||||
core_class->promptdatasig = g_signal_new( "directory-prompt-data",
|
||||
G_TYPE_FROM_CLASS( g_class ),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
tr_core_marshal_data,
|
||||
G_TYPE_NONE, 3, G_TYPE_STRING,
|
||||
G_TYPE_UINT, G_TYPE_BOOLEAN );
|
||||
|
||||
core_class = TR_CORE_CLASS( g_class );
|
||||
core_class->quitsig = g_signal_new( "quit", G_TYPE_FROM_CLASS( g_class ),
|
||||
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
|
||||
@@ -168,6 +179,33 @@ tr_core_marshal_prompt( GClosure * closure, GValue * ret SHUTUP, guint count,
|
||||
callback( inst, paths, action, paused, gdata );
|
||||
}
|
||||
|
||||
void
|
||||
tr_core_marshal_data( GClosure * closure, GValue * ret SHUTUP, guint count,
|
||||
const GValue * vals, gpointer hint SHUTUP,
|
||||
gpointer marshal )
|
||||
{
|
||||
typedef void (*TRMarshalPrompt)
|
||||
( gpointer, uint8_t *, size_t, gboolean, gpointer );
|
||||
TRMarshalPrompt callback;
|
||||
GCClosure * cclosure = (GCClosure*) closure;
|
||||
uint8_t * data;
|
||||
size_t size;
|
||||
gboolean paused;
|
||||
gpointer inst, gdata;
|
||||
|
||||
g_return_if_fail( 4 == count );
|
||||
|
||||
inst = g_value_peek_pointer( vals );
|
||||
data = (char *) g_value_get_string( vals + 1 );
|
||||
size = g_value_get_uint( vals + 2 );
|
||||
paused = g_value_get_boolean( vals + 3 );
|
||||
gdata = closure->data;
|
||||
|
||||
callback = (TRMarshalPrompt) ( NULL == marshal ?
|
||||
cclosure->callback : marshal );
|
||||
callback( inst, data, size, paused, gdata );
|
||||
}
|
||||
|
||||
void
|
||||
tr_core_init( GTypeInstance * instance, gpointer g_class SHUTUP )
|
||||
{
|
||||
@@ -583,6 +621,50 @@ tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
|
||||
return count;
|
||||
}
|
||||
|
||||
gboolean
|
||||
tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused )
|
||||
{
|
||||
TrCoreClass * class;
|
||||
const char * pref;
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
pref = tr_prefs_get( PREF_ID_ASKDIR );
|
||||
if( NULL != pref && strbool( pref ) )
|
||||
{
|
||||
class = g_type_class_peek( TR_CORE_TYPE );
|
||||
g_signal_emit( self, class->promptdatasig, 0, data, size, paused );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return tr_core_add_data_dir( self, data, size, getdownloaddir(), paused );
|
||||
}
|
||||
|
||||
gboolean
|
||||
tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
|
||||
const char * dir, gboolean paused )
|
||||
{
|
||||
TrTorrent * tor;
|
||||
char * errstr;
|
||||
|
||||
TR_IS_CORE( self );
|
||||
|
||||
errstr = NULL;
|
||||
tor = tr_torrent_new_with_data( self->handle, data, size, dir,
|
||||
paused, &errstr );
|
||||
if( NULL == tor )
|
||||
{
|
||||
tr_core_errsig( self, TR_CORE_ERR_ADD_TORRENT, errstr );
|
||||
g_free( errstr );
|
||||
return FALSE;
|
||||
}
|
||||
g_assert( NULL == errstr );
|
||||
|
||||
tr_core_insert( self, tor );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
tr_core_torrents_added( TrCore * self )
|
||||
{
|
||||
|
||||
@@ -76,6 +76,9 @@ struct _TrCoreClass
|
||||
void handler( TrCore *, GList *, enum tr_torrent_action, gboolean,
|
||||
gpointer ) */
|
||||
int promptsig;
|
||||
/* "directory-prompt-data" signal:
|
||||
void handler( TrCore *, uint8_t *, size_t, gboolean, gpointer ) */
|
||||
int promptdatasig;
|
||||
/* "quit" signal:
|
||||
void handler( TrCore *, gpointer ) */
|
||||
int quitsig;
|
||||
@@ -138,6 +141,15 @@ int
|
||||
tr_core_add_list( TrCore * self, GList * paths, enum tr_torrent_action act,
|
||||
gboolean paused );
|
||||
|
||||
/* Add the torrent data in the given buffer */
|
||||
gboolean
|
||||
tr_core_add_data( TrCore * self, uint8_t * data, size_t size, gboolean paused );
|
||||
|
||||
/* Add the torrent data in the given buffer with the given download directory */
|
||||
gboolean
|
||||
tr_core_add_data_dir( TrCore * self, uint8_t * data, size_t size,
|
||||
const char * dir, gboolean paused );
|
||||
|
||||
/* Save state, update model, and signal the end of a torrent cluster */
|
||||
void
|
||||
tr_core_torrents_added( TrCore * self );
|
||||
|
||||
@@ -372,6 +372,41 @@ tr_torrent_new( tr_handle_t * back, const char *torrent, const char *dir,
|
||||
return ret;
|
||||
}
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new_with_data( tr_handle_t * back, uint8_t * data, size_t size,
|
||||
const char * dir, gboolean paused, char ** err )
|
||||
{
|
||||
tr_torrent_t * handle;
|
||||
int errcode;
|
||||
|
||||
g_assert( NULL != dir );
|
||||
|
||||
*err = NULL;
|
||||
|
||||
errcode = -1;
|
||||
handle = tr_torrentInitData( back, data, size, NULL, TR_FLAG_SAVE,
|
||||
&errcode );
|
||||
|
||||
if( NULL == handle )
|
||||
{
|
||||
switch( errcode )
|
||||
{
|
||||
case TR_EINVALID:
|
||||
*err = g_strdup( _("not a valid torrent file") );
|
||||
break;
|
||||
case TR_EDUPLICATE:
|
||||
*err = g_strdup( _("torrent is already open") );
|
||||
break;
|
||||
default:
|
||||
*err = g_strdup( "" );
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return maketorrent( handle, dir, paused );
|
||||
}
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new_with_state( tr_handle_t * back, benc_val_t * state,
|
||||
gboolean forcedpause, char ** err )
|
||||
|
||||
@@ -90,6 +90,10 @@ TrTorrent *
|
||||
tr_torrent_new( tr_handle_t * handle, const char * path, const char * dir,
|
||||
enum tr_torrent_action act, gboolean paused, char ** err);
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new_with_data( tr_handle_t * handle, uint8_t * data, size_t size,
|
||||
const char * dir, gboolean paused, char ** err );
|
||||
|
||||
TrTorrent *
|
||||
tr_torrent_new_with_state( tr_handle_t * handle, benc_val_t * state,
|
||||
gboolean forcepaused, char ** err );
|
||||
|
||||
Reference in New Issue
Block a user