transmission 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +0 -0
- data/LICENSE +23 -0
- data/README +50 -0
- data/Rakefile +41 -0
- data/ext/bencode.c +335 -0
- data/ext/bencode.h +64 -0
- data/ext/choking.c +335 -0
- data/ext/choking.h +30 -0
- data/ext/clients.c +90 -0
- data/ext/clients.h +25 -0
- data/ext/completion.c +266 -0
- data/ext/completion.h +67 -0
- data/ext/extconf.rb +3 -0
- data/ext/fastresume.h +375 -0
- data/ext/fdlimit.c +297 -0
- data/ext/fdlimit.h +36 -0
- data/ext/inout.c +620 -0
- data/ext/inout.h +38 -0
- data/ext/internal.h +202 -0
- data/ext/metainfo.c +339 -0
- data/ext/metainfo.h +44 -0
- data/ext/net.c +405 -0
- data/ext/net.h +54 -0
- data/ext/peer.c +584 -0
- data/ext/peer.h +55 -0
- data/ext/peermessages.h +326 -0
- data/ext/peerparse.h +564 -0
- data/ext/peerutils.h +394 -0
- data/ext/platform.c +196 -0
- data/ext/platform.h +63 -0
- data/ext/r_transmission.c +1135 -0
- data/ext/ratecontrol.c +170 -0
- data/ext/ratecontrol.h +33 -0
- data/ext/sha1.c +235 -0
- data/ext/sha1.h +68 -0
- data/ext/tracker.c +767 -0
- data/ext/tracker.h +53 -0
- data/ext/transmission.c +776 -0
- data/ext/transmission.h +317 -0
- data/ext/utils.c +142 -0
- data/ext/utils.h +164 -0
- data/lib/transmission.rb +75 -0
- metadata +98 -0
data/ext/platform.h
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
/******************************************************************************
|
2
|
+
* $Id: platform.h 310 2006-06-09 19:53:35Z joshe $
|
3
|
+
*
|
4
|
+
* Copyright (c) 2005 Transmission authors and contributors
|
5
|
+
*
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a
|
7
|
+
* copy of this software and associated documentation files (the "Software"),
|
8
|
+
* to deal in the Software without restriction, including without limitation
|
9
|
+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
10
|
+
* and/or sell copies of the Software, and to permit persons to whom the
|
11
|
+
* Software is furnished to do so, subject to the following conditions:
|
12
|
+
*
|
13
|
+
* The above copyright notice and this permission notice shall be included in
|
14
|
+
* all copies or substantial portions of the Software.
|
15
|
+
*
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
22
|
+
* DEALINGS IN THE SOFTWARE.
|
23
|
+
*****************************************************************************/
|
24
|
+
#ifndef TR_PLATFORM_H
|
25
|
+
#define TR_PLATFORM_H 1
|
26
|
+
|
27
|
+
#ifdef SYS_BEOS
|
28
|
+
#include <kernel/OS.h>
|
29
|
+
typedef thread_id tr_thread_t;
|
30
|
+
typedef sem_id tr_lock_t;
|
31
|
+
#else
|
32
|
+
#include <pthread.h>
|
33
|
+
typedef pthread_t tr_thread_t;
|
34
|
+
typedef pthread_mutex_t tr_lock_t;
|
35
|
+
#endif
|
36
|
+
|
37
|
+
char * tr_getCacheDirectory();
|
38
|
+
char * tr_getTorrentsDirectory();
|
39
|
+
|
40
|
+
void tr_threadCreate ( tr_thread_t *, void (*func)(void *), void * arg );
|
41
|
+
void tr_threadJoin ( tr_thread_t * );
|
42
|
+
void tr_lockInit ( tr_lock_t * );
|
43
|
+
void tr_lockClose ( tr_lock_t * );
|
44
|
+
|
45
|
+
static inline void tr_lockLock( tr_lock_t * l )
|
46
|
+
{
|
47
|
+
#ifdef SYS_BEOS
|
48
|
+
acquire_sem( *l );
|
49
|
+
#else
|
50
|
+
pthread_mutex_lock( l );
|
51
|
+
#endif
|
52
|
+
}
|
53
|
+
|
54
|
+
static inline void tr_lockUnlock( tr_lock_t * l )
|
55
|
+
{
|
56
|
+
#ifdef SYS_BEOS
|
57
|
+
release_sem( *l );
|
58
|
+
#else
|
59
|
+
pthread_mutex_unlock( l );
|
60
|
+
#endif
|
61
|
+
}
|
62
|
+
|
63
|
+
#endif
|
@@ -0,0 +1,1135 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include "transmission.h"
|
3
|
+
|
4
|
+
#define VERSION "0.1"
|
5
|
+
|
6
|
+
static VALUE cTransmission;
|
7
|
+
static VALUE cTorrent;
|
8
|
+
static VALUE cFileInfo;
|
9
|
+
static VALUE cStat;
|
10
|
+
|
11
|
+
static VALUE eTransmissionError;
|
12
|
+
static VALUE eParseError;
|
13
|
+
static VALUE eUnsupportedError;
|
14
|
+
static VALUE eDuplicateError;
|
15
|
+
static VALUE eTorrentError;
|
16
|
+
|
17
|
+
typedef struct {
|
18
|
+
tr_handle_t *handle;
|
19
|
+
VALUE torrents;
|
20
|
+
} r_transmission_t;
|
21
|
+
|
22
|
+
typedef struct {
|
23
|
+
VALUE transmission;
|
24
|
+
tr_torrent_t *handle;
|
25
|
+
int flags;
|
26
|
+
} r_torrent_t;
|
27
|
+
|
28
|
+
#define TORRENT_CLOSED 0x1
|
29
|
+
#define CLOSED(torrent) ((torrent)->flags & TORRENT_CLOSED)
|
30
|
+
#define SET_CLOSED(torrent) (torrent)->flags |= TORRENT_CLOSED;
|
31
|
+
|
32
|
+
#define STARTED(torrent) (tr_torrentStat((torrent)->handle)->status & TR_STATUS_ACTIVE)
|
33
|
+
|
34
|
+
#define CHECK_TORRENT(torrent) if(CLOSED(torrent)) rb_raise(eTorrentError, "Torrrent is already closed.");
|
35
|
+
|
36
|
+
static void r_torrent_close(r_torrent_t *);
|
37
|
+
static VALUE r_torrent_get_folder(VALUE);
|
38
|
+
static VALUE r_torrent_set_folder(VALUE, VALUE);
|
39
|
+
|
40
|
+
static void
|
41
|
+
r_transmission_mark(void *data)
|
42
|
+
{
|
43
|
+
r_transmission_t *transmission;
|
44
|
+
|
45
|
+
transmission = (r_transmission_t *) data;
|
46
|
+
rb_gc_mark(transmission -> torrents);
|
47
|
+
}
|
48
|
+
|
49
|
+
static void
|
50
|
+
r_transmission_free(void *data)
|
51
|
+
{
|
52
|
+
r_transmission_t *transmission;
|
53
|
+
r_torrent_t *torrent;
|
54
|
+
int i;
|
55
|
+
transmission = (r_transmission_t *) data;
|
56
|
+
for( i = 0; i < RARRAY(transmission->torrents)->len; i += 1 )
|
57
|
+
{
|
58
|
+
Data_Get_Struct(RARRAY(transmission->torrents)->ptr[i], r_torrent_t, torrent);
|
59
|
+
r_torrent_close(torrent);
|
60
|
+
}
|
61
|
+
tr_close(transmission->handle);
|
62
|
+
xfree(data);
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE
|
66
|
+
r_transmission_alloc(VALUE klass)
|
67
|
+
{
|
68
|
+
tr_handle_t *handle;
|
69
|
+
r_transmission_t *transmission;
|
70
|
+
VALUE obj;
|
71
|
+
|
72
|
+
handle = tr_init();
|
73
|
+
transmission = ALLOC(r_transmission_t);
|
74
|
+
transmission->handle = handle;
|
75
|
+
transmission->torrents = rb_ary_new();
|
76
|
+
obj = Data_Wrap_Struct(klass, r_transmission_mark, r_transmission_free, transmission);
|
77
|
+
return obj;
|
78
|
+
}
|
79
|
+
|
80
|
+
/*
|
81
|
+
* call-seq:
|
82
|
+
* Transmission.pref_directory -> string
|
83
|
+
*
|
84
|
+
* Returns the full path to a directory which can be used to store preferences.
|
85
|
+
*
|
86
|
+
*/
|
87
|
+
static VALUE
|
88
|
+
r_transmission_pref_dir(VALUE self)
|
89
|
+
{
|
90
|
+
return rb_str_new2(tr_getPrefsDirectory());
|
91
|
+
}
|
92
|
+
|
93
|
+
/*
|
94
|
+
* call-seq:
|
95
|
+
* transmission.bind_port = port -> port
|
96
|
+
*
|
97
|
+
* Sets a "starting" bind port. Everytime a torrent is started, the library tries to bind
|
98
|
+
* this port, then the next one and so on until it is successful.
|
99
|
+
*
|
100
|
+
*/
|
101
|
+
static VALUE
|
102
|
+
r_transmission_set_bind_port(VALUE self, VALUE port)
|
103
|
+
{
|
104
|
+
r_transmission_t *transmission;
|
105
|
+
|
106
|
+
Data_Get_Struct(self, r_transmission_t, transmission);
|
107
|
+
tr_setBindPort(transmission->handle, FIX2INT(port));
|
108
|
+
return port;
|
109
|
+
}
|
110
|
+
|
111
|
+
static void
|
112
|
+
r_torrent_mark(void *data)
|
113
|
+
{
|
114
|
+
r_torrent_t *torrent;
|
115
|
+
torrent = (r_torrent_t *)data;
|
116
|
+
rb_gc_mark(torrent->transmission);
|
117
|
+
}
|
118
|
+
|
119
|
+
static void
|
120
|
+
r_torrent_free(void *data)
|
121
|
+
{
|
122
|
+
r_torrent_t *torrent;
|
123
|
+
torrent = (r_torrent_t *) data;
|
124
|
+
r_torrent_close(torrent);
|
125
|
+
xfree(data);
|
126
|
+
}
|
127
|
+
|
128
|
+
/*
|
129
|
+
* call-seq:
|
130
|
+
* transmission.open(path) -> torrent
|
131
|
+
*
|
132
|
+
* Opens and parses torrent file at 'path'. If the file exists and is a
|
133
|
+
* valid torrent file, returns a Torrent instance and adds it to the list of
|
134
|
+
* torrents (but doesn't start it).
|
135
|
+
*
|
136
|
+
*/
|
137
|
+
static VALUE
|
138
|
+
r_transmission_open(int argc, VALUE *argv, VALUE self)
|
139
|
+
{
|
140
|
+
VALUE file, save = Qnil, saved = Qnil, excp, result;
|
141
|
+
r_transmission_t *transmission;
|
142
|
+
tr_torrent_t *torrent_h;
|
143
|
+
r_torrent_t *torrent;
|
144
|
+
int flags = 0;
|
145
|
+
int error = 0;
|
146
|
+
|
147
|
+
rb_scan_args(argc, argv, "12", &file, &save, &saved);
|
148
|
+
|
149
|
+
if( RTEST(save) && !RTEST(saved))
|
150
|
+
flags = TR_FSAVEPRIVATE;
|
151
|
+
|
152
|
+
Data_Get_Struct(self, r_transmission_t, transmission);
|
153
|
+
|
154
|
+
torrent_h = RTEST(saved) ?
|
155
|
+
tr_torrentInitSaved(transmission->handle, StringValuePtr(file), flags, &error) :
|
156
|
+
tr_torrentInit(transmission->handle, StringValuePtr(file), flags, &error);
|
157
|
+
if(torrent_h == NULL) {
|
158
|
+
switch(error)
|
159
|
+
{
|
160
|
+
case TR_EINVALID:
|
161
|
+
excp = eParseError;
|
162
|
+
break;
|
163
|
+
case TR_EUNSUPPORTED:
|
164
|
+
excp = eUnsupportedError;
|
165
|
+
break;
|
166
|
+
case TR_EDUPLICATE:
|
167
|
+
excp = eDuplicateError;
|
168
|
+
case TR_EOTHER:
|
169
|
+
default:
|
170
|
+
excp = eTorrentError;
|
171
|
+
}
|
172
|
+
rb_raise(excp, "Failed to open torrent file");
|
173
|
+
}
|
174
|
+
torrent = ALLOC(r_torrent_t);
|
175
|
+
torrent->transmission = self;
|
176
|
+
torrent->handle = torrent_h;
|
177
|
+
torrent->flags = 0;
|
178
|
+
|
179
|
+
result = Data_Wrap_Struct(cTorrent, r_torrent_mark, r_torrent_free, torrent);
|
180
|
+
rb_ary_push(transmission->torrents, result);
|
181
|
+
if(r_torrent_get_folder(result) == Qnil)
|
182
|
+
r_torrent_set_folder(result, rb_str_new2("."));
|
183
|
+
return result;
|
184
|
+
}
|
185
|
+
|
186
|
+
/*
|
187
|
+
* call-seq:
|
188
|
+
* transmission.size -> int
|
189
|
+
*
|
190
|
+
* Returns the count of open torrents.
|
191
|
+
*/
|
192
|
+
static VALUE
|
193
|
+
r_transmission_size(VALUE self)
|
194
|
+
{
|
195
|
+
r_transmission_t *transmission;
|
196
|
+
Data_Get_Struct(self, r_transmission_t, transmission);
|
197
|
+
return INT2FIX(tr_torrentCount(transmission->handle));
|
198
|
+
}
|
199
|
+
|
200
|
+
static VALUE
|
201
|
+
r_transmission_find(r_transmission_t *transmission, tr_torrent_t *h)
|
202
|
+
{
|
203
|
+
r_torrent_t *torrent;
|
204
|
+
VALUE result;
|
205
|
+
int i;
|
206
|
+
for( i = 0; i < RARRAY(transmission->torrents)->len; i += 1 )
|
207
|
+
{
|
208
|
+
result = RARRAY(transmission->torrents)->ptr[i];
|
209
|
+
Data_Get_Struct(result, r_torrent_t, torrent);
|
210
|
+
if(torrent->handle == h && !CLOSED(torrent)) return result;
|
211
|
+
}
|
212
|
+
return Qnil;
|
213
|
+
}
|
214
|
+
|
215
|
+
|
216
|
+
static void
|
217
|
+
r_transmission_each_i(tr_torrent_t *h, void *data)
|
218
|
+
{
|
219
|
+
r_transmission_t *transmission;
|
220
|
+
VALUE torrent;
|
221
|
+
|
222
|
+
transmission = (r_transmission_t *)data;
|
223
|
+
torrent = r_transmission_find(transmission, h);
|
224
|
+
if(torrent != Qnil) rb_yield(torrent);
|
225
|
+
}
|
226
|
+
|
227
|
+
/*
|
228
|
+
* call-seq:
|
229
|
+
* transmission.each {|torrent| ...} -> transmission
|
230
|
+
*
|
231
|
+
* Iterate through all opened torrents.
|
232
|
+
*/
|
233
|
+
static VALUE
|
234
|
+
r_transmission_each(VALUE self)
|
235
|
+
{
|
236
|
+
r_transmission_t *transmission;
|
237
|
+
Data_Get_Struct(self, r_transmission_t, transmission);
|
238
|
+
|
239
|
+
tr_torrentIterate(transmission->handle, r_transmission_each_i, (void *)transmission);
|
240
|
+
return self;
|
241
|
+
}
|
242
|
+
|
243
|
+
/*
|
244
|
+
* call-seq:
|
245
|
+
* transmission.rates -> [int, int]
|
246
|
+
*
|
247
|
+
* Returns total download and upload rates.
|
248
|
+
*/
|
249
|
+
static VALUE
|
250
|
+
r_transmission_rates(VALUE self)
|
251
|
+
{
|
252
|
+
r_transmission_t *transmission;
|
253
|
+
float down, up;
|
254
|
+
|
255
|
+
Data_Get_Struct(self, r_transmission_t, transmission);
|
256
|
+
tr_torrentRates(transmission->handle, &down, &up);
|
257
|
+
return rb_ary_new3(2, rb_float_new(down), rb_float_new(up));
|
258
|
+
}
|
259
|
+
|
260
|
+
/*
|
261
|
+
* call-seq:
|
262
|
+
* transmission.upload_limit = limit -> limit
|
263
|
+
*
|
264
|
+
* Sets upload limit in Kb.
|
265
|
+
*/
|
266
|
+
static VALUE
|
267
|
+
r_transmission_set_upload_limit(VALUE self, VALUE limit)
|
268
|
+
{
|
269
|
+
r_transmission_t *transmission;
|
270
|
+
Data_Get_Struct(self, r_transmission_t, transmission);
|
271
|
+
tr_setUploadLimit(transmission->handle, FIX2INT(limit));
|
272
|
+
return limit;
|
273
|
+
}
|
274
|
+
|
275
|
+
/*
|
276
|
+
* call-seq:
|
277
|
+
* transmission.download_limit = limit -> limit
|
278
|
+
*
|
279
|
+
* Sets download limit in Kb.
|
280
|
+
*/
|
281
|
+
static VALUE
|
282
|
+
r_transmission_set_download_limit(VALUE self, VALUE limit)
|
283
|
+
{
|
284
|
+
r_transmission_t *transmission;
|
285
|
+
Data_Get_Struct(self, r_transmission_t, transmission);
|
286
|
+
tr_setDownloadLimit(transmission->handle, FIX2INT(limit));
|
287
|
+
return limit;
|
288
|
+
}
|
289
|
+
|
290
|
+
static void
|
291
|
+
r_torrent_close(r_torrent_t *torrent)
|
292
|
+
{
|
293
|
+
r_transmission_t *transmission;
|
294
|
+
|
295
|
+
if(CLOSED(torrent)) return;
|
296
|
+
|
297
|
+
Data_Get_Struct(torrent->transmission, r_transmission_t, transmission);
|
298
|
+
|
299
|
+
if(STARTED(torrent))
|
300
|
+
tr_torrentStop(torrent->handle);
|
301
|
+
|
302
|
+
tr_torrentClose(transmission->handle, torrent->handle);
|
303
|
+
SET_CLOSED(torrent);
|
304
|
+
}
|
305
|
+
|
306
|
+
/*
|
307
|
+
* call-seq:
|
308
|
+
* torrent.remove(saved = false) -> nil
|
309
|
+
*
|
310
|
+
* Removes torrent from the current session. If 'saved' parameter is true,
|
311
|
+
* it also deletes a private torrent copy if there is one.
|
312
|
+
*/
|
313
|
+
static VALUE
|
314
|
+
r_torrent_remove(int argc, VALUE *argv, VALUE self)
|
315
|
+
{
|
316
|
+
r_transmission_t *transmission;
|
317
|
+
r_torrent_t *torrent;
|
318
|
+
VALUE remove_saved = Qfalse;
|
319
|
+
|
320
|
+
rb_scan_args(argc, argv, "01", &remove_saved);
|
321
|
+
|
322
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
323
|
+
CHECK_TORRENT(torrent);
|
324
|
+
Data_Get_Struct(torrent->transmission, r_transmission_t, transmission);
|
325
|
+
if(RTEST(remove_saved))
|
326
|
+
tr_torrentRemoveSaved(torrent->handle);
|
327
|
+
rb_ary_delete(transmission->torrents, self);
|
328
|
+
r_torrent_close(torrent);
|
329
|
+
return Qnil;
|
330
|
+
}
|
331
|
+
|
332
|
+
static char *
|
333
|
+
r_torrent_scrape_error(int code)
|
334
|
+
{
|
335
|
+
switch(code)
|
336
|
+
{
|
337
|
+
case TR_SCRAPE_RESOLVE:
|
338
|
+
return "Could not resolve address";
|
339
|
+
case TR_SCRAPE_CONNECT:
|
340
|
+
return "Could not connect to the tracker";
|
341
|
+
case TR_SCRAPE_READ:
|
342
|
+
return "Failed to read from the tracker";
|
343
|
+
default:
|
344
|
+
return "Failed to scrape the tracker";
|
345
|
+
}
|
346
|
+
}
|
347
|
+
|
348
|
+
/*
|
349
|
+
* call-seq:
|
350
|
+
* torrent.scrape -> [int, int]
|
351
|
+
*
|
352
|
+
* Scrapes the tracker and returns a number of seeders and leechers.
|
353
|
+
*/
|
354
|
+
static VALUE
|
355
|
+
r_torrent_scrape(VALUE self)
|
356
|
+
{
|
357
|
+
r_torrent_t *torrent;
|
358
|
+
int seeders, leechers;
|
359
|
+
int ret_code;
|
360
|
+
|
361
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
362
|
+
CHECK_TORRENT(torrent);
|
363
|
+
|
364
|
+
if((ret_code = tr_torrentScrape(torrent->handle, &seeders, &leechers)) != 0)
|
365
|
+
{
|
366
|
+
rb_raise(eTorrentError, r_torrent_scrape_error(ret_code));
|
367
|
+
}
|
368
|
+
return rb_ary_new3(2, INT2FIX(seeders), INT2FIX(leechers));
|
369
|
+
}
|
370
|
+
|
371
|
+
static tr_info_t *
|
372
|
+
r_torrent_info(VALUE self)
|
373
|
+
{
|
374
|
+
r_torrent_t *torrent;
|
375
|
+
|
376
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
377
|
+
CHECK_TORRENT(torrent);
|
378
|
+
return tr_torrentInfo(torrent->handle);
|
379
|
+
}
|
380
|
+
|
381
|
+
/*
|
382
|
+
* call-seq:
|
383
|
+
* torrent.file_name -> string
|
384
|
+
*
|
385
|
+
* Returns file name of the torrent file.
|
386
|
+
*/
|
387
|
+
static VALUE
|
388
|
+
r_torrent_file_name(VALUE self)
|
389
|
+
{
|
390
|
+
return rb_str_new2(r_torrent_info(self)->torrent);
|
391
|
+
}
|
392
|
+
|
393
|
+
/*
|
394
|
+
* call-seq:
|
395
|
+
* torrent.name -> string
|
396
|
+
*
|
397
|
+
* Returns the description of the torrent file.
|
398
|
+
*/
|
399
|
+
static VALUE
|
400
|
+
r_torrent_name(VALUE self)
|
401
|
+
{
|
402
|
+
return rb_str_new2(r_torrent_info(self)->name);
|
403
|
+
}
|
404
|
+
|
405
|
+
/*
|
406
|
+
* call-seq:
|
407
|
+
* torrent.hash_string -> string
|
408
|
+
*
|
409
|
+
* Returns the hash string of the torrent file.
|
410
|
+
*/
|
411
|
+
static VALUE
|
412
|
+
r_torrent_hash_string(VALUE self)
|
413
|
+
{
|
414
|
+
return rb_str_new2(r_torrent_info(self)->hashString);
|
415
|
+
}
|
416
|
+
|
417
|
+
/*
|
418
|
+
* call-seq:
|
419
|
+
* torrent.tracker_address -> string
|
420
|
+
*
|
421
|
+
* Returns the tracker address.
|
422
|
+
*/
|
423
|
+
static VALUE
|
424
|
+
r_torrent_tracker_address(VALUE self)
|
425
|
+
{
|
426
|
+
return rb_str_new2(r_torrent_info(self)->trackerAddress);
|
427
|
+
}
|
428
|
+
|
429
|
+
/*
|
430
|
+
* call-seq:
|
431
|
+
* torrent.tracker_port -> int
|
432
|
+
*
|
433
|
+
* Returns the tracker port.
|
434
|
+
*/
|
435
|
+
static VALUE
|
436
|
+
r_torrent_tracker_port(VALUE self)
|
437
|
+
{
|
438
|
+
return INT2FIX(r_torrent_info(self)->trackerPort);
|
439
|
+
}
|
440
|
+
|
441
|
+
/*
|
442
|
+
* call-seq:
|
443
|
+
* torrent.tracker_announce -> string
|
444
|
+
*
|
445
|
+
* Returns the tracker announce address.
|
446
|
+
*/
|
447
|
+
static VALUE
|
448
|
+
r_torrent_tracker_announce(VALUE self)
|
449
|
+
{
|
450
|
+
return rb_str_new2(r_torrent_info(self)->trackerAnnounce);
|
451
|
+
}
|
452
|
+
|
453
|
+
/*
|
454
|
+
* call-seq:
|
455
|
+
* torrent.piece_size -> int
|
456
|
+
*
|
457
|
+
* Returns piece size in bytes.
|
458
|
+
*/
|
459
|
+
static VALUE
|
460
|
+
r_torrent_piece_size(VALUE self)
|
461
|
+
{
|
462
|
+
return INT2FIX(r_torrent_info(self)->pieceSize);
|
463
|
+
}
|
464
|
+
|
465
|
+
/*
|
466
|
+
* call-seq:
|
467
|
+
* torrent.piece_count -> string
|
468
|
+
*
|
469
|
+
* Returns piece count.
|
470
|
+
*/
|
471
|
+
static VALUE
|
472
|
+
r_torrent_piece_count(VALUE self)
|
473
|
+
{
|
474
|
+
return INT2FIX(r_torrent_info(self)->pieceCount);
|
475
|
+
}
|
476
|
+
|
477
|
+
/*
|
478
|
+
* call-seq:
|
479
|
+
* torrent.total_size -> string
|
480
|
+
*
|
481
|
+
* Returns the total size of all pieces in bytes.
|
482
|
+
*/
|
483
|
+
static VALUE
|
484
|
+
r_torrent_total_size(VALUE self)
|
485
|
+
{
|
486
|
+
return ULONG2NUM(r_torrent_info(self)->totalSize);
|
487
|
+
}
|
488
|
+
|
489
|
+
/*
|
490
|
+
* call-seq:
|
491
|
+
* torrent.pieces -> array
|
492
|
+
*
|
493
|
+
* Returns the array of pieces.
|
494
|
+
*/
|
495
|
+
static VALUE
|
496
|
+
r_torrent_pieces(VALUE self)
|
497
|
+
{
|
498
|
+
VALUE *pieces;
|
499
|
+
tr_info_t *info;
|
500
|
+
VALUE result;
|
501
|
+
int i;
|
502
|
+
|
503
|
+
info = r_torrent_info(self);
|
504
|
+
|
505
|
+
pieces = ALLOC_N(VALUE, info->pieceCount);
|
506
|
+
for( i = 0; i < info->pieceCount; i += 1 )
|
507
|
+
{
|
508
|
+
pieces[i] = INT2FIX(info->pieces[i]);
|
509
|
+
}
|
510
|
+
|
511
|
+
result = rb_ary_new4(info->pieceCount, pieces);
|
512
|
+
xfree(pieces);
|
513
|
+
return result;
|
514
|
+
}
|
515
|
+
|
516
|
+
/*
|
517
|
+
* call-seq:
|
518
|
+
* torrent.file_count -> int
|
519
|
+
*
|
520
|
+
* Returns the total number of files for this torrent.
|
521
|
+
*/
|
522
|
+
static VALUE
|
523
|
+
r_torrent_file_count(VALUE self)
|
524
|
+
{
|
525
|
+
return INT2FIX(r_torrent_info(self)->fileCount);
|
526
|
+
}
|
527
|
+
|
528
|
+
/*
|
529
|
+
* call-seq:
|
530
|
+
* torrent.files -> array
|
531
|
+
*
|
532
|
+
* Returns the array of FileInfo.
|
533
|
+
*/
|
534
|
+
static VALUE
|
535
|
+
r_torrent_files(VALUE self)
|
536
|
+
{
|
537
|
+
VALUE *files;
|
538
|
+
VALUE result;
|
539
|
+
tr_info_t *info;
|
540
|
+
tr_file_t *f;
|
541
|
+
int i;
|
542
|
+
|
543
|
+
info = r_torrent_info(self);
|
544
|
+
|
545
|
+
files = ALLOC_N(VALUE, info->fileCount);
|
546
|
+
for( i = 0; i < info->fileCount; i += 1 )
|
547
|
+
{
|
548
|
+
f = ALLOC(tr_file_t);
|
549
|
+
MEMCPY(f, &info->files[i], tr_file_t, 1);
|
550
|
+
files[i] = Data_Wrap_Struct(cFileInfo, NULL, xfree, f);
|
551
|
+
}
|
552
|
+
result = rb_ary_new4(info->fileCount, files);
|
553
|
+
xfree(files);
|
554
|
+
return result;
|
555
|
+
}
|
556
|
+
|
557
|
+
/*
|
558
|
+
* call-seq:
|
559
|
+
* torrent.stat -> Stat
|
560
|
+
*
|
561
|
+
* Returns the stat of this torrent.
|
562
|
+
*/
|
563
|
+
static VALUE
|
564
|
+
r_torrent_stat(VALUE self)
|
565
|
+
{
|
566
|
+
r_torrent_t *torrent;
|
567
|
+
tr_stat_t *stat;
|
568
|
+
|
569
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
570
|
+
CHECK_TORRENT(torrent);
|
571
|
+
|
572
|
+
stat = ALLOC(tr_stat_t);
|
573
|
+
MEMCPY(stat, tr_torrentStat(torrent->handle), tr_stat_t, 1);
|
574
|
+
return Data_Wrap_Struct(cStat, NULL, xfree, stat);
|
575
|
+
}
|
576
|
+
|
577
|
+
/*
|
578
|
+
* call-seq:
|
579
|
+
* torrent.folder -> string
|
580
|
+
*
|
581
|
+
* Returns the path where torrent files will be stored.
|
582
|
+
*/
|
583
|
+
static VALUE
|
584
|
+
r_torrent_get_folder(VALUE self)
|
585
|
+
{
|
586
|
+
r_torrent_t *torrent;
|
587
|
+
char *folder;
|
588
|
+
|
589
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
590
|
+
CHECK_TORRENT(torrent);
|
591
|
+
|
592
|
+
folder = tr_torrentGetFolder(torrent->handle);
|
593
|
+
if(folder)
|
594
|
+
return rb_str_new2(folder);
|
595
|
+
return Qnil;
|
596
|
+
}
|
597
|
+
|
598
|
+
/*
|
599
|
+
* call-seq:
|
600
|
+
* torrent.folder = folder -> folder
|
601
|
+
*
|
602
|
+
* Changes the directory wher torrent file will be stored.
|
603
|
+
*/
|
604
|
+
static VALUE
|
605
|
+
r_torrent_set_folder(VALUE self, VALUE file)
|
606
|
+
{
|
607
|
+
r_torrent_t *torrent;
|
608
|
+
|
609
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
610
|
+
CHECK_TORRENT(torrent);
|
611
|
+
|
612
|
+
tr_torrentSetFolder(torrent->handle, StringValuePtr(file));
|
613
|
+
return file;
|
614
|
+
}
|
615
|
+
|
616
|
+
/*
|
617
|
+
* call-seq:
|
618
|
+
* torrent.start -> nil
|
619
|
+
*
|
620
|
+
* Starts the torrent downloading. The download is launched in a seperate thread,
|
621
|
+
* therefore torrent.start returns immediately.
|
622
|
+
*/
|
623
|
+
static VALUE
|
624
|
+
r_torrent_start(VALUE self)
|
625
|
+
{
|
626
|
+
r_torrent_t *torrent;
|
627
|
+
|
628
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
629
|
+
CHECK_TORRENT(torrent);
|
630
|
+
|
631
|
+
if(!STARTED(torrent))
|
632
|
+
{
|
633
|
+
tr_torrentStart(torrent->handle);
|
634
|
+
}
|
635
|
+
|
636
|
+
return Qnil;
|
637
|
+
}
|
638
|
+
|
639
|
+
/*
|
640
|
+
* call-seq:
|
641
|
+
* torrent.stop -> nil
|
642
|
+
*
|
643
|
+
* Stops the torrent downloading.
|
644
|
+
*/
|
645
|
+
static VALUE
|
646
|
+
r_torrent_stop(VALUE self)
|
647
|
+
{
|
648
|
+
r_torrent_t *torrent;
|
649
|
+
|
650
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
651
|
+
CHECK_TORRENT(torrent);
|
652
|
+
|
653
|
+
if(STARTED(torrent))
|
654
|
+
{
|
655
|
+
tr_torrentStop(torrent->handle);
|
656
|
+
}
|
657
|
+
|
658
|
+
return Qnil;
|
659
|
+
}
|
660
|
+
|
661
|
+
/*
|
662
|
+
* call-seq:
|
663
|
+
* torrent.active? -> bool
|
664
|
+
*
|
665
|
+
* Returns true if torrent is in active state.
|
666
|
+
*/
|
667
|
+
static VALUE
|
668
|
+
r_torrent_active(VALUE self)
|
669
|
+
{
|
670
|
+
r_torrent_t *torrent;
|
671
|
+
|
672
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
673
|
+
CHECK_TORRENT(torrent);
|
674
|
+
|
675
|
+
return STARTED(torrent) ? Qtrue : Qfalse;
|
676
|
+
}
|
677
|
+
|
678
|
+
/*
|
679
|
+
* call-seq:
|
680
|
+
* torrent.closed? -> bool
|
681
|
+
*
|
682
|
+
* Returns true if torrent is closed and can't be used anymore.
|
683
|
+
*/
|
684
|
+
static VALUE
|
685
|
+
r_torrent_closed(VALUE self)
|
686
|
+
{
|
687
|
+
r_torrent_t *torrent;
|
688
|
+
|
689
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
690
|
+
|
691
|
+
return CLOSED(torrent) ? Qtrue : Qfalse;
|
692
|
+
}
|
693
|
+
|
694
|
+
/*
|
695
|
+
* call-seq:
|
696
|
+
* torrent.availability(size) -> array of integers
|
697
|
+
*
|
698
|
+
* Use this to draw an advanced progress bar which is 'size' pixels
|
699
|
+
* wide. Returns an array of integer where each integer is set
|
700
|
+
* to either -1 if we have the piece, otherwise it is set to the number
|
701
|
+
* of connected peers who have the piece.
|
702
|
+
*/
|
703
|
+
static VALUE
|
704
|
+
r_torrent_availability(VALUE self, VALUE size)
|
705
|
+
{
|
706
|
+
r_torrent_t *torrent;
|
707
|
+
int8_t *data;
|
708
|
+
VALUE *result_data;
|
709
|
+
VALUE result;
|
710
|
+
int length, i;
|
711
|
+
|
712
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
713
|
+
CHECK_TORRENT(torrent);
|
714
|
+
|
715
|
+
length = FIX2INT(size);
|
716
|
+
data = ALLOC_N(int8_t, length);
|
717
|
+
result_data = ALLOC_N(VALUE, length);
|
718
|
+
tr_torrentAvailability(torrent->handle, data, length);
|
719
|
+
for( i = 0; i < length; i += 1 )
|
720
|
+
{
|
721
|
+
result_data[i] = INT2FIX(data[i]);
|
722
|
+
}
|
723
|
+
result = rb_ary_new4(length, result_data);
|
724
|
+
xfree(data);
|
725
|
+
xfree(result_data);
|
726
|
+
return result;
|
727
|
+
}
|
728
|
+
|
729
|
+
/*
|
730
|
+
* call-seq:
|
731
|
+
* torrent.just_finished? -> bool
|
732
|
+
*
|
733
|
+
* The first call after a torrent is completed returns true. Returns false
|
734
|
+
* in other cases.
|
735
|
+
*/
|
736
|
+
static VALUE
|
737
|
+
r_torrent_just_finished(VALUE self)
|
738
|
+
{
|
739
|
+
r_torrent_t *torrent;
|
740
|
+
|
741
|
+
Data_Get_Struct(self, r_torrent_t, torrent);
|
742
|
+
|
743
|
+
return tr_getFinished(torrent->handle) ? Qtrue : Qfalse;
|
744
|
+
}
|
745
|
+
|
746
|
+
/*
|
747
|
+
* call-seq:
|
748
|
+
* file_info.name -> string
|
749
|
+
*
|
750
|
+
* Returns the name of the file.
|
751
|
+
*/
|
752
|
+
static VALUE
|
753
|
+
r_file_info_name(VALUE self)
|
754
|
+
{
|
755
|
+
tr_file_t *file;
|
756
|
+
Data_Get_Struct(self, tr_file_t, file);
|
757
|
+
return rb_str_new2(file->name);
|
758
|
+
}
|
759
|
+
|
760
|
+
/*
|
761
|
+
* call-seq:
|
762
|
+
* file_info.size -> int
|
763
|
+
*
|
764
|
+
* Returns the size of the file.
|
765
|
+
*/
|
766
|
+
static VALUE
|
767
|
+
r_file_info_size(VALUE self)
|
768
|
+
{
|
769
|
+
tr_file_t *file;
|
770
|
+
Data_Get_Struct(self, tr_file_t, file);
|
771
|
+
return INT2FIX(file->length);
|
772
|
+
}
|
773
|
+
|
774
|
+
/*
|
775
|
+
* call-seq:
|
776
|
+
* stat.status -> int
|
777
|
+
*
|
778
|
+
* Returns the status of the torrent.
|
779
|
+
*/
|
780
|
+
static VALUE
|
781
|
+
r_stat_status(VALUE self)
|
782
|
+
{
|
783
|
+
tr_stat_t *stat;
|
784
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
785
|
+
return INT2FIX(stat->status);
|
786
|
+
}
|
787
|
+
|
788
|
+
/*
|
789
|
+
* call-seq:
|
790
|
+
* stat.error -> int
|
791
|
+
*
|
792
|
+
* Returns the error code of the torrent, 0 otherwise.
|
793
|
+
*/
|
794
|
+
static VALUE
|
795
|
+
r_stat_error(VALUE self)
|
796
|
+
{
|
797
|
+
tr_stat_t *stat;
|
798
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
799
|
+
return INT2FIX(stat->error);
|
800
|
+
}
|
801
|
+
|
802
|
+
/*
|
803
|
+
* call-seq:
|
804
|
+
* stat.tracker_error -> string
|
805
|
+
*
|
806
|
+
* Returns the tracker error or empty string.
|
807
|
+
*/
|
808
|
+
static VALUE
|
809
|
+
r_stat_tracker_error(VALUE self)
|
810
|
+
{
|
811
|
+
tr_stat_t *stat;
|
812
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
813
|
+
return rb_str_new2(stat->trackerError);
|
814
|
+
}
|
815
|
+
|
816
|
+
/*
|
817
|
+
* call-seq:
|
818
|
+
* stat.progress -> float
|
819
|
+
*
|
820
|
+
* Returns the progress of the torrent from 0.0 to 1.0.
|
821
|
+
*/
|
822
|
+
static VALUE
|
823
|
+
r_stat_progress(VALUE self)
|
824
|
+
{
|
825
|
+
tr_stat_t *stat;
|
826
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
827
|
+
return rb_float_new(stat->progress);
|
828
|
+
}
|
829
|
+
|
830
|
+
/*
|
831
|
+
* call-seq:
|
832
|
+
* stat.down_rate -> float
|
833
|
+
*
|
834
|
+
* Returns downloading rate.
|
835
|
+
*/
|
836
|
+
static VALUE
|
837
|
+
r_stat_down_rate(VALUE self)
|
838
|
+
{
|
839
|
+
tr_stat_t *stat;
|
840
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
841
|
+
return rb_float_new(stat->rateDownload);
|
842
|
+
}
|
843
|
+
|
844
|
+
/*
|
845
|
+
* call-seq:
|
846
|
+
* stat.up_rate -> float
|
847
|
+
*
|
848
|
+
* Returns uploading rate.
|
849
|
+
*/
|
850
|
+
static VALUE
|
851
|
+
r_stat_up_rate(VALUE self)
|
852
|
+
{
|
853
|
+
tr_stat_t *stat;
|
854
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
855
|
+
return rb_float_new(stat->rateUpload);
|
856
|
+
}
|
857
|
+
|
858
|
+
/*
|
859
|
+
* call-seq:
|
860
|
+
* stat.rates -> [float, float]
|
861
|
+
*
|
862
|
+
* Returns an array of downloading and uploading rates.
|
863
|
+
*/
|
864
|
+
static VALUE
|
865
|
+
r_stat_rates(VALUE self)
|
866
|
+
{
|
867
|
+
tr_stat_t *stat;
|
868
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
869
|
+
return rb_ary_new3(2, rb_float_new(stat->rateDownload), rb_float_new(stat->rateUpload));
|
870
|
+
}
|
871
|
+
|
872
|
+
/*
|
873
|
+
* call-seq:
|
874
|
+
* stat.eta -> int
|
875
|
+
*
|
876
|
+
* Returns eta until the torrent finishes downloading.
|
877
|
+
*/
|
878
|
+
static VALUE
|
879
|
+
r_stat_eta(VALUE self)
|
880
|
+
{
|
881
|
+
tr_stat_t *stat;
|
882
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
883
|
+
return INT2FIX(stat->eta);
|
884
|
+
}
|
885
|
+
|
886
|
+
/*
|
887
|
+
* call-seq:
|
888
|
+
* stat.peers_total -> int
|
889
|
+
*
|
890
|
+
* Returns the total number of peers.
|
891
|
+
*/
|
892
|
+
static VALUE
|
893
|
+
r_stat_peers_total(VALUE self)
|
894
|
+
{
|
895
|
+
tr_stat_t *stat;
|
896
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
897
|
+
return INT2FIX(stat->peersTotal);
|
898
|
+
}
|
899
|
+
|
900
|
+
/*
|
901
|
+
* call-seq:
|
902
|
+
* stat.up_peers -> int
|
903
|
+
*
|
904
|
+
* Returns a number of uploading peers.
|
905
|
+
*/
|
906
|
+
static VALUE
|
907
|
+
r_stat_up_peers(VALUE self)
|
908
|
+
{
|
909
|
+
tr_stat_t *stat;
|
910
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
911
|
+
return INT2FIX(stat->peersUploading);
|
912
|
+
}
|
913
|
+
|
914
|
+
/*
|
915
|
+
* call-seq:
|
916
|
+
* stat.down_peers -> int
|
917
|
+
*
|
918
|
+
* Returns a number of downloaded peers.
|
919
|
+
*/
|
920
|
+
static VALUE
|
921
|
+
r_stat_down_peers(VALUE self)
|
922
|
+
{
|
923
|
+
tr_stat_t *stat;
|
924
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
925
|
+
return INT2FIX(stat->peersDownloading);
|
926
|
+
}
|
927
|
+
|
928
|
+
/*
|
929
|
+
* call-seq:
|
930
|
+
* stat.peers -> [int, int]
|
931
|
+
*
|
932
|
+
* Returns an array of numbers of downloading and uploading peers.
|
933
|
+
*/
|
934
|
+
static VALUE
|
935
|
+
r_stat_peers(VALUE self)
|
936
|
+
{
|
937
|
+
tr_stat_t *stat;
|
938
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
939
|
+
return rb_ary_new3(2, INT2FIX(stat->peersDownloading), INT2FIX(stat->peersUploading));
|
940
|
+
}
|
941
|
+
|
942
|
+
/*
|
943
|
+
* call-seq:
|
944
|
+
* stat.seeders -> int
|
945
|
+
*
|
946
|
+
* Returns a number of seeders.
|
947
|
+
*/
|
948
|
+
static VALUE
|
949
|
+
r_stat_seeders(VALUE self)
|
950
|
+
{
|
951
|
+
tr_stat_t *stat;
|
952
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
953
|
+
return INT2FIX(stat->seeders);
|
954
|
+
}
|
955
|
+
|
956
|
+
/*
|
957
|
+
* call-seq:
|
958
|
+
* stat.leechers -> int
|
959
|
+
*
|
960
|
+
* Returns a number of leechers.
|
961
|
+
*/
|
962
|
+
static VALUE
|
963
|
+
r_stat_leechers(VALUE self)
|
964
|
+
{
|
965
|
+
tr_stat_t *stat;
|
966
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
967
|
+
return INT2FIX(stat->leechers);
|
968
|
+
}
|
969
|
+
|
970
|
+
/*
|
971
|
+
* call-seq:
|
972
|
+
* stat.downloaded -> int
|
973
|
+
*
|
974
|
+
* Returns the total number of downloaded bytes.
|
975
|
+
*/
|
976
|
+
static VALUE
|
977
|
+
r_stat_downloaded(VALUE self)
|
978
|
+
{
|
979
|
+
tr_stat_t *stat;
|
980
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
981
|
+
return ULONG2NUM(stat->downloaded);
|
982
|
+
}
|
983
|
+
|
984
|
+
/*
|
985
|
+
* call-seq:
|
986
|
+
* stat.uploaded -> int
|
987
|
+
*
|
988
|
+
* Returns the total number of uploaded bytes.
|
989
|
+
*/
|
990
|
+
static VALUE
|
991
|
+
r_stat_uploaded(VALUE self)
|
992
|
+
{
|
993
|
+
tr_stat_t *stat;
|
994
|
+
Data_Get_Struct(self, tr_stat_t, stat);
|
995
|
+
return ULONG2NUM(stat->uploaded);
|
996
|
+
}
|
997
|
+
|
998
|
+
/*
|
999
|
+
* Document-class: Transmission::Torrent
|
1000
|
+
*
|
1001
|
+
* == Summary
|
1002
|
+
*
|
1003
|
+
* The Torrent class represent a torrent instance. You can use this instance
|
1004
|
+
* start and stop downloading process and keep track of its progress.
|
1005
|
+
*/
|
1006
|
+
static void
|
1007
|
+
Init_torrent()
|
1008
|
+
{
|
1009
|
+
cTorrent = rb_define_class_under(cTransmission, "Torrent", rb_cObject);
|
1010
|
+
rb_define_method(cTorrent, "remove", r_torrent_remove, -1);
|
1011
|
+
rb_define_method(cTorrent, "scrape", r_torrent_scrape, 0);
|
1012
|
+
rb_define_method(cTorrent, "file_name", r_torrent_file_name, 0);
|
1013
|
+
rb_define_method(cTorrent, "name", r_torrent_name, 0);
|
1014
|
+
rb_define_method(cTorrent, "hash_string", r_torrent_hash_string, 0);
|
1015
|
+
rb_define_method(cTorrent, "tracker_addr", r_torrent_tracker_address, 0);
|
1016
|
+
rb_define_method(cTorrent, "tracker_address", r_torrent_tracker_address, 0);
|
1017
|
+
rb_define_method(cTorrent, "tracker_port", r_torrent_tracker_port, 0);
|
1018
|
+
rb_define_method(cTorrent, "tracker_announce", r_torrent_tracker_announce, 0);
|
1019
|
+
rb_define_method(cTorrent, "tracker_ann", r_torrent_tracker_announce, 0);
|
1020
|
+
rb_define_method(cTorrent, "piece_size", r_torrent_piece_size, 0);
|
1021
|
+
rb_define_method(cTorrent, "piece_count", r_torrent_piece_count, 0);
|
1022
|
+
rb_define_method(cTorrent, "total_size", r_torrent_total_size, 0);
|
1023
|
+
rb_define_method(cTorrent, "size", r_torrent_total_size, 0);
|
1024
|
+
rb_define_method(cTorrent, "pieces", r_torrent_pieces, 0);
|
1025
|
+
rb_define_method(cTorrent, "file_count", r_torrent_file_count, 0);
|
1026
|
+
rb_define_method(cTorrent, "files", r_torrent_files, 0);
|
1027
|
+
rb_define_method(cTorrent, "stat", r_torrent_stat, 0);
|
1028
|
+
rb_define_method(cTorrent, "download_to", r_torrent_set_folder, 1);
|
1029
|
+
rb_define_method(cTorrent, "folder", r_torrent_get_folder, 0);
|
1030
|
+
rb_define_method(cTorrent, "folder=", r_torrent_set_folder, 1);
|
1031
|
+
rb_define_method(cTorrent, "start", r_torrent_start, 0);
|
1032
|
+
rb_define_method(cTorrent, "stop", r_torrent_stop, 0);
|
1033
|
+
rb_define_method(cTorrent, "active?", r_torrent_active, 0);
|
1034
|
+
rb_define_method(cTorrent, "closed?", r_torrent_closed, 0);
|
1035
|
+
rb_define_method(cTorrent, "availability", r_torrent_availability, 1);
|
1036
|
+
rb_define_method(cTorrent, "just_finished?", r_torrent_just_finished, 0);
|
1037
|
+
}
|
1038
|
+
|
1039
|
+
/*
|
1040
|
+
* Document-class: Transmission::Torrent::FileInfo
|
1041
|
+
*
|
1042
|
+
* == Summary
|
1043
|
+
*
|
1044
|
+
* The FileInfo class containts the information about a file which is part of this torrent.
|
1045
|
+
*/
|
1046
|
+
static void
|
1047
|
+
Init_fileinfo()
|
1048
|
+
{
|
1049
|
+
cFileInfo = rb_define_class_under(cTorrent, "FileInfo", rb_cObject);
|
1050
|
+
rb_define_method(cFileInfo, "name", r_file_info_name, 0);
|
1051
|
+
rb_define_method(cFileInfo, "file_name", r_file_info_name, 0);
|
1052
|
+
rb_define_method(cFileInfo, "size", r_file_info_size, 0);
|
1053
|
+
rb_define_method(cFileInfo, "length", r_file_info_size, 0);
|
1054
|
+
}
|
1055
|
+
|
1056
|
+
/*
|
1057
|
+
* Document-class: Transmission::Torrent::Stat
|
1058
|
+
*
|
1059
|
+
* == Summary
|
1060
|
+
*
|
1061
|
+
* The Stat class containts the information about the torrent.
|
1062
|
+
*/
|
1063
|
+
static void
|
1064
|
+
Init_stat()
|
1065
|
+
{
|
1066
|
+
cStat = rb_define_class_under(cTorrent, "Stat", rb_cObject);
|
1067
|
+
rb_define_method(cStat, "status", r_stat_status, 0);
|
1068
|
+
rb_define_method(cStat, "error", r_stat_error, 0);
|
1069
|
+
rb_define_method(cStat, "tracker_error", r_stat_tracker_error, 0);
|
1070
|
+
rb_define_method(cStat, "progress", r_stat_progress, 0);
|
1071
|
+
rb_define_method(cStat, "rates", r_stat_rates, 0);
|
1072
|
+
rb_define_method(cStat, "down_rate", r_stat_down_rate, 0);
|
1073
|
+
rb_define_method(cStat, "up_rate", r_stat_up_rate, 0);
|
1074
|
+
rb_define_method(cStat, "eta", r_stat_eta, 0);
|
1075
|
+
rb_define_method(cStat, "peers_total", r_stat_peers_total, 0);
|
1076
|
+
rb_define_method(cStat, "peers", r_stat_peers, 0);
|
1077
|
+
rb_define_method(cStat, "up_peers", r_stat_up_peers, 0);
|
1078
|
+
rb_define_method(cStat, "down_peers", r_stat_down_peers, 0);
|
1079
|
+
rb_define_method(cStat, "seeders", r_stat_seeders, 0);
|
1080
|
+
rb_define_method(cStat, "leechers", r_stat_leechers, 0);
|
1081
|
+
rb_define_method(cStat, "downloaded", r_stat_downloaded, 0);
|
1082
|
+
rb_define_method(cStat, "uploaded", r_stat_uploaded, 0);
|
1083
|
+
|
1084
|
+
rb_define_const(cStat, "STATUS_CHECK", INT2FIX(TR_STATUS_CHECK));
|
1085
|
+
rb_define_const(cStat, "STATUS_DOWNLOAD", INT2FIX(TR_STATUS_DOWNLOAD));
|
1086
|
+
rb_define_const(cStat, "STATUS_SEED", INT2FIX(TR_STATUS_SEED));
|
1087
|
+
rb_define_const(cStat, "STATUS_STOPPING", INT2FIX(TR_STATUS_STOPPING));
|
1088
|
+
rb_define_const(cStat, "STATUS_STOPPED", INT2FIX(TR_STATUS_STOPPED));
|
1089
|
+
rb_define_const(cStat, "STATUS_PAUSE", INT2FIX(TR_STATUS_PAUSE));
|
1090
|
+
rb_define_const(cStat, "STATUS_ACTIVE", INT2FIX(TR_STATUS_ACTIVE));
|
1091
|
+
rb_define_const(cStat, "STATUS_INACTIVE", INT2FIX(TR_STATUS_INACTIVE));
|
1092
|
+
|
1093
|
+
rb_define_const(cStat, "ERR_TRACKER", INT2FIX(TR_ETRACKER));
|
1094
|
+
rb_define_const(cStat, "ERR_INOUT", INT2FIX(TR_EINOUT));
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
/*
|
1098
|
+
* Document-class: Transmission
|
1099
|
+
*
|
1100
|
+
* == Summary
|
1101
|
+
*
|
1102
|
+
* The Transmission class represent a bittorrent session. You can use an instance of
|
1103
|
+
* this class to open a torrent and start its downloading process.
|
1104
|
+
*/
|
1105
|
+
void
|
1106
|
+
Init_transmission()
|
1107
|
+
{
|
1108
|
+
cTransmission = rb_define_class("Transmission", rb_cObject);
|
1109
|
+
|
1110
|
+
rb_define_const(cTransmission, "VERSION", rb_obj_freeze(rb_str_new2(VERSION)));
|
1111
|
+
|
1112
|
+
rb_define_module_function(cTransmission, "pref_directory", r_transmission_pref_dir, 0);
|
1113
|
+
|
1114
|
+
rb_define_alloc_func(cTransmission, r_transmission_alloc);
|
1115
|
+
rb_define_method(cTransmission, "bind_port=", r_transmission_set_bind_port, 1);
|
1116
|
+
rb_define_method(cTransmission, "open", r_transmission_open, -1);
|
1117
|
+
rb_define_method(cTransmission, "size", r_transmission_size, 0);
|
1118
|
+
rb_define_method(cTransmission, "length", r_transmission_size, 0);
|
1119
|
+
rb_define_method(cTransmission, "each", r_transmission_each, 0);
|
1120
|
+
rb_define_method(cTransmission, "rates", r_transmission_rates, 0);
|
1121
|
+
rb_define_method(cTransmission, "upload_limit=", r_transmission_set_upload_limit, 1);
|
1122
|
+
rb_define_method(cTransmission, "download_limit=", r_transmission_set_download_limit, 1);
|
1123
|
+
|
1124
|
+
rb_include_module(cTransmission, rb_mEnumerable);
|
1125
|
+
|
1126
|
+
eTransmissionError = rb_define_class_under(cTransmission, "TransmissionError", rb_eStandardError);
|
1127
|
+
eParseError = rb_define_class_under(cTransmission, "ParseError", eTransmissionError);
|
1128
|
+
eUnsupportedError = rb_define_class_under(cTransmission, "UnsupportedError", eTransmissionError);
|
1129
|
+
eDuplicateError = rb_define_class_under(cTransmission, "DuplicateError", eTransmissionError);
|
1130
|
+
eTorrentError = rb_define_class_under(cTransmission, "TorrentError", eTransmissionError);
|
1131
|
+
|
1132
|
+
Init_torrent();
|
1133
|
+
Init_fileinfo();
|
1134
|
+
Init_stat();
|
1135
|
+
}
|