[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>lastfm
parent
99fad892f0
commit
c489d7ca91
|
@ -452,11 +452,16 @@
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
if(signalStopped) {
|
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];
|
[self stop];
|
||||||
|
|
||||||
bufferChain = nil;
|
self->bufferChain = nil;
|
||||||
|
|
||||||
[self notifyPlaybackStopped:nil];
|
[self notifyPlaybackStopped:nil];
|
||||||
|
});
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
- (void)close;
|
- (void)close;
|
||||||
- (void)seek:(double)time;
|
- (void)seek:(double)time;
|
||||||
|
|
||||||
|
- (double)latency;
|
||||||
|
|
||||||
- (AudioChunk *)readChunk:(size_t)amount;
|
- (AudioChunk *)readChunk:(size_t)amount;
|
||||||
|
|
||||||
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig;
|
- (void)setFormat:(AudioStreamBasicDescription *)f channelConfig:(uint32_t)channelConfig;
|
||||||
|
|
|
@ -186,4 +186,8 @@
|
||||||
[controller restartPlaybackAtCurrentPosition];
|
[controller restartPlaybackAtCurrentPosition];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (double)latency {
|
||||||
|
return [output latency];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -50,7 +50,6 @@ using std::atomic_long;
|
||||||
BOOL started;
|
BOOL started;
|
||||||
BOOL paused;
|
BOOL paused;
|
||||||
BOOL restarted;
|
BOOL restarted;
|
||||||
BOOL stopFlush;
|
|
||||||
BOOL commandStop;
|
BOOL commandStop;
|
||||||
|
|
||||||
BOOL eqEnabled;
|
BOOL eqEnabled;
|
||||||
|
@ -122,6 +121,8 @@ using std::atomic_long;
|
||||||
- (void)resume;
|
- (void)resume;
|
||||||
- (void)stop;
|
- (void)stop;
|
||||||
|
|
||||||
|
- (double)latency;
|
||||||
|
|
||||||
- (void)setVolume:(double)v;
|
- (void)setVolume:(double)v;
|
||||||
|
|
||||||
- (void)setEqualizerEnabled:(BOOL)enabled;
|
- (void)setEqualizerEnabled:(BOOL)enabled;
|
||||||
|
|
|
@ -325,7 +325,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
running = YES;
|
running = YES;
|
||||||
started = NO;
|
started = NO;
|
||||||
secondsLatency = 1.0;
|
secondsLatency = 1.0;
|
||||||
stopFlush = NO;
|
|
||||||
|
|
||||||
while(!stopping) {
|
while(!stopping) {
|
||||||
if([outputController shouldReset]) {
|
if([outputController shouldReset]) {
|
||||||
|
@ -361,7 +360,6 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
|
|
||||||
CFRelease(bufferRef);
|
CFRelease(bufferRef);
|
||||||
} else {
|
} else {
|
||||||
stopFlush = YES;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1021,6 +1019,11 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
eqEnabled = enabled;
|
eqEnabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (double)latency {
|
||||||
|
if(secondsLatency > 0) return secondsLatency;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)start {
|
- (void)start {
|
||||||
[self threadEntry:nil];
|
[self threadEntry:nil];
|
||||||
}
|
}
|
||||||
|
@ -1032,13 +1035,9 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
||||||
|
|
||||||
- (void)doStop {
|
- (void)doStop {
|
||||||
if(stopInvoked) {
|
if(stopInvoked) {
|
||||||
stopFlush = NO;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@synchronized(self) {
|
@synchronized(self) {
|
||||||
if(commandStop) {
|
|
||||||
stopFlush = NO;
|
|
||||||
}
|
|
||||||
stopInvoked = YES;
|
stopInvoked = YES;
|
||||||
if(observersapplied) {
|
if(observersapplied) {
|
||||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice" context:kOutputAVFoundationContext];
|
[[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 || audioRenderer) {
|
||||||
if(renderSynchronizer) {
|
if(renderSynchronizer) {
|
||||||
if(stopFlush) {
|
if(!commandStop) {
|
||||||
int compareVal = 0;
|
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 {
|
do {
|
||||||
[currentPtsLock lock];
|
[currentPtsLock lock];
|
||||||
compareVal = CMTimeCompare(outputPts, currentPts);
|
compareVal = CMTimeCompare(outputPts, currentPts);
|
||||||
[currentPtsLock unlock];
|
[currentPtsLock unlock];
|
||||||
usleep(5000);
|
usleep(5000);
|
||||||
} while(stopFlush && compareVal > 0);
|
} while(!commandStop && compareVal > 0 && compareMax-- > 0);
|
||||||
}
|
}
|
||||||
[self removeSynchronizerBlock];
|
[self removeSynchronizerBlock];
|
||||||
[renderSynchronizer setRate:0];
|
[renderSynchronizer setRate:0];
|
||||||
|
|
Loading…
Reference in New Issue