[Audio Output] Play last track and stop correctly

Play last track up until it actually ends, and stop on command.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
swiftingly
Christopher Snowhill 2022-06-25 06:42:56 -07:00
parent d33475953e
commit 5f2335b796
5 changed files with 25 additions and 12 deletions

View File

@ -452,11 +452,16 @@
} while(0);
if(signalStopped) {
double latency = 0;
if(output) latency = [output latency];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, latency * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self stop];
bufferChain = nil;
self->bufferChain = nil;
[self notifyPlaybackStopped:nil];
});
return YES;
}

View File

@ -51,6 +51,8 @@
- (void)close;
- (void)seek:(double)time;
- (double)latency;
- (AudioChunk *)readChunk:(size_t)amount;
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig;

View File

@ -186,4 +186,8 @@
[controller restartPlaybackAtCurrentPosition];
}
- (double)latency {
return [output latency];
}
@end

View File

@ -50,7 +50,6 @@ using std::atomic_long;
BOOL started;
BOOL paused;
BOOL restarted;
BOOL stopFlush;
BOOL commandStop;
BOOL eqEnabled;
@ -122,6 +121,8 @@ using std::atomic_long;
- (void)resume;
- (void)stop;
- (double)latency;
- (void)setVolume:(double)v;
- (void)setEqualizerEnabled:(BOOL)enabled;

View File

@ -325,7 +325,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
running = YES;
started = NO;
secondsLatency = 1.0;
stopFlush = NO;
while(!stopping) {
if([outputController shouldReset]) {
@ -361,7 +360,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
CFRelease(bufferRef);
} else {
stopFlush = YES;
break;
}
}
@ -1021,6 +1019,11 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
eqEnabled = enabled;
}
- (double)latency {
if(secondsLatency > 0) return secondsLatency;
else return 0;
}
- (void)start {
[self threadEntry:nil];
}
@ -1032,13 +1035,9 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
- (void)doStop {
if(stopInvoked) {
stopFlush = NO;
return;
}
@synchronized(self) {
if(commandStop) {
stopFlush = NO;
}
stopInvoked = YES;
if(observersapplied) {
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice" context:kOutputAVFoundationContext];
@ -1074,14 +1073,16 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
}
if(renderSynchronizer || audioRenderer) {
if(renderSynchronizer) {
if(stopFlush) {
if(!commandStop) {
int compareVal = 0;
double secondsLatency = self->secondsLatency >= 0 ? self->secondsLatency : 0;
int compareMax = (((1000000 / 5000) * secondsLatency) + (10000 / 5000)); // latency plus 10ms, divide by sleep intervals
do {
[currentPtsLock lock];
compareVal = CMTimeCompare(outputPts, currentPts);
[currentPtsLock unlock];
usleep(5000);
} while(stopFlush && compareVal > 0);
} while(!commandStop && compareVal > 0 && compareMax-- > 0);
}
[self removeSynchronizerBlock];
[renderSynchronizer setRate:0];