diff --git a/macosx/Controller.m b/macosx/Controller.m index e58afc94b..39a6ae35e 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -1343,7 +1343,7 @@ static void sleepCallBack(void * controller, io_service_t y, natural_t messageTy { enumerator = [fTorrents objectEnumerator]; while ((torrent = [enumerator nextObject])) - if ([torrent isActive] && ![torrent isError]) + if ([torrent isActive] && ![torrent isStalled] && ![torrent isError]) { if ([torrent allDownloaded]) desiredSeedActive--; diff --git a/macosx/Defaults.plist b/macosx/Defaults.plist index 85f786d27..9576a34c8 100644 --- a/macosx/Defaults.plist +++ b/macosx/Defaults.plist @@ -24,6 +24,8 @@ CheckRemoveDownloading + CheckStalled + CheckUpload DeleteOriginalTorrent @@ -98,6 +100,8 @@ 10 SpeedLimitUploadLimit 10 + StalledSeconds + 300 StatusBar UpdateCheck diff --git a/macosx/English.lproj/PrefsWindow.nib/classes.nib b/macosx/English.lproj/PrefsWindow.nib/classes.nib index d2b94f387..0bf38b9be 100644 --- a/macosx/English.lproj/PrefsWindow.nib/classes.nib +++ b/macosx/English.lproj/PrefsWindow.nib/classes.nib @@ -25,6 +25,8 @@ setRatioStop = id; setSound = id; setSpeedLimit = id; + setStalled = id; + setStalledSeconds = id; setUpdate = id; }; CLASS = PrefsController; @@ -51,6 +53,7 @@ fSeedingSoundPopUp = NSPopUpButton; fSpeedLimitDownloadField = NSTextField; fSpeedLimitUploadField = NSTextField; + fStalledField = NSTextField; fTransfersView = NSView; fUpdatePopUp = NSPopUpButton; fUploadField = NSTextField; diff --git a/macosx/English.lproj/PrefsWindow.nib/info.nib b/macosx/English.lproj/PrefsWindow.nib/info.nib index 0e2a3759b..fff0485c7 100644 --- a/macosx/English.lproj/PrefsWindow.nib/info.nib +++ b/macosx/English.lproj/PrefsWindow.nib/info.nib @@ -7,11 +7,11 @@ IBEditorPositions 153 - 206 273 563 268 0 0 1152 842 + 294 444 563 268 0 0 1152 842 28 294 421 563 313 0 0 1152 842 41 - 294 425 563 305 0 0 1152 842 + 70 441 563 305 0 0 1152 842 66 294 506 563 144 0 0 1152 842 diff --git a/macosx/English.lproj/PrefsWindow.nib/keyedobjects.nib b/macosx/English.lproj/PrefsWindow.nib/keyedobjects.nib index b63661b01..6a0d2f3e2 100644 Binary files a/macosx/English.lproj/PrefsWindow.nib/keyedobjects.nib and b/macosx/English.lproj/PrefsWindow.nib/keyedobjects.nib differ diff --git a/macosx/PrefsController.h b/macosx/PrefsController.h index 6e8c2b0dd..1725320c7 100644 --- a/macosx/PrefsController.h +++ b/macosx/PrefsController.h @@ -39,7 +39,7 @@ IBOutlet NSPopUpButton * fFolderPopUp, * fIncompleteFolderPopUp, * fImportFolderPopUp, * fDownloadSoundPopUp, * fSeedingSoundPopUp; - IBOutlet NSTextField * fRatioStopField, * fQueueDownloadField, * fQueueSeedField; + IBOutlet NSTextField * fRatioStopField, * fQueueDownloadField, * fQueueSeedField, * fStalledField; NSArray * fSounds; @@ -68,6 +68,9 @@ - (void) setQueue: (id) sender; - (void) setQueueNumber: (id) sender; +- (void) setStalled: (id) sender; +- (void) setStalledSeconds: (id) sender; + - (void) setDownloadLocation: (id) sender; - (void) folderSheetShow: (id) sender; - (void) incompleteFolderSheetShow: (id) sender; diff --git a/macosx/PrefsController.m b/macosx/PrefsController.m index c7469f8b3..232972d7c 100644 --- a/macosx/PrefsController.m +++ b/macosx/PrefsController.m @@ -155,6 +155,9 @@ [fQueueDownloadField setIntValue: [fDefaults integerForKey: @"QueueDownloadNumber"]]; [fQueueSeedField setIntValue: [fDefaults integerForKey: @"QueueSeedNumber"]]; + //set stalled value + [fStalledField setIntValue: [fDefaults integerForKey: @"StalledSeconds"]]; + //set update check NSString * updateCheck = [fDefaults stringForKey: @"UpdateCheck"]; if ([updateCheck isEqualToString: @"Weekly"]) @@ -484,10 +487,28 @@ } [fDefaults setInteger: limit forKey: download ? @"QueueDownloadNumber" : @"QueueSeedNumber"]; - [self setQueue: nil]; } +- (void) setStalled: (id) sender +{ + [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateUI" object: self]; +} + +- (void) setStalledSeconds: (id) sender +{ + int seconds = [sender intValue]; + if (![[sender stringValue] isEqualToString: [NSString stringWithFormat: @"%d", seconds]] || seconds < 0) + { + NSBeep(); + [sender setIntValue: [fDefaults integerForKey: @"StalledSeconds"]]; + return; + } + + [fDefaults setInteger: seconds forKey: @"StalledSeconds"]; + [self setQueueStalled: nil]; +} + - (void) setDownloadLocation: (id) sender { switch ([fFolderPopUp indexOfSelectedItem]) diff --git a/macosx/Torrent.h b/macosx/Torrent.h index 787a5efe5..e55170f84 100644 --- a/macosx/Torrent.h +++ b/macosx/Torrent.h @@ -56,7 +56,7 @@ int fUploadLimit, fDownloadLimit; float fRatioLimit; int fCheckUpload, fCheckDownload, fRatioSetting; - BOOL fFinishedSeeding, fWaitToStart, fError, fChecking; + BOOL fFinishedSeeding, fWaitToStart, fError, fChecking, fStalled; int fOrderValue; @@ -205,6 +205,9 @@ - (NSDate *) dateCompleted; - (NSDate *) dateActivity; +- (int) stalledSeconds; +- (BOOL) isStalled; + - (NSNumber *) stateSortKey; - (NSNumber *) progressSortKey; - (NSNumber *) ratioSortKey; diff --git a/macosx/Torrent.m b/macosx/Torrent.m index 2f3c38c31..cb258244c 100644 --- a/macosx/Torrent.m +++ b/macosx/Torrent.m @@ -445,21 +445,23 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 break; } - if (wasChecking && !fChecking) - [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateQueue" object: self]; - - if ([self isError]) - { - [statusString setString: [NSLocalizedString(@"Error: ", "Torrent -> status string") stringByAppendingString: - [self errorMessage]]]; - } - + //check for error BOOL wasError = fError; - if ((fError = fStat->cannotConnect)) - { - if (!wasError && [self isActive]) - [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateQueue" object: self]; - } + if ((fError = [self isError])) + [statusString setString: [NSLocalizedString(@"Error: ", "Torrent -> status string") + stringByAppendingString: [self errorMessage]]]; + + //check if stalled + BOOL wasStalled = fStalled; + fStalled = [fDefaults boolForKey: @"CheckStalled"] + && [fDefaults integerForKey: @"StalledSeconds"] < [self stalledSeconds]; + if (!fError && fStalled) + [statusString setString: [NSLocalizedString(@"Stalled, ", "Torrent -> status string") + stringByAppendingString: statusString]]; + + //update queue for checking (from downloading to seeding), stalled, or error + if ((wasChecking && !fChecking) || (!wasStalled && fStalled) || (!wasError && fError && [self isActive])) + [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateQueue" object: self]; if ([self isActive] && fStat->status != TR_STATUS_CHECK ) { @@ -1355,6 +1357,24 @@ static uint32_t kRed = BE(0xFF6450FF), //255, 100, 80 return date > 0 ? [NSDate dateWithTimeIntervalSince1970: date] : fDateActivity; } +- (int) stalledSeconds +{ + if (![self isActive]) + return -1; + + NSDate * started = [NSDate dateWithTimeIntervalSince1970: fStat->startDate / 1000], + * activity = [self dateActivity]; + if (!activity || [started compare: activity] == NSOrderedDescending) + return -1.0 * [started timeIntervalSinceNow]; + else + return -1.0 * [activity timeIntervalSinceNow]; +} + +- (BOOL) isStalled +{ + return fStalled; +} + - (NSNumber *) stateSortKey { if (![self isActive])