source: trunk/macosx/Torrent.m @ 256

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

Merged Mitchell's changes, this includes:
Adds stop at ratio,
Adds sorting by name, date or state,
Seperates Info window into its own nib,
Adds option to enable or disabled autostarting downloads,
Seperates Network / Transfers in the Preferences

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