MusicSequenceFileLoad Returns -1 on iOS10

I've encountered an error invoking the AudioToolbox / MusicPlayer API method "MusicSequenceFileLoad()" to load the contents of a MIDI file (from the given URL) into a music sequence on iOS10 devices.

Primary symptoms:


  • This code had previously been working without issue in production on iOS7, 8, and 9
  • Runs without issue on the iOS 10 Simulator but returns an OSStatus result of -1 on most iOS 10 devices


Code sample:


@property (readwrite, nonatomic) MusicPlayer midiMusicPlayer;
@property (readwrite, atomic) MusicSequence masterMidiMusicSequence;

- (void)initializeMusicPlayerAndMasterSequenceWithFile:(NSString *)midiFilename
{
    CheckError(NewMusicPlayer(&_midiMusicPlayer), "NewMusicPlayer: _midiMusicPlayer");
    CheckError(NewMusicSequence(&_masterMidiMusicSequence), "NewMusicSequence: _masterMidiMusicSequence");

    NSString *midiFilePath = [NSBundle pathForResource:midiFilename
                                                ofType:@"mid"
                               checkDocumentsDirectory:YES];
    NSURL *midiFileURL = [NSURL fileURLWithPath:midiFilePath];

    // Crash is encountered on the following line:
    CheckError(MusicSequenceFileLoad(self.masterMidiMusicSequence, (__bridge CFURLRef)midiFileURL, 0, 0), "MusicSequenceFileLoad");
}

Replies

I received some guidance from an Apple engineer via the Core Audio Mailing List and have successfully implemented the proposed work-around for this issue in iOS10.


By updating the "errno" value to 0 after a failed call, subsequent calls to 'MusicSequenceFileLoad' generate a successful response. Therefore, I've amended my code as follows:


OSStatus statusOfInitialAttempt = CheckError(MusicSequenceFileLoad(self.masterMidiMusicSequence, (__bridge CFURLRef)midiFileURL, 0, 0), "MusicSequenceFileLoad");
if (statusOfInitialAttempt == -1) {
    errno = 0;

    OSStatus statusOfSecondAttempt = CheckErrorAndReturnOnFailure(MusicSequenceFileLoad(self.masterMidiMusicSequence, (__bridge CFURLRef)midiFileURL, 0, 0), "MusicSequenceFileLoad");

    if (statusOfSecondAttempt == -1) {
        // Handle error case
    }
}


... where the CheckError() function simply checks the OSStatus return value against known OSStatus codes and is similar to this one on GitHub (originally created by Chris Adamson from his blog post / presentation "Core Audio Cranks It Up").

I understand that this issue is expected to be resolved in a future iOS update according to what was posted on the Core Audio Mailing List.

This issue has come up a couple of times, is a known problem now, and will be fixed in a future release.


The workaround should be as simple as adding


#import <sys/errno.h>


to your source, and add the line:


errno = 0;


just prior to your call to MusicSequenceFileLoad()


-DS