Skip to content

Commit

Permalink
Playback: Start playback and seek in the background
Browse files Browse the repository at this point in the history
Perform playback start and seeking operations in the background, instead
of on the main thread, which should help prevent them from stalling the
user interface.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
  • Loading branch information
kode54 committed Sep 3, 2023
1 parent d4196a5 commit f54dd1c
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
41 changes: 35 additions & 6 deletions Application/PlaybackController.m
Expand Up @@ -23,6 +23,35 @@

extern BOOL kAppControllerShuttingDown;

@implementation NSObject (NxAdditions)

-(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ...
{
NSMethodSignature *signature = [self methodSignatureForSelector:selector];

// Setup the invocation
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = selector;

// Associate the arguments
va_list objects;
va_start(objects, object);
unsigned int objectCounter = 2;
for (id obj = object; obj != nil; obj = va_arg(objects, id))
{
[invocation setArgument:&obj atIndex:objectCounter++];
}
va_end(objects);

// Make sure to invoke on a background queue
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithInvocation:invocation];
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperation:operation];
}

@end

@implementation PlaybackController

#define DEFAULT_SEEK 5
Expand Down Expand Up @@ -241,7 +270,7 @@ - (void)playEntry:(PlaylistEntry *)pe startPaused:(BOOL)paused andSeekTo:(id)off

double seekTime = pe.seekable ? [offset doubleValue] : 0.0;

[audioPlayer play:pe.url withUserInfo:pe withRGInfo:makeRGInfo(pe) startPaused:paused andSeekTo:seekTime];
[audioPlayer performSelectorInBackground:@selector(playBG:withUserInfo:withRGInfo:startPaused:andSeekTo:) withObjects:pe.url, pe, makeRGInfo(pe), @(paused), @(seekTime), nil];
}

- (IBAction)next:(id)sender {
Expand Down Expand Up @@ -272,7 +301,7 @@ - (void)updatePosition:(id)sender {
- (IBAction)seek:(id)sender {
double time = [sender doubleValue];

[audioPlayer seekToTime:time];
[audioPlayer performSelectorInBackground:@selector(seekToTimeBG:) withObject:@(time)];

lastPosition = -10;

Expand All @@ -289,7 +318,7 @@ - (IBAction)seek:(id)sender toTime:(NSTimeInterval)position {

lastPosition = -10;

[audioPlayer seekToTime:time];
[audioPlayer performSelectorInBackground:@selector(seekToTimeBG:) withObject:@(time)];

[self setPosition:time];

Expand Down Expand Up @@ -321,7 +350,7 @@ - (void)seekForward:(double)amount {
[self next:self];
} else {
lastPosition = -10;
[audioPlayer seekToTime:seekTo];
[audioPlayer performSelectorInBackground:@selector(seekToTimeBG:) withObject:@(seekTo)];
[self setPosition:seekTo];
}
}
Expand All @@ -338,7 +367,7 @@ - (void)seekBackward:(double)amount {

lastPosition = -10;

[audioPlayer seekToTime:seekTo];
[audioPlayer performSelectorInBackground:@selector(seekToTimeBG:) withObject:@(seekTo)];
[self setPosition:seekTo];
}

Expand Down Expand Up @@ -704,7 +733,7 @@ - (void)audioPlayer:(AudioPlayer *)player restartPlaybackAtCurrentPosition:(id)u
PlaylistEntry *pe = [playlistController currentEntry];
BOOL paused = playbackStatus == CogStatusPaused;
[[FIRCrashlytics crashlytics] logWithFormat:@"Restarting playback of track: %@", pe.url];
[player play:pe.url withUserInfo:pe withRGInfo:makeRGInfo(pe) startPaused:paused andSeekTo:pe.seekable ? pe.currentPosition : 0.0];
[player performSelectorInBackground:@selector(playBG:withUserInfo:withRGInfo:startPaused:andSeekTo:) withObjects:pe.url, pe, makeRGInfo(pe), @(paused), @(pe.seekable ? pe.currentPosition : 0.0), nil];
}

- (void)audioPlayer:(AudioPlayer *)player pushInfo:(NSDictionary *)info toTrack:(id)userInfo {
Expand Down
2 changes: 2 additions & 0 deletions Audio/AudioPlayer.h
Expand Up @@ -61,12 +61,14 @@
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi;
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused;
- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused andSeekTo:(double)time;
- (void)playBG:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(NSNumber *)paused andSeekTo:(NSNumber *)time;

- (void)stop;
- (void)pause;
- (void)resume;

- (void)seekToTime:(double)time;
- (void)seekToTimeBG:(NSNumber *)time;
- (void)setVolume:(double)v;
- (double)volume;
- (double)volumeUp:(double)amount;
Expand Down
8 changes: 8 additions & 0 deletions Audio/AudioPlayer.m
Expand Up @@ -56,6 +56,10 @@ - (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)r
[self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:paused andSeekTo:0.0];
}

- (void)playBG:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(NSNumber *)paused andSeekTo:(NSNumber *)time {
[self play:url withUserInfo:userInfo withRGInfo:rgi startPaused:[paused boolValue] andSeekTo:[time doubleValue]];
}

- (void)play:(NSURL *)url withUserInfo:(id)userInfo withRGInfo:(NSDictionary *)rgi startPaused:(BOOL)paused andSeekTo:(double)time {
ALog(@"Opening file for playback: %@ at seek offset %f%@", url, time, (paused) ? @", starting paused" : @"");

Expand Down Expand Up @@ -165,6 +169,10 @@ - (void)resume {
[self setPlaybackStatus:CogStatusPlaying waitUntilDone:YES];
}

- (void)seekToTimeBG:(NSNumber *)time {
[self seekToTime:[time doubleValue]];
}

- (void)seekToTime:(double)time {
if(endOfInputReached) {
// This is a dirty hack in case the playback has finished with the track
Expand Down

0 comments on commit f54dd1c

Please sign in to comment.