I am new to Objective C and I am trying to make an application that will play a midi file when a button is pressed. I also want it not respond to additional button presses while the file is playing. I made a custom button class and put this code (from a tutorial) into the .m file:
- (IBAction)MIDItest:(id)sender
{
MusicSequence s;
NewMusicSequence(&s);
NSString *midiFilePath = [[NSBundle mainBundle]
pathForResource:@"eDom"
ofType:@"mid"];
NSURL *midiFileURL = [NSURL fileURLWithPath:midiFilePath];
MusicSequenceFileLoad(s, (__bridge CFURLRef)(midiFileURL), 0, 0);
MusicPlayer p;
NewMusicPlayer(&p);
MusicPlayerSetSequence(p, s);
MusicPlayerPreroll(p);
MusicPlayerStart(p);
MusicTrack t;
MusicTimeStamp len;
UInt32 sz = sizeof(MusicTimeStamp);
MusicSequenceGetIndTrack(s, 1, &t);
MusicTrackGetProperty(t, kSequenceTrackProperty_TrackLength, &len, &sz);
while (1) {
usleep (3 *1000 *1000);
MusicTimeStamp now = 0;
MusicPlayerGetTime(p, &now);
if (now >= len)
break;
}
MusicPlayerStop(p);
DisposeMusicSequence(s);
DisposeMusicPlayer(p);
}
However, when I press the button, nothing happens. I did set the button to be the custom class, so I think the problem is in the midi player code. Can anyone tell me what I have done wrong and how I can fix this?
There are a number of problems with that code. Using
while (1)
withusleep
as a control structure is a very bad idea. It locks up the user interface for the duration of the midi file. My guess is that that is just some poor tutorial code meant to show how to use the MusicPlayer API but inadvertently showing a very bad way to implement it.The right way to do this is to declare the MusicPlayer as a @property so that it persists for the life of the app (or however long it is needed) and set and remove MusicSequences as needed.
The specific problem with your code is that MusicTracks are zero based (header definition below) and you are asking for track 1, which I am guessing does not exist. An error is returned but you are not checking for it. All MusicPlayer functions return a result code and you should always check for them (or suffer blindly in debug hell ... ;-)
You check for error like this:
The
printErrorMessage
function (included below) is just a convenience to be able to log strings and result codes easily.As to why your code isn't working: if the track doesn't exist, its length is going to be zero and so your sleep code is not going to work and the method will exit immediately. You can check this with:
The MusicPlayer API is very powerful and fun to work with but always check for error result codes (listed here) since will fail silently and you won't have a clue without them.