From b8580cf193f30e9af814365ed21be5dadd7abdf5 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 28 Feb 2025 17:56:10 -0800 Subject: [PATCH] Seeking: Restart output completely on track seek This required some minor workarounds to deal with the play time counting that works toward play count reporting. Signed-off-by: Christopher Snowhill --- Audio/AudioPlayer.m | 36 +++++++++++++++--------------------- Audio/Chain/OutputNode.h | 1 + Audio/Chain/OutputNode.m | 12 +++++++++--- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Audio/AudioPlayer.m b/Audio/AudioPlayer.m index 69bc5341e..38a6c0104 100644 --- a/Audio/AudioPlayer.m +++ b/Audio/AudioPlayer.m @@ -67,6 +67,10 @@ } - (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused andSeekTo:(double)time { + [self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:paused andSeekTo:time andResumeInterval:NO]; +} + +- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused andSeekTo:(double)time andResumeInterval:(BOOL)resumeInterval { ALog(@"Opening file for playback: %@ at seek offset %f%@", url, time, (paused) ? @", starting paused" : @""); [self waitUntilCallbacksExit]; @@ -77,7 +81,7 @@ if(!output) { output = [[OutputNode alloc] initWithController:self previous:nil]; } - [output setup]; + [output setupWithInterval:resumeInterval]; [output setVolume:volume]; @synchronized(chainQueue) { for(id anObject in chainQueue) { @@ -184,28 +188,18 @@ } - (void)seekToTime:(double)time { - if(endOfInputReached) { - // This is a dirty hack in case the playback has finished with the track - // that the user thinks they're seeking into - CogStatus status = (CogStatus)currentPlaybackStatus; - NSURL *url; - id userInfo; - NSDictionary *rgi; + CogStatus status = (CogStatus)currentPlaybackStatus; + NSURL *url; + id userInfo; + NSDictionary *rgi; - @synchronized(chainQueue) { - url = [bufferChain streamURL]; - userInfo = [bufferChain userInfo]; - rgi = [bufferChain rgInfo]; - } - - [self stop]; - - [self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:(status == CogStatusPaused) andSeekTo:time]; - } else { - // Still decoding the current file, safe to seek within it - [output seek:time]; - [bufferChain seek:time]; + @synchronized(chainQueue) { + url = [bufferChain streamURL]; + userInfo = [bufferChain userInfo]; + rgi = [bufferChain rgInfo]; } + + [self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:(status == CogStatusPaused) andSeekTo:time andResumeInterval:YES]; } - (void)setVolume:(double)v { diff --git a/Audio/Chain/OutputNode.h b/Audio/Chain/OutputNode.h index 2ea2f8aa2..f0450eea0 100644 --- a/Audio/Chain/OutputNode.h +++ b/Audio/Chain/OutputNode.h @@ -44,6 +44,7 @@ - (double)secondsBuffered; - (void)setup; +- (void)setupWithInterval:(BOOL)resumeInterval; - (void)process; - (void)close; - (void)seek:(double)time; diff --git a/Audio/Chain/OutputNode.m b/Audio/Chain/OutputNode.m index 0ede9847d..952292eb2 100644 --- a/Audio/Chain/OutputNode.m +++ b/Audio/Chain/OutputNode.m @@ -16,12 +16,18 @@ @implementation OutputNode - (void)setup { - amountPlayed = 0.0; - amountPlayedInterval = 0.0; + [self setupWithInterval:NO]; +} + +- (void)setupWithInterval:(BOOL)resumeInterval { + if(!resumeInterval) { + amountPlayed = 0.0; + amountPlayedInterval = 0.0; + intervalReported = NO; + } paused = YES; started = NO; - intervalReported = NO; output = [[OutputCoreAudio alloc] initWithController:self];