#include #include #include #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; 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; 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); } void tr_backend_stop_torrents(TrBackend *back) { GList *ii; TR_IS_BACKEND(back); for(ii = back->torrents; NULL != ii; ii = ii->next) if(TR_STATUS_ACTIVE & tr_torrent_stat(ii->data)->status) tr_torrentStop(tr_torrent_handle(ii->data)); } gboolean tr_backend_torrents_stopped(TrBackend *back) { GList *ii; TR_IS_BACKEND(back); for(ii = back->torrents; NULL != ii; ii = ii->next) if(TR_STATUS_ACTIVE & tr_torrent_stat(ii->data)->status) return FALSE; return TRUE; }