source: trunk/gtk/tr_backend.c @ 248

Last change on this file since 248 was 248, checked in by joshe, 16 years ago

Major internal restructuring for the GTK GUI,

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.

File size: 5.6 KB
Line 
1#include <string.h>
2
3#include <gtk/gtk.h>
4#include <glib/gi18n.h>
5
6#define TR_WANT_TORRENT_PRIVATE
7
8#include "transmission.h"
9#include "bencode.h"
10
11#include "conf.h"
12#include "tr_backend.h"
13#include "tr_torrent.h"
14#include "util.h"
15
16/*
17enum {
18  TR_BACKEND_HANDLE = 1,
19};
20*/
21
22static void
23tr_backend_init(GTypeInstance *instance, gpointer g_class);
24static void
25tr_backend_set_property(GObject *object, guint property_id,
26                        const GValue *value, GParamSpec *pspec);
27static void
28tr_backend_get_property(GObject *object, guint property_id,
29                        GValue *value, GParamSpec *pspec);
30static void
31tr_backend_class_init(gpointer g_class, gpointer g_class_data);
32static void
33tr_backend_dispose(GObject *obj);
34static void
35tr_backend_finalize(GObject *obj);
36static void
37tr_backend_torrent_finalized(gpointer gdata, GObject *tor);
38
39GType
40tr_backend_get_type(void) {
41  static GType type = 0;
42
43  if(0 == type) {
44    static const GTypeInfo info = {
45      sizeof (TrBackendClass),
46      NULL,   /* base_init */
47      NULL,   /* base_finalize */
48      tr_backend_class_init,   /* class_init */
49      NULL,   /* class_finalize */
50      NULL,   /* class_data */
51      sizeof (TrBackend),
52      0,      /* n_preallocs */
53      tr_backend_init, /* instance_init */
54      NULL,
55    };
56    type = g_type_register_static(G_TYPE_OBJECT, "TrBackendType", &info, 0);
57  }
58  return type;
59}
60
61static void
62tr_backend_class_init(gpointer g_class, gpointer g_class_data SHUTUP) {
63  GObjectClass *gobject_class = G_OBJECT_CLASS(g_class);
64  //GParamSpec *pspec;
65
66  gobject_class->set_property = tr_backend_set_property;
67  gobject_class->get_property = tr_backend_get_property;
68  gobject_class->dispose = tr_backend_dispose;
69  gobject_class->finalize = tr_backend_finalize;
70
71/*
72  pspec = g_param_spec_pointer("backend-handle", _("Backend handle"),
73                               _("Backend handle from libtransmission"),
74                               G_PARAM_READWRITE);
75  g_object_class_install_property(gobject_class, TR_BACKEND_HANDLE, pspec);
76*/
77}
78
79static void
80tr_backend_init(GTypeInstance *instance, gpointer g_class SHUTUP) {
81  TrBackend *self = (TrBackend *)instance;
82
83  self->handle = tr_init();
84  self->disposed = FALSE;
85}
86
87static void
88tr_backend_set_property(GObject *object, guint property_id,
89                        const GValue *value SHUTUP, GParamSpec *pspec) {
90  TrBackend *self = (TrBackend*)object;
91
92  if(self->disposed)
93    return;
94
95  switch(property_id) {
96/*
97    case TR_BACKEND_HANDLE:
98      g_assert(NULL == self->handle);
99      self->handle = g_value_get_pointer(value);
100      break;
101*/
102    default:
103      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
104      break;
105  }
106}
107
108static void
109tr_backend_get_property(GObject *object, guint property_id,
110                        GValue *value SHUTUP, GParamSpec *pspec) {
111  TrBackend *self = (TrBackend*)object;
112
113  if(self->disposed)
114    return;
115
116  switch(property_id) {
117/*
118    case TR_BACKEND_HANDLE:
119      g_value_set_pointer(value, self->handle);
120      break;
121*/
122    default:
123      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
124      break;
125  }
126}
127
128static void
129tr_backend_dispose(GObject *obj) {
130  GObjectClass *parent = g_type_class_peek(g_type_parent(TR_BACKEND_TYPE));
131  TrBackend *self = (TrBackend*)obj;
132  GList *ii;
133
134  if(self->disposed)
135    return;
136  self->disposed = TRUE;
137
138  fprintf(stderr, "back dispose %p\n", self);
139
140  if(NULL != self->torrents) {
141    for(ii = self->torrents; NULL != ii; ii = ii->next)
142      g_object_weak_unref(ii->data, tr_backend_torrent_finalized, self);
143    g_list_free(self->torrents);
144    self->torrents = NULL;
145  }
146
147  /* Chain up to the parent class */
148  parent->dispose(obj);
149}
150
151static void
152tr_backend_finalize(GObject *obj) {
153  GObjectClass *parent = g_type_class_peek(g_type_parent(TR_BACKEND_TYPE));
154  TrBackend *self = (TrBackend *)obj;
155
156  fprintf(stderr, "back finalize %p\n", self);
157
158  if(NULL != self->handle)
159    tr_close(self->handle);
160
161  /* Chain up to the parent class */
162  parent->finalize(obj);
163}
164
165TrBackend *
166tr_backend_new(void) {
167  return g_object_new(TR_BACKEND_TYPE, NULL);
168}
169
170tr_handle_t *
171tr_backend_handle(TrBackend *back) {
172  TR_IS_BACKEND(back);
173
174  return back->handle;
175}
176
177void
178tr_backend_save_state(TrBackend *back, char **errstr) {
179  benc_val_t state;
180  int ii;
181  GList *jj;
182
183  TR_IS_BACKEND(back);
184
185  bzero(&state, sizeof(state));
186  state.type = TYPE_LIST;
187  state.val.l.alloc = state.val.l.count = g_list_length(back->torrents);
188  state.val.l.vals = g_new0(benc_val_t, state.val.l.alloc);
189
190  for(ii = 0, jj = back->torrents; NULL != jj; ii++, jj = jj->next)
191    tr_torrent_get_state(jj->data, state.val.l.vals + ii);
192
193  cf_savestate(&state, errstr);
194  tr_bencFree(&state);
195}
196
197GList *
198tr_backend_load_state(TrBackend *back, benc_val_t *state, GList **errors) {
199  GList *ret = NULL;
200  int ii;
201  TrTorrent *tor;
202  char *errstr;
203
204  TR_IS_BACKEND(back);
205
206  if(TYPE_LIST != state->type)
207    return NULL;
208
209  for(ii = 0; ii < state->val.l.count; ii++) {
210    errstr = NULL;
211    tor = tr_torrent_new_with_state(G_OBJECT(back), state->val.l.vals + ii,
212                                    &errstr);
213    if(NULL != errstr)
214      *errors = g_list_append(*errors, errstr);
215    if(NULL != tor)
216      ret = g_list_append(ret, tor);
217  }
218
219  return ret;
220}
221
222void
223tr_backend_add_torrent(TrBackend *back, GObject *tor) {
224  TR_IS_BACKEND(back);
225  TR_IS_TORRENT(tor);
226
227  g_object_weak_ref(tor, tr_backend_torrent_finalized, back);
228  back->torrents = g_list_append(back->torrents, tor);
229}
230
231static void
232tr_backend_torrent_finalized(gpointer gdata, GObject *tor) {
233  TrBackend *back = gdata;
234
235  TR_IS_BACKEND(back);
236
237  back->torrents = g_list_remove(back->torrents, tor);
238}
Note: See TracBrowser for help on using the repository browser.