source: branches/save_torrent_files/macosx/Torrent.m @ 295

Last change on this file since 295 was 295, checked in by livings124, 16 years ago

trying to get it to work

  • Property svn:keywords set to Date Rev Author Id
File size: 15.3 KB
Line 
1/******************************************************************************
2 * $Id: Torrent.m 295 2006-06-08 05:48:40Z livings124 $
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- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
32        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
33- (id) initWithHash: (NSString *) hashString lib: (tr_handle_t *) lib date: (NSDate *) date
34        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
35- (id) initForSuccessWithDate: (NSDate *) date stopRatioSetting: (NSNumber *)
36            stopRatioSetting ratioLimit: (NSNumber *) ratioLimit;
37
38- (void) trashPath: (NSString *) path;
39
40@end
41
42
43@implementation Torrent
44
45- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib
46{NSLog(path);
47    id torrent = [self initWithPath: path lib: lib date: nil
48                    stopRatioSetting: nil ratioLimit: nil];
49                   
50    if (!torrent)
51        return nil;
52
53    if (fPrivateSaved && [fDefaults boolForKey: @"DeleteOriginalTorrent"])
54        [self trashPath: path];
55   
56    return torrent;
57}
58
59- (id) initWithHistory: (NSDictionary *) history lib: (tr_handle_t *) lib
60{
61    NSNumber * privateCopy;
62    if ((privateCopy = [history objectForKey: @"PrivateCopy"]) && [privateCopy boolValue])
63        self = [self initWithHash: [history objectForKey: @"TorrentHash"]
64            lib: lib date: [history objectForKey: @"Date"]
65            stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
66            ratioLimit: [history objectForKey: @"RatioLimit"]];
67    else
68        self = [self initWithPath: [history objectForKey: @"TorrentPath"]
69            lib: lib date: [history objectForKey: @"Date"]
70            stopRatioSetting: [history objectForKey: @"StopRatioSetting"]
71            ratioLimit: [history objectForKey: @"RatioLimit"]];
72           
73    if (self)
74    {
75        NSString * downloadFolder;
76        if (!(downloadFolder = [history objectForKey: @"DownloadFolder"]))
77            downloadFolder = [[fDefaults stringForKey: @"DownloadFolder"]
78                                stringByExpandingTildeInPath];
79        [self setDownloadFolder: downloadFolder];
80
81        NSString * paused;
82        if (!(paused = [history objectForKey: @"Paused"]) || [paused isEqualToString: @"NO"])
83            [self start];
84    }
85    return self;
86}
87
88- (NSDictionary *) history
89{
90    NSMutableDictionary * history = [NSMutableDictionary dictionaryWithObjectsAndKeys:
91                    [NSNumber numberWithBool: fPrivateSaved], @"PrivateCopy",
92                    [self downloadFolder], @"DownloadFolder",
93                    [self isActive] ? @"NO" : @"YES", @"Paused",
94                    [self date], @"Date",
95                    [NSNumber numberWithInt: fStopRatioSetting], @"StopRatioSetting",
96                    [NSNumber numberWithFloat: fRatioLimit], @"RatioLimit", nil];
97           
98    if (fPrivateSaved)
99        [history setObject: [self torrentLocation] forKey: @"TorrentPath"];
100    else
101        [history setObject: [self hashString] forKey: @"TorrentHash"];
102   
103    return history;
104}
105
106- (void) dealloc
107{
108    if( fHandle )
109    {
110        tr_torrentClose( fLib, fHandle );
111       
112        [fDate release];
113        [fIcon release];
114        [fIconFlipped release];
115        [fProgressString release];
116        [fStatusString release];
117    }
118    [super dealloc];
119}
120
121- (void) setDownloadFolder: (NSString *) path
122{
123    tr_torrentSetFolder( fHandle, [path UTF8String] );
124}
125
126- (NSString *) downloadFolder
127{
128    return [NSString stringWithUTF8String: tr_torrentGetFolder( fHandle )];
129}
130
131- (void) getAvailability: (int8_t *) tab size: (int) size
132{
133    tr_torrentAvailability( fHandle, tab, size );
134}
135
136- (void) update
137{
138    fStat = tr_torrentStat( fHandle );
139   
140    if ([self isSeeding])
141        if ((fStopRatioSetting == RATIO_CHECK && [self ratio] >= fRatioLimit)
142            || (fStopRatioSetting == RATIO_GLOBAL && [fDefaults boolForKey: @"RatioCheck"]
143                && [self ratio] >= [fDefaults floatForKey: @"RatioLimit"]))
144        {
145            [self stop];
146            [self setStopRatioSetting: RATIO_NO_CHECK];
147           
148            fStat = tr_torrentStat( fHandle );
149           
150            [[NSNotificationCenter defaultCenter] postNotificationName:
151                @"TorrentRatioChanged" object: self];
152        }
153   
154    [fProgressString setString: @""];
155    if ([self progress] < 1.0)
156        [fProgressString appendFormat: @"%@ of %@ completed (%.2f%%)", [NSString stringForFileSize:
157                [self downloaded]], [NSString stringForFileSize: [self size]], 100 * [self progress]];
158    else
159        [fProgressString appendFormat: @"%@, uploaded %@ (ratio: %@)", [NSString stringForFileSize:
160                [self size]], [NSString stringForFileSize: [self uploaded]],
161                [NSString stringForRatioWithDownload: [self downloaded] upload: [self uploaded]]];
162
163    switch( fStat->status )
164    {
165        case TR_STATUS_PAUSE:
166            [fStatusString setString: @"Paused"];
167            break;
168
169        case TR_STATUS_CHECK:
170            [fStatusString setString: [@"Checking existing files" stringByAppendingString: NS_ELLIPSIS]];
171            break;
172
173        case TR_STATUS_DOWNLOAD:
174            [fStatusString setString: @""];
175            [fStatusString appendFormat:
176                @"Downloading from %d of %d peer%s",
177                [self peersUploading], [self totalPeers],
178                ([self totalPeers] == 1) ? "" : "s"];
179           
180            int eta = fStat->eta;
181            if (eta < 0)
182                [fProgressString appendString: @" - remaining time unknown"];
183            else
184            {
185                if (eta < 60)
186                    [fProgressString appendFormat: @" - %d sec remaining", eta];
187                else if (eta < 3600)
188                    [fProgressString appendFormat: @" - %d min %02d sec remaining",
189                                                    eta / 60, eta % 60];
190                else
191                    [fProgressString appendFormat: @" - %d hr %02d min remaining",
192                                                    eta / 3600, (eta / 60) % 60];
193            }
194            break;
195
196        case TR_STATUS_SEED:
197            [fStatusString setString: @""];
198            [fStatusString appendFormat:
199                @"Seeding to %d of %d peer%s",
200                [self peersDownloading], [self totalPeers],
201                ([self totalPeers] == 1) ? "" : "s"];
202            break;
203
204        case TR_STATUS_STOPPING:
205            [fStatusString setString: [@"Stopping" stringByAppendingString: NS_ELLIPSIS]];
206            break;
207    }
208   
209    if( fStat->error & TR_ETRACKER )
210    {
211        [fStatusString setString: [@"Error: " stringByAppendingString:
212            [NSString stringWithUTF8String: fStat->trackerError]]];
213    }
214
215    if ([self isActive])
216    {
217        if ([self progress] < 1.0)
218            [fStatusString appendFormat: @" - DL: %@, ", [NSString stringForSpeed: [self downloadRate]]];
219        [fStatusString appendString: [@"UL: " stringByAppendingString:
220                                                [NSString stringForSpeed: [self uploadRate]]]];
221    }
222}
223
224- (void) start
225{
226    if( fStat->status & TR_STATUS_INACTIVE )
227    {
228        tr_torrentStart( fHandle );
229    }
230}
231
232- (void) stop
233{
234    if( fStat->status & TR_STATUS_ACTIVE )
235    {
236        tr_torrentStop( fHandle );
237    }
238}
239
240- (void) removeForever
241{
242    tr_torrentRemoveSaved(fHandle);
243}
244
245- (void) sleep
246{
247    if( ( fResumeOnWake = ( fStat->status & TR_STATUS_ACTIVE ) ) )
248    {
249        [self stop];
250    }
251}
252
253- (void) wakeUp
254{
255    if( fResumeOnWake )
256    {
257        [self start];
258    }
259}
260
261- (float) ratio
262{
263    float downloaded = [self downloaded];
264    return downloaded > 0 ? (float)[self uploaded] / downloaded : -1;
265}
266
267- (int) stopRatioSetting
268{
269        return fStopRatioSetting;
270}
271
272- (void) setStopRatioSetting: (int) setting
273{
274    fStopRatioSetting = setting;
275}
276
277- (float) ratioLimit
278{
279    return fRatioLimit;
280}
281
282- (void) setRatioLimit: (float) limit
283{
284    if (limit >= 0)
285        fRatioLimit = limit;
286}
287
288- (void) reveal
289{
290    [[NSWorkspace sharedWorkspace] selectFile: [self dataLocation]
291        inFileViewerRootedAtPath: nil];
292}
293
294- (void) trashData
295{
296    [self trashPath: [self dataLocation]];
297}
298
299- (NSImage *) icon
300{
301    return fIcon;
302}
303
304- (NSImage *) iconFlipped
305{
306    return fIconFlipped;
307}
308
309- (NSString *) name
310{
311    return [NSString stringWithUTF8String: fInfo->name];
312}
313
314- (uint64_t) size
315{
316    return fInfo->totalSize;
317}
318
319- (NSString *) tracker
320{
321    return [NSString stringWithFormat: @"%s:%d",
322            fInfo->trackerAddress, fInfo->trackerPort];
323}
324
325- (NSString *) announce
326{
327    return [NSString stringWithUTF8String: fInfo->trackerAnnounce];
328}
329
330- (int) pieceSize
331{
332    return fInfo->pieceSize;
333}
334
335- (int) pieceCount
336{
337    return fInfo->pieceCount;
338}
339
340- (NSString *) hashString
341{
342    return [NSString stringWithUTF8String: fInfo->hashString];
343}
344
345- (NSString *) torrentLocation
346{
347    return [NSString stringWithUTF8String: fInfo->torrent];
348}
349
350- (NSString *) dataLocation
351{
352    return [[self downloadFolder] stringByAppendingPathComponent: [self name]];
353}
354
355- (NSString *) state
356{
357    switch( fStat->status )
358    {
359        case TR_STATUS_PAUSE:
360            return @"Paused";
361            break;
362
363        case TR_STATUS_CHECK:
364            return [@"Checking existing files" stringByAppendingString: NS_ELLIPSIS];
365            break;
366
367        case TR_STATUS_DOWNLOAD:
368            return @"Downloading";
369            break;
370
371        case TR_STATUS_SEED:
372            return @"Seeding";
373            break;
374
375        case TR_STATUS_STOPPING:
376            return [@"Stopping" stringByAppendingString: NS_ELLIPSIS];
377            break;
378       
379        default:
380            return @"N/A";
381    }
382}
383
384- (float) progress
385{
386    return fStat->progress;
387}
388
389- (BOOL) isActive
390{
391    return ( fStat->status & TR_STATUS_ACTIVE );
392}
393
394- (BOOL) isSeeding
395{
396    return ( fStat->status == TR_STATUS_SEED );
397}
398
399- (BOOL) isPaused
400{
401    return ( fStat->status == TR_STATUS_PAUSE );
402}
403
404- (BOOL) justFinished
405{
406    return tr_getFinished( fHandle );
407}
408
409- (NSString *) progressString
410{
411    return fProgressString;
412}
413
414- (NSString *) statusString
415{
416    return fStatusString;
417}
418
419- (int) seeders
420{
421    return fStat->seeders;
422}
423
424- (int) leechers
425{
426    return fStat->leechers;
427}
428
429- (int) totalPeers
430{
431    return fStat->peersTotal;
432}
433
434//peers uploading to you
435- (int) peersUploading
436{
437    return fStat->peersUploading;
438}
439
440//peers downloading from you
441- (int) peersDownloading
442{
443    return fStat->peersDownloading;
444}
445
446- (float) downloadRate
447{
448    return fStat->rateDownload;
449}
450
451- (float) uploadRate
452{
453    return fStat->rateUpload;
454}
455
456- (uint64_t) downloaded
457{
458    return fStat->downloaded;
459}
460
461- (uint64_t) uploaded
462{
463    return fStat->uploaded;
464}
465
466- (NSArray *) fileList
467{
468    int count = fInfo->fileCount, i;
469    NSMutableArray * files = [NSMutableArray arrayWithCapacity: count];
470    for (i = 0; i < count; i++)
471        [files addObject: [[self downloadFolder] stringByAppendingPathComponent:
472            [NSString stringWithUTF8String: fInfo->files[i].name]]];
473    return files;
474}
475
476- (NSDate *) date
477{
478    return fDate;
479}
480
481- (NSNumber *) stateSortKey
482{
483    if (fStat->status & TR_STATUS_INACTIVE)
484        return [NSNumber numberWithInt: 0];
485    else if (fStat->status == TR_STATUS_SEED)
486        return [NSNumber numberWithInt: 1];
487    else
488        return [NSNumber numberWithInt: 2];
489}
490
491- (NSNumber *) progressSortKey
492{
493    return [NSNumber numberWithFloat: [self progress]];
494}
495
496@end
497
498
499@implementation Torrent (Private)
500
501- (id) initWithPath: (NSString *) path lib: (tr_handle_t *) lib date: (NSDate *) date
502        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
503{
504    if (!(self = [super init]))
505        return nil;
506
507    fLib = lib;
508    fDefaults = [NSUserDefaults standardUserDefaults];
509
510    fPrivateSaved = [fDefaults boolForKey: @"SavePrivateTorrent"];
511
512    int error;
513    if (!path || !(fHandle = tr_torrentInit(fLib, [path UTF8String],
514                    fPrivateSaved ? TR_FSAVEPRIVATE : 0, & error)))
515    {
516        [self release];
517        return nil;
518    }
519
520    return [self initForSuccessWithDate: date stopRatioSetting: stopRatioSetting ratioLimit: ratioLimit];
521}
522
523- (id) initWithHash: (NSString *) hashString lib: (tr_handle_t *) lib date: (NSDate *) date
524        stopRatioSetting: (NSNumber *) stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
525{
526    if (!(self = [super init]))
527        return nil;
528
529    fLib = lib;
530    fDefaults = [NSUserDefaults standardUserDefaults];
531   
532    fPrivateSaved = YES;
533
534    int error;
535    if (!hashString || !(fHandle = tr_torrentInitSaved(fLib, [hashString UTF8String], TR_FSAVEPRIVATE, & error)))
536    {
537        [self release];
538        return nil;
539    }
540   
541    return [self initForSuccessWithDate: date stopRatioSetting: stopRatioSetting ratioLimit: ratioLimit];
542}
543
544- (id) initForSuccessWithDate: (NSDate *) date stopRatioSetting: (NSNumber *)
545            stopRatioSetting ratioLimit: (NSNumber *) ratioLimit
546{
547    fInfo = tr_torrentInfo( fHandle );
548
549    fDate = date ? [date retain] : [[NSDate alloc] init];
550    fStopRatioSetting = stopRatioSetting ? [stopRatioSetting intValue] : -1;
551    fRatioLimit = ratioLimit ? [ratioLimit floatValue] : [fDefaults floatForKey: @"RatioLimit"];
552   
553    NSString * fileType = ( fInfo->fileCount > 1 ) ?
554        NSFileTypeForHFSTypeCode('fldr') : [[self name] pathExtension];
555    fIcon = [[NSWorkspace sharedWorkspace] iconForFileType: fileType];
556    [fIcon retain];
557   
558    fIconFlipped = [fIcon copy];
559    [fIconFlipped setFlipped: YES];
560
561    fProgressString = [[NSMutableString alloc] initWithCapacity: 50];
562    fStatusString = [[NSMutableString alloc] initWithCapacity: 75];
563
564    [self update];
565    return self;
566}
567
568
569- (void) trashPath: (NSString *) path
570{
571    if( ![[NSWorkspace sharedWorkspace] performFileOperation:
572           NSWorkspaceRecycleOperation source:
573           [path stringByDeletingLastPathComponent]
574           destination: @""
575           files: [NSArray arrayWithObject: [path lastPathComponent]]
576           tag: nil] )
577    {
578        /* We can't move it to the trash, let's try just to delete it
579           (will work if it is on a remote volume) */
580        if( ![[NSFileManager defaultManager]
581                removeFileAtPath: path handler: nil] )
582        {
583            NSLog( [@"Could not trash " stringByAppendingString: path] );
584        }
585    }
586}
587
588@end
Note: See TracBrowser for help on using the repository browser.