From ced4d73fd65748a396f6ac5db4de1b97db51fda8 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sat, 22 Feb 2025 04:39:43 -0800 Subject: [PATCH] Crash Fix: Change background event to main thread Two playback event items were set to queue a playback start to a background thread, when playback should instead be queued on the main thread. Fix this in a simple way. This crash was easily reproducible by skipping through tracks rapidly. Signed-off-by: Christopher Snowhill --- Application/PlaybackController.m | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Application/PlaybackController.m b/Application/PlaybackController.m index 669a353b3..dcd2ae07c 100644 --- a/Application/PlaybackController.m +++ b/Application/PlaybackController.m @@ -25,6 +25,7 @@ extern BOOL kAppControllerShuttingDown; @implementation NSObject (NxAdditions) +#if 0 -(void)performSelectorInBackground:(SEL)selector withObjects:(id)object, ... { NSMethodSignature *signature = [self methodSignatureForSelector:selector]; @@ -49,6 +50,32 @@ extern BOOL kAppControllerShuttingDown; NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init]; [backgroundQueue addOperation:operation]; } +#endif + +-(void)performSelectorOnMainThread:(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); + + // Invoke on the main operation queue + NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithInvocation:invocation]; + NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; + [mainQueue addOperation:operation]; +} @end @@ -302,7 +329,7 @@ NSDictionary *makeRGInfo(PlaylistEntry *pe) { double seekTime = pe.seekable ? [offset doubleValue] : 0.0; - [audioPlayer performSelectorInBackground:@selector(playBG:withUserInfo:withRGInfo:startPaused:andSeekTo:) withObjects:pe.url, pe, makeRGInfo(pe), @(paused), @(seekTime), nil]; + [audioPlayer performSelectorOnMainThread:@selector(playBG:withUserInfo:withRGInfo:startPaused:andSeekTo:) withObjects:pe.url, pe, makeRGInfo(pe), @(paused), @(seekTime), nil]; } - (IBAction)next:(id)sender { @@ -855,7 +882,7 @@ NSDictionary *makeRGInfo(PlaylistEntry *pe) { PlaylistEntry *pe = [playlistController currentEntry]; BOOL paused = playbackStatus == CogStatusPaused; [[FIRCrashlytics crashlytics] logWithFormat:@"Restarting playback of track: %@", pe.url]; - [player performSelectorInBackground:@selector(playBG:withUserInfo:withRGInfo:startPaused:andSeekTo:) withObjects:pe.url, pe, makeRGInfo(pe), @(paused), @(pe.seekable ? pe.currentPosition : 0.0), nil]; + [player performSelectorOnMainThread:@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 {