mirror of
https://github.com/transmission/transmission.git
synced 2025-12-24 12:28:52 +00:00
GObject-derived wrappers are used for tr_handle_t and tr_torrent_t. Use bencoding to store prefs and state file. Make sure to always group error messages when adding multiple torrents at once. Remove some unused code. Many miscellaneous cleanups.
239 lines
5.6 KiB
C
239 lines
5.6 KiB
C
#include <string.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <glib/gi18n.h>
|
|
|
|
#define TR_WANT_TORRENT_PRIVATE
|
|
|
|
#include "transmission.h"
|
|
#include "bencode.h"
|
|
|
|
#include "conf.h"
|
|
#include "tr_backend.h"
|
|
#include "tr_torrent.h"
|
|
#include "util.h"
|
|
|
|
/*
|
|
enum {
|
|
TR_BACKEND_HANDLE = 1,
|
|
};
|
|
*/
|
|
|
|
static void
|
|
tr_backend_init(GTypeInstance *instance, gpointer g_class);
|
|
static void
|
|
tr_backend_set_property(GObject *object, guint property_id,
|
|
const GValue *value, GParamSpec *pspec);
|
|
static void
|
|
tr_backend_get_property(GObject *object, guint property_id,
|
|
GValue *value, GParamSpec *pspec);
|
|
static void
|
|
tr_backend_class_init(gpointer g_class, gpointer g_class_data);
|
|
static void
|
|
tr_backend_dispose(GObject *obj);
|
|
static void
|
|
tr_backend_finalize(GObject *obj);
|
|
static void
|
|
tr_backend_torrent_finalized(gpointer gdata, GObject *tor);
|
|
|
|
GType
|
|
tr_backend_get_type(void) {
|
|
static GType type = 0;
|
|
|
|
if(0 == type) {
|
|
static const GTypeInfo info = {
|
|
sizeof (TrBackendClass),
|
|
NULL, /* base_init */
|
|
NULL, /* base_finalize */
|
|
tr_backend_class_init, /* class_init */
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (TrBackend),
|
|
0, /* n_preallocs */
|
|
tr_backend_init, /* instance_init */
|
|
NULL,
|
|
};
|
|
type = g_type_register_static(G_TYPE_OBJECT, "TrBackendType", &info, 0);
|
|
}
|
|
return type;
|
|
}
|
|
|
|
static void
|
|
tr_backend_class_init(gpointer g_class, gpointer g_class_data SHUTUP) {
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
|
|
//GParamSpec *pspec;
|
|
|
|
gobject_class->set_property = tr_backend_set_property;
|
|
gobject_class->get_property = tr_backend_get_property;
|
|
gobject_class->dispose = tr_backend_dispose;
|
|
gobject_class->finalize = tr_backend_finalize;
|
|
|
|
/*
|
|
pspec = g_param_spec_pointer("backend-handle", _("Backend handle"),
|
|
_("Backend handle from libtransmission"),
|
|
G_PARAM_READWRITE);
|
|
g_object_class_install_property(gobject_class, TR_BACKEND_HANDLE, pspec);
|
|
*/
|
|
}
|
|
|
|
static void
|
|
tr_backend_init(GTypeInstance *instance, gpointer g_class SHUTUP) {
|
|
TrBackend *self = (TrBackend *)instance;
|
|
|
|
self->handle = tr_init();
|
|
self->disposed = FALSE;
|
|
}
|
|
|
|
static void
|
|
tr_backend_set_property(GObject *object, guint property_id,
|
|
const GValue *value SHUTUP, GParamSpec *pspec) {
|
|
TrBackend *self = (TrBackend*)object;
|
|
|
|
if(self->disposed)
|
|
return;
|
|
|
|
switch(property_id) {
|
|
/*
|
|
case TR_BACKEND_HANDLE:
|
|
g_assert(NULL == self->handle);
|
|
self->handle = g_value_get_pointer(value);
|
|
break;
|
|
*/
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
tr_backend_get_property(GObject *object, guint property_id,
|
|
GValue *value SHUTUP, GParamSpec *pspec) {
|
|
TrBackend *self = (TrBackend*)object;
|
|
|
|
if(self->disposed)
|
|
return;
|
|
|
|
switch(property_id) {
|
|
/*
|
|
case TR_BACKEND_HANDLE:
|
|
g_value_set_pointer(value, self->handle);
|
|
break;
|
|
*/
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
tr_backend_dispose(GObject *obj) {
|
|
GObjectClass *parent = g_type_class_peek(g_type_parent(TR_BACKEND_TYPE));
|
|
TrBackend *self = (TrBackend*)obj;
|
|
GList *ii;
|
|
|
|
if(self->disposed)
|
|
return;
|
|
self->disposed = TRUE;
|
|
|
|
fprintf(stderr, "back dispose %p\n", self);
|
|
|
|
if(NULL != self->torrents) {
|
|
for(ii = self->torrents; NULL != ii; ii = ii->next)
|
|
g_object_weak_unref(ii->data, tr_backend_torrent_finalized, self);
|
|
g_list_free(self->torrents);
|
|
self->torrents = NULL;
|
|
}
|
|
|
|
/* Chain up to the parent class */
|
|
parent->dispose(obj);
|
|
}
|
|
|
|
static void
|
|
tr_backend_finalize(GObject *obj) {
|
|
GObjectClass *parent = g_type_class_peek(g_type_parent(TR_BACKEND_TYPE));
|
|
TrBackend *self = (TrBackend *)obj;
|
|
|
|
fprintf(stderr, "back finalize %p\n", self);
|
|
|
|
if(NULL != self->handle)
|
|
tr_close(self->handle);
|
|
|
|
/* Chain up to the parent class */
|
|
parent->finalize(obj);
|
|
}
|
|
|
|
TrBackend *
|
|
tr_backend_new(void) {
|
|
return g_object_new(TR_BACKEND_TYPE, NULL);
|
|
}
|
|
|
|
tr_handle_t *
|
|
tr_backend_handle(TrBackend *back) {
|
|
TR_IS_BACKEND(back);
|
|
|
|
return back->handle;
|
|
}
|
|
|
|
void
|
|
tr_backend_save_state(TrBackend *back, char **errstr) {
|
|
benc_val_t state;
|
|
int ii;
|
|
GList *jj;
|
|
|
|
TR_IS_BACKEND(back);
|
|
|
|
bzero(&state, sizeof(state));
|
|
state.type = TYPE_LIST;
|
|
state.val.l.alloc = state.val.l.count = g_list_length(back->torrents);
|
|
state.val.l.vals = g_new0(benc_val_t, state.val.l.alloc);
|
|
|
|
for(ii = 0, jj = back->torrents; NULL != jj; ii++, jj = jj->next)
|
|
tr_torrent_get_state(jj->data, state.val.l.vals + ii);
|
|
|
|
cf_savestate(&state, errstr);
|
|
tr_bencFree(&state);
|
|
}
|
|
|
|
GList *
|
|
tr_backend_load_state(TrBackend *back, benc_val_t *state, GList **errors) {
|
|
GList *ret = NULL;
|
|
int ii;
|
|
TrTorrent *tor;
|
|
char *errstr;
|
|
|
|
TR_IS_BACKEND(back);
|
|
|
|
if(TYPE_LIST != state->type)
|
|
return NULL;
|
|
|
|
for(ii = 0; ii < state->val.l.count; ii++) {
|
|
errstr = NULL;
|
|
tor = tr_torrent_new_with_state(G_OBJECT(back), state->val.l.vals + ii,
|
|
&errstr);
|
|
if(NULL != errstr)
|
|
*errors = g_list_append(*errors, errstr);
|
|
if(NULL != tor)
|
|
ret = g_list_append(ret, tor);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
tr_backend_add_torrent(TrBackend *back, GObject *tor) {
|
|
TR_IS_BACKEND(back);
|
|
TR_IS_TORRENT(tor);
|
|
|
|
g_object_weak_ref(tor, tr_backend_torrent_finalized, back);
|
|
back->torrents = g_list_append(back->torrents, tor);
|
|
}
|
|
|
|
static void
|
|
tr_backend_torrent_finalized(gpointer gdata, GObject *tor) {
|
|
TrBackend *back = gdata;
|
|
|
|
TR_IS_BACKEND(back);
|
|
|
|
back->torrents = g_list_remove(back->torrents, tor);
|
|
}
|