source: trunk/macosx/Torrent.m @ 261

Last change on this file since 261 was 261, checked in by titer, 16 years ago

Updated svn:keywords

  • Property svn:keywords set to Date Rev Author Id
File size: 11.6 KB
Line 
1/******************************************************************************
2 * $Id: Torrent.m 261 2006-05-29 21:27:31Z titer $
3 *
4 * Copyright (c) 2006 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
25#import "Torrent.h"
26#import "StringAdditions.h"
27#import "Utils.h"
28
29@interface Torrent (Private)
30
31- (void) trashPath: (NSString *) path;
32- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
33        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
34
35@end
36
37
38@implementation Torrent
39
40- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
41{
42    return [self initWithPath: path lib: lib
43            date: nil stopRatioSetting: nil
44            ratioLimit: nil];
45}
46
47- (id) initWithHistory: (NSDictionary *) history lib: (tr_handle_t *) lib
48{
49    self = [self initWithPath: [history objectForKey: @"TorrentPath"]
50            lib: lib date: [history objectForKey: @"Date"]
51            stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
52            ratioLimit: [history objectForKey: @"RatioLimit"]];
53           
54    if (self)
55    {
56        NSString * downloadFolder;
57        if (!(downloadFolder = [history objectForKey: @"DownloadFolder"]))
58            downloadFolder = [[fDefaults stringForKey: @"DownloadFolder"]
59                                stringByExpandingTildeInPath];
60        [self setFolder: downloadFolder];
61
62        NSString * paused;
63        if (!(paused = [history objectForKey: @"Paused"]) || [paused isEqualToString: @"NO"])
64            [self start];
65    }
66   
67    return self;
68}
69
70- (NSDictionary *) history
71{
72    return [NSDictionary dictionaryWithObjectsAndKeys:
73            [self path], @"TorrentPath",
74            [self getFolder], @"DownloadFolder",
75            [self isActive] ? @"NO" : @"YES", @"Paused",
76            [self date], @"Date",
77            [NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
78            [NSNumber numberWithFloat: fRatioLimit], @"RatioLimit", nil];
79}
80
81- (void) dealloc
82{
83    if( fHandle )
84    {
85        tr_torrentClose( fLib, fHandle );
86       
87        [fDate release];
88        [fIcon release];
89        [fIconNonFlipped release];
90        [fStatusString release];
91        [fInfoString release];
92        [fDownloadString release];
93        [fUploadString release];
94    }
95    [super dealloc];
96}
97
98- (void) setFolder: (NSString *) path
99{
100    tr_torrentSetFolder( fHandle, [path UTF8String] );
101}
102
103- (NSString *) getFolder
104{
105    return [NSString stringWithUTF8String: tr_torrentGetFolder( fHandle )];
106}
107
108- (void) getAvailability: (int8_t *) tab size: (int) size
109{
110    tr_torrentAvailability( fHandle, tab, size );
111}
112
113- (void) update
114{
115    fStat = tr_torrentStat( fHandle );
116   
117    if ([self isSeeding])
118        if ((fStopRatioSetting == 1 && [self ratio] >= fRatioLimit)
119            || (fStopRatioSetting == -1 && [fDefaults boolForKey: @"RatioCheck"]
120                && [self ratio] >= [fDefaults floatForKey: @"RatioLimit"]))
121        {
122            [self stop];
123            [self setStopRatioSetting: 0];
124           
125            fStat = tr_torrentStat( fHandle );
126        }
127
128    [fStatusString setString: @""];
129    [fInfoString setString: @""];
130
131    switch( fStat->status )
132    {
133        case TR_STATUS_PAUSE:
134            [fStatusString appendFormat: @"Paused (%.2f %%)",
135                100 * fStat->progress];
136            break;
137
138        case TR_STATUS_CHECK:
139            [fStatusString appendFormat:
140                @"Checking existing files (%.2f %%)",
141                100 * fStat->progress];
142            break;
143
144        case TR_STATUS_DOWNLOAD:
145            if( fStat->eta < 0 )
146            {
147                [fStatusString appendFormat:
148                    @"Finishing in --:--:-- (%.2f %%)",
149                    100 * fStat->progress];
150            }
151            else
152            {
153                [fStatusString appendFormat:
154                    @"Finishing in %02d:%02d:%02d (%.2f %%)",
155                    fStat->eta / 3600, ( fStat->eta / 60 ) % 60,
156                    fStat->eta % 60, 100 * fStat->progress];
157            }
158            [fInfoString appendFormat:
159                @"Downloading from %d of %d peer%s",
160                fStat->peersUploading, fStat->peersTotal,
161                ( fStat->peersTotal == 1 ) ? "" : "s"];
162            break;
163
164        case TR_STATUS_SEED:
165            [fStatusString appendFormat:
166                @"Seeding, uploading to %d of %d peer%s",
167                fStat->peersDownloading, fStat->peersTotal,
168                ( fStat->peersTotal == 1 ) ? "" : "s"];
169            break;
170
171        case TR_STATUS_STOPPING:
172            [fStatusString setString: [@"Stopping"
173                stringByAppendingString: NS_ELLIPSIS]];
174            break;
175    }
176
177    if( fStat->error & TR_ETRACKER )
178    {
179        [fInfoString setString: [@"Error: " stringByAppendingString:
180            [NSString stringWithUTF8String: fStat->trackerError]]];
181    }
182
183    if( fStat->progress == 1.0 )
184    {
185        [fDownloadString setString: [@"Ratio: " stringByAppendingString:
186            [NSString stringForRatio: fStat->downloaded
187            upload: fStat->uploaded]]];
188    }
189    else
190    {
191        [fDownloadString setString: [@"DL: " stringByAppendingString:
192            [NSString stringForSpeed: fStat->rateDownload]]];
193    }
194    [fUploadString setString: [@"UL: " stringByAppendingString:
195        [NSString stringForSpeed: fStat->rateUpload]]];
196}
197
198- (void) start
199{
200    if( fStat->status & TR_STATUS_INACTIVE )
201    {
202        tr_torrentStart( fHandle );
203    }
204}
205
206- (void) stop
207{
208    if( fStat->status & TR_STATUS_ACTIVE )
209    {
210        tr_torrentStop( fHandle );
211    }
212}
213
214- (void) sleep
215{
216    if( ( fResumeOnWake = ( fStat->status & TR_STATUS_ACTIVE ) ) )
217    {
218        [self stop];
219    }
220}
221
222- (void) wakeUp
223{
224    if( fResumeOnWake )
225    {
226        [self start];
227    }
228}
229
230- (float) ratio
231{
232    uint64_t downloaded = [self downloaded];
233    return downloaded > 0 ? [self uploaded] / downloaded : -1;
234}
235
236/*  1: Check ratio
237    0: Don't check ratio
238   -1: Use defaults */
239- (int) stopRatioSetting
240{
241        return fStopRatioSetting;
242}
243
244- (void) setStopRatioSetting: (int) setting
245{
246    fStopRatioSetting = setting;
247}
248
249- (float) ratioLimit
250{
251    return fRatioLimit;
252}
253
254- (void) setRatioLimit: (float) limit
255{
256    if (limit >= 0)
257        fRatioLimit = limit;
258}
259
260- (void) reveal
261{
262    [[NSWorkspace sharedWorkspace] selectFile: [[self getFolder]
263        stringByAppendingPathComponent: [self name]]
264        inFileViewerRootedAtPath: nil];
265}
266
267- (void) trashTorrent
268{
269    [self trashPath: [self path]];
270}
271
272- (void) trashData
273{
274    [self trashPath: [[self getFolder]
275        stringByAppendingPathComponent: [self name]]];
276}
277
278- (NSImage *) icon
279{
280    return fIcon;
281}
282
283- (NSImage *) iconNonFlipped
284{
285    return fIconNonFlipped;
286}
287
288- (NSString *) path
289{
290    return [NSString stringWithUTF8String: fInfo->torrent];
291}
292
293- (NSString *) name
294{
295    return [NSString stringWithUTF8String: fInfo->name];
296}
297
298- (uint64_t) size
299{
300    return fInfo->totalSize;
301}
302
303- (NSString *) tracker
304{
305    return [NSString stringWithFormat: @"%s:%d",
306            fInfo->trackerAddress, fInfo->trackerPort];
307}
308
309- (NSString *) announce
310{
311    return [NSString stringWithUTF8String: fInfo->trackerAnnounce];
312}
313
314- (int) pieceSize
315{
316    return fInfo->pieceSize;
317}
318
319- (int) pieceCount
320{
321    return fInfo->pieceCount;
322}
323
324- (NSString *) hash
325{
326    NSMutableString * string = [NSMutableString
327        stringWithCapacity: SHA_DIGEST_LENGTH];
328    int i;
329    for( i = 0; i < SHA_DIGEST_LENGTH; i++ )
330    {
331        [string appendFormat: @"%02x", fInfo->hash[i]];
332    }
333    return string;
334}
335
336- (float) progress
337{
338    return fStat->progress;
339}
340
341- (BOOL) isActive
342{
343    return ( fStat->status & TR_STATUS_ACTIVE );
344}
345
346- (BOOL) isSeeding
347{
348    return ( fStat->status == TR_STATUS_SEED );
349}
350
351- (BOOL) isPaused
352{
353    return ( fStat->status == TR_STATUS_PAUSE );
354}
355
356- (BOOL) justFinished
357{
358    return tr_getFinished( fHandle );
359}
360
361- (NSString *) statusString
362{
363    return fStatusString;
364}
365
366- (NSString *) infoString
367{
368    return fInfoString;
369}
370
371- (NSString *) downloadString
372{
373    return fDownloadString;
374}
375
376- (NSString *) uploadString
377{
378    return fUploadString;
379}
380
381- (int) seeders
382{
383    return fStat->seeders;
384}
385
386- (int) leechers
387{
388    return fStat->leechers;
389}
390
391- (uint64_t) downloaded
392{
393    return fStat->downloaded;
394}
395
396- (uint64_t) uploaded
397{
398    return fStat->uploaded;
399}
400
401- (NSDate *) date
402{
403    return fDate;
404}
405
406- (NSNumber *) stateSortKey
407{
408    if (fStat->status & TR_STATUS_INACTIVE)
409        return [NSNumber numberWithInt: 0];
410    else if (fStat->status == TR_STATUS_SEED)
411        return [NSNumber numberWithInt: 1];
412    else
413        return [NSNumber numberWithInt: 2];
414}
415
416@end
417
418
419@implementation Torrent (Private)
420
421- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
422        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
423{
424    if (!(self = [super init]))
425        return nil;
426
427    fLib = lib;
428
429    int error;
430    if (!path || !(fHandle = tr_torrentInit(fLib, [path UTF8String], &error)))
431    {
432        [self release];
433        return nil;
434    }
435   
436    fInfo = tr_torrentInfo( fHandle );
437   
438    fDefaults = [NSUserDefaults standardUserDefaults];
439
440    fDate = date ? [date retain] : [[NSDate alloc] init];
441    fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
442    fRatioLimit = ratioLimit ? [ratioLimit floatValue] : [fDefaults floatForKey: @"RatioLimit"];
443   
444    NSString * fileType = ( fInfo->fileCount > 1 ) ?
445        NSFileTypeForHFSTypeCode('fldr') : [[self name] pathExtension];
446    fIcon = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
447    [fIcon setFlipped: YES];
448    [fIcon retain];
449    fIconNonFlipped = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
450    [fIconNonFlipped retain];
451
452    fStatusString   = [[NSMutableString alloc] initWithCapacity: 50];
453    fInfoString     = [[NSMutableString alloc] initWithCapacity: 50];
454    fDownloadString = [[NSMutableString alloc] initWithCapacity: 10];
455    fUploadString   = [[NSMutableString alloc] initWithCapacity: 10];
456
457    [self update];
458    return self;
459}
460
461- (void) trashPath: (NSString *) path
462{
463    if( ![[NSWorkspace sharedWorkspace] performFileOperation:
464           NSWorkspaceRecycleOperation source:
465           [path stringByDeletingLastPathComponent]
466           destination: @""
467           files: [NSArray arrayWithObject: [path lastPathComponent]]
468           tag: nil] )
469    {
470        /* We can't move it to the trash, let's try just to delete it
471           (will work if it is on a remote volume) */
472        if( ![[NSFileManager defaultManager]
473                removeFileAtPath: path handler: nil] )
474        {
475            NSLog( [@"Could not trash " stringByAppendingString: path] );
476        }
477    }
478}
479
480@end
Note: See TracBrowser for help on using the repository browser.