diff --git a/Source/MIKMIDISequence.h b/Source/MIKMIDISequence.h index 0b7c1a7d..53b66ceb 100644 --- a/Source/MIKMIDISequence.h +++ b/Source/MIKMIDISequence.h @@ -53,6 +53,20 @@ NS_INLINE MIKMIDITimeSignature MIKMIDITimeSignatureMake(UInt8 numerator, UInt8 d */ + (instancetype)sequenceWithFileAtURL:(NSURL *)fileURL error:(NSError **)error; +/** + * Creates and initilazes a new instance of MIKMIDISequence from a MIDI file. + * + * @param fileURL The URL of the MIDI file. + * @param convertMIDIChannelsToTracks Determines whether or not the track structure should be altered. When YES, the resulting sequence will + * contain a tempo track, 1 track for each MIDI Channel that is found in the MIDI file, and 1 track for SysEx or MetaEvents as the last track in + * the sequence. When NO, the track structure of the original MIDI file is left unaltered. + * @param error If an error occurs, upon returns contains an NSError object that describes the problem. If you are not interested in possible errors, + * you may pass in NULL. + * + * @return A new instance of MIKMIDISequence containing the loaded file's MIDI sequence, or nil if an error occured. + */ ++ (instancetype)sequenceWithFileAtURL:(NSURL *)fileURL convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error; + /** * Initilazes a new instance of MIKMIDISequence from a MIDI file. * @@ -64,28 +78,70 @@ NS_INLINE MIKMIDITimeSignature MIKMIDITimeSignatureMake(UInt8 numerator, UInt8 d */ - (instancetype)initWithFileAtURL:(NSURL *)fileURL error:(NSError **)error; +/** + * Initilazes a new instance of MIKMIDISequence from a MIDI file. + * + * @param fileURL The URL of the MIDI file. + * @param convertMIDIChannelsToTracks Determines whether or not the track structure should be altered. When YES, the resulting sequence will + * contain a tempo track, 1 track for each MIDI Channel that is found in the MIDI file, and 1 track for SysEx or MetaEvents as the last track in + * the sequence. When NO, the track structure of the original MIDI file is left unaltered. + * @param error If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, + * you may pass in NULL. + * + * @return A new instance of MIKMIDISequence containing the loaded file's MIDI sequence, or nil if an error occured. + */ +- (instancetype)initWithFileAtURL:(NSURL *)fileURL convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error; + /** * Creates and initializes a new instance of MIKMIDISequence from MIDI data. * * @param data An NSData instance containing the data for the MIDI sequence/file. - * @param error If an + * @param error If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, * * @return If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, * you may pass in NULL. */ + (instancetype)sequenceWithData:(NSData *)data error:(NSError **)error; +/** + * Creates and initializes a new instance of MIKMIDISequence from MIDI data. + * + * @param data An NSData instance containing the data for the MIDI sequence/file. + * @param convertMIDIChannelsToTracks Determines whether or not the track structure should be altered. When YES, the resulting sequence will + * contain a tempo track, 1 track for each MIDI Channel that is found in the MIDI file, and 1 track for SysEx or MetaEvents as the last track in + * the sequence. When NO, the track structure of the original MIDI file is left unaltered. + * @param error If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, + * + * @return If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, + * you may pass in NULL. + */ ++ (instancetype)sequenceWithData:(NSData *)data convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error; + /** * Initializes a new instance of MIKMIDISequence from MIDI data. * * @param data An NSData instance containing the data for the MIDI sequence/file. - * @param error If an + * @param error If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, * * @return If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, * you may pass in NULL. */ - (instancetype)initWithData:(NSData *)data error:(NSError **)error; +/** + * Initializes a new instance of MIKMIDISequence from MIDI data. + * + * @param data An NSData instance containing the data for the MIDI sequence/file. + * @param convertMIDIChannelsToTracks Determines whether or not the track structure should be altered. When YES, the resulting sequence will + * contain a tempo track, 1 track for each MIDI Channel that is found in the MIDI file, and 1 track for SysEx or MetaEvents as the last track in + * the sequence. When NO, the track structure of the original MIDI file is left unaltered. + * @param error If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, + * + * @return If an error occurs, upon return contains an NSError object that describes the problem. If you are not interested in possible errors, + * you may pass in NULL. + */ +- (instancetype)initWithData:(NSData *)data convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error; + /** * Writes the MIDI sequence in Standard MIDI File format to a file at the specified URL. * diff --git a/Source/MIKMIDISequence.m b/Source/MIKMIDISequence.m index 8f91ec5f..f43e59d1 100644 --- a/Source/MIKMIDISequence.m +++ b/Source/MIKMIDISequence.m @@ -52,21 +52,41 @@ - (instancetype)init + (instancetype)sequenceWithFileAtURL:(NSURL *)fileURL error:(NSError **)error; { - return [[self alloc] initWithFileAtURL:fileURL error:error]; + return [[self alloc] initWithFileAtURL:fileURL convertMIDIChannelsToTracks:NO error:error]; +} + ++ (instancetype)sequenceWithFileAtURL:(NSURL *)fileURL convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error +{ + return [[self alloc] initWithFileAtURL:fileURL convertMIDIChannelsToTracks:convertMIDIChannelsToTracks error:error]; } - (instancetype)initWithFileAtURL:(NSURL *)fileURL error:(NSError **)error; { - NSData *data = [NSData dataWithContentsOfURL:fileURL options:0 error:error]; - return [self initWithData:data error:error]; + return [self initWithFileAtURL:fileURL convertMIDIChannelsToTracks:NO error:error]; +} + +- (instancetype)initWithFileAtURL:(NSURL *)fileURL convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error +{ + NSData *data = [NSData dataWithContentsOfURL:fileURL options:0 error:error]; + return [self initWithData:data convertMIDIChannelsToTracks:convertMIDIChannelsToTracks error:error]; } + (instancetype)sequenceWithData:(NSData *)data error:(NSError **)error { - return [[self alloc] initWithData:data error:error]; + return [[self alloc] initWithData:data convertMIDIChannelsToTracks:NO error:error]; +} + ++ (instancetype)sequenceWithData:(NSData *)data convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error +{ + return [[self alloc] initWithData:data convertMIDIChannelsToTracks:convertMIDIChannelsToTracks error:error]; } - (instancetype)initWithData:(NSData *)data error:(NSError **)error +{ + return [self initWithData:data convertMIDIChannelsToTracks:NO error:error]; +} + +- (instancetype)initWithData:(NSData *)data convertMIDIChannelsToTracks:(BOOL)convertMIDIChannelsToTracks error:(NSError **)error { error = error ? error : &(NSError *__autoreleasing){ nil }; @@ -78,7 +98,8 @@ - (instancetype)initWithData:(NSData *)data error:(NSError **)error return nil; } - err = MusicSequenceFileLoadData(sequence, (__bridge CFDataRef)data, kMusicSequenceFile_MIDIType, 0); + MusicSequenceLoadFlags flags = convertMIDIChannelsToTracks ? kMusicSequenceLoadSMF_ChannelsToTracks : 0; + err = MusicSequenceFileLoadData(sequence, (__bridge CFDataRef)data, kMusicSequenceFile_MIDIType, flags); if (err) { NSLog(@"MusicSequenceFileLoadData() failed with error %d in %s.", err, __PRETTY_FUNCTION__); *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];