diff --git a/libtransmission/torrent.cc b/libtransmission/torrent.cc index 6a20157d6..22b7f53f5 100644 --- a/libtransmission/torrent.cc +++ b/libtransmission/torrent.cc @@ -1044,7 +1044,7 @@ void tr_torrent::init(tr_ctor const& ctor) { on_metainfo_completed(); } - else if (start_when_stable_) + else if (start_when_stable_ || (is_new_torrent && !has_metainfo)) { auto const bypass_queue = !has_metainfo; // to fetch metainfo from peers start(bypass_queue, has_any_local_data); @@ -1344,6 +1344,7 @@ tr_stat tr_torrent::stats() const stats.desiredAvailable = tr_peerMgrGetDesiredAvailable(this); stats.ratio = tr_getRatio(stats.uploadedEver, this->size_when_done()); + stats.startWhenStable = this->start_when_stable_; auto seed_ratio_bytes_left = uint64_t{}; auto seed_ratio_bytes_goal = uint64_t{}; @@ -1541,6 +1542,14 @@ void tr_torrentStartNow(tr_torrent* tor) } } +void tr_torrentStabilize(tr_torrent* tor) +{ + if (tr_isTorrent(tor)) + { + tor->start(!tor->has_metainfo(), {}); + } +} + // --- void tr_torrentVerify(tr_torrent* tor) diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 2c3730cb6..8bd141829 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -588,6 +588,9 @@ void tr_sessionSetAntiBruteForceEnabled(tr_session* session, bool enabled); /** @brief Like `tr_torrentStart()`, but resumes right away regardless of the queues. */ void tr_torrentStartNow(tr_torrent* tor); +/** @brief Like `tr_torrentStart()`, but doesn't modify `start_when_stable`. */ +void tr_torrentStabilize(tr_torrent* tor); + /** @brief Return the queued torrent's position in the queue it's in. [0...n) */ size_t tr_torrentGetQueuePosition(tr_torrent const* tor); @@ -1543,6 +1546,9 @@ struct tr_stat /** If seeding, number of seconds left until the idle time limit is reached. */ time_t etaIdle; + /** Non-paused */ + bool startWhenStable; + /** What is this torrent doing right now? */ tr_torrent_activity activity; diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 1f84de1e3..c30ce75d8 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -759,25 +759,36 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool // theoretical max without doing a lot of work NSMutableArray* waitToStartTorrents = [NSMutableArray arrayWithCapacity:((history.count > 0 && !self.fPauseOnLaunch) ? history.count - 1 : 0)]; + NSMutableArray* waitToStabilizeTorrents = [NSMutableArray + arrayWithCapacity:((history.count > 0 && !self.fPauseOnLaunch) ? history.count - 1 : 0)]; - Torrent* t = [[Torrent alloc] init]; for (NSDictionary* historyItem in history) { NSString* hash = historyItem[@"TorrentHash"]; if ([self.fTorrentHashes.allKeys containsObject:hash]) { Torrent* torrent = self.fTorrentHashes[hash]; - [t setResumeStatusForTorrent:torrent withHistory:historyItem forcePause:self.fPauseOnLaunch]; + [torrent setResumeStatusWithHistory:historyItem forcePause:self.fPauseOnLaunch]; - NSNumber* waitToStart; - if (!self.fPauseOnLaunch && (waitToStart = historyItem[@"WaitToStart"]) && waitToStart.boolValue) + if (!self.fPauseOnLaunch && [historyItem[@"WaitToStart"] boolValue]) { - [waitToStartTorrents addObject:torrent]; + if ([historyItem[@"StartWhenStable"] boolValue]) + { + [waitToStartTorrents addObject:torrent]; + } + else + { + [waitToStabilizeTorrents addObject:torrent]; + } } } } - //now that all are loaded, let's set those in the queue to waiting + // now that all are loaded, let's set those in the queue to waiting + for (Torrent* torrent in waitToStabilizeTorrents) + { + [torrent stabilize]; + } for (Torrent* torrent in waitToStartTorrents) { [torrent startTransfer]; diff --git a/macosx/Torrent.h b/macosx/Torrent.h index 777fbc183..20af014ca 100644 --- a/macosx/Torrent.h +++ b/macosx/Torrent.h @@ -21,7 +21,7 @@ extern NSString* const kTorrentDidChangeGroupNotification; lib:(tr_session*)lib; - (instancetype)initWithTorrentStruct:(tr_torrent*)torrentStruct location:(NSString*)location lib:(tr_session*)lib; - (instancetype)initWithMagnetAddress:(NSString*)address location:(NSString*)location lib:(tr_session*)lib; -- (void)setResumeStatusForTorrent:(Torrent*)torrent withHistory:(NSDictionary*)history forcePause:(BOOL)pause; +- (void)setResumeStatusWithHistory:(NSDictionary*)history forcePause:(BOOL)pause; @property(nonatomic, readonly) NSDictionary* history; @@ -37,6 +37,7 @@ extern NSString* const kTorrentDidChangeGroupNotification; - (void)update; +- (void)stabilize; - (void)startTransferIgnoringQueue:(BOOL)ignoreQueue; - (void)startTransferNoQueue; - (void)startTransfer; @@ -127,6 +128,8 @@ extern NSString* const kTorrentDidChangeGroupNotification; @property(nonatomic, readonly) CGFloat availableDesired; +/// True if non-paused. +@property(nonatomic, readonly) BOOL startWhenStable; /// True if non-paused. Running. @property(nonatomic, getter=isActive, readonly) BOOL active; /// True if downloading or uploading. diff --git a/macosx/Torrent.mm b/macosx/Torrent.mm index 81a0ce0c5..2ac20a236 100644 --- a/macosx/Torrent.mm +++ b/macosx/Torrent.mm @@ -147,16 +147,22 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error* error) return self; } -- (void)setResumeStatusForTorrent:(Torrent*)torrent withHistory:(NSDictionary*)history forcePause:(BOOL)pause +- (void)setResumeStatusWithHistory:(NSDictionary*)history forcePause:(BOOL)pause { - //restore GroupValue - torrent.groupValue = [history[@"GroupValue"] intValue]; + // restore GroupValue + self.groupValue = [history[@"GroupValue"] intValue]; - //start transfer - NSNumber* active; - if (!pause && (active = history[@"Active"]) && active.boolValue) + // start transfer + if (!pause && [history[@"Active"] boolValue]) { - [torrent startTransferNoQueue]; + if ([history[@"StartWhenStable"] boolValue]) + { + [self startTransferNoQueue]; + } + else + { + [self stabilize]; + } } NSNumber* ratioLimit; @@ -172,6 +178,7 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error* error) @"TorrentHash" : self.hashString, @"Active" : @(self.active), @"WaitToStart" : @(self.waitingToStart), + @"StartWhenStable" : @(self.startWhenStable), @"GroupValue" : @(self.groupValue), @"RemoveWhenFinishSeeding" : @(_removeWhenFinishSeeding) }; @@ -258,6 +265,12 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error* error) } } +- (void)stabilize +{ + tr_torrentStabilize(self.fHandle); + [self update]; +} + - (void)startTransferIgnoringQueue:(BOOL)ignoreQueue { if ([self alertForRemainingDiskSpace]) @@ -446,6 +459,7 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error* error) { return tr_torrentGetPeerLimit(self.fHandle); } + - (BOOL)waitingToStart { return self.fStat->activity == TR_STATUS_DOWNLOAD_WAIT || self.fStat->activity == TR_STATUS_SEED_WAIT; @@ -888,6 +902,11 @@ bool trashDataFile(char const* filename, void* /*user_data*/, tr_error* error) return (CGFloat)self.fStat->desiredAvailable / self.sizeLeft; } +- (BOOL)startWhenStable +{ + return self.fStat->startWhenStable; +} + - (BOOL)isActive { return self.fStat->activity != TR_STATUS_STOPPED && self.fStat->activity != TR_STATUS_DOWNLOAD_WAIT &&