//
//  main.m
//  musictracktest
//
//  Created by Tod E. Kurt on Fri Jun 18 2004.
//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
//
#include <string.h>

#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>

/**
* The loop info struct (why not defined in the API, I wonder?)
 */
typedef struct {
  MusicTimeStamp loopLength;
  SInt32 numLoops;
} loopinfo;


#define trkcnt 4

int main(int argc, char *argv[])
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  
  NSLog(@"starting....\n");  
  OSStatus result = noErr;
  MIDINoteMessage note;
  
  MusicPlayer player;
  MusicSequence  sequence;
  MusicTrack tracks[trkcnt];
  
  require_noerr(result= NewMusicPlayer(&player), bailout);
  require_noerr(result= NewMusicSequence(&sequence), bailout);
  require_noerr(result= MusicPlayerSetSequence(player, sequence), bailout);
  
  // tracks[0] was going to be our conductor track, so leave it alone
  for( int i=1; i<trkcnt; i++ ) {
    require_noerr(result= MusicSequenceNewTrack(sequence, &tracks[i]), bailout);
    int channel = i-1;
    MIDIChannelMessage patchChange = { 0xc0 | channel, 33 + (i*1), 0, 0 };
    require_noerr(result= MusicTrackNewMIDIChannelEvent(tracks[i], 0.0, &patchChange), bailout);
    
    // Add octave of chromatic scale
    for (int j=0; j < 12; j++) {
      note.channel = i;
      note.velocity = (j==0) ? 120 : (80.00 - (j*5));
      note.duration = (j==0) ? 1.0 : 0.5;
      note.note = 50 + j + ((i*3)%36);
      require_noerr(result= MusicTrackNewMIDINoteEvent(tracks[i], j * (1.0-(i/5)), &note), bailout);
    }
    // Set the track to loop 3 bars forever
    loopinfo loopInfo = { 3*4.0f, 0 };
    require_noerr(result= MusicTrackSetProperty(tracks[i], kSequenceTrackProperty_LoopInfo, &loopInfo, sizeof(loopinfo)), bailout);
  }
  
  CAShow(sequence);
  
  MusicPlayerSetTime(player, 0.0);
  MusicPlayerPreroll(player);
  require_noerr(result= MusicPlayerStart(player), bailout);
  
  Boolean didActionA = FALSE;
  Boolean didActionB = FALSE;
  Boolean isPlaying;
  float sleeptime = (60/120.0)/4;  // wakekup every bar
  while (MusicPlayerIsPlaying(player, &isPlaying) == noErr && isPlaying) {
    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:sleeptime]];
    
    MusicTimeStamp currentTime;
    require_noerr(result= MusicPlayerGetTime(player, &currentTime), bailout);
    NSLog(@"currentTime=%f\n",currentTime);
    
    // demonstrate we can mute/turn-off tracks
    if( currentTime > 5.0 && didActionA==FALSE) {
      NSLog(@"muting tracks 1 & 2 at beat 5...\n");
      Boolean mute = TRUE;
      require_noerr(result= MusicTrackSetProperty(tracks[1], kSequenceTrackProperty_MuteStatus, &mute, sizeof(Boolean)), bailout);
      require_noerr(result= MusicTrackSetProperty(tracks[2], kSequenceTrackProperty_MuteStatus, &mute, sizeof(Boolean)), bailout);
      didActionA = TRUE;
    }
    
    // attempt to re-start a track at a particular time
    if( currentTime > 25.71 && didActionB==FALSE) {
      NSLog(@"starting track 2 at beat 26...\n");
      MusicTimeStamp offset = 26.0;
      Boolean mute = FALSE;
      require_noerr(result= MusicTrackSetProperty(tracks[2], kSequenceTrackProperty_OffsetTime, &offset, sizeof(MusicTimeStamp)), bailout);      
      require_noerr(result= MusicTrackSetProperty(tracks[2], kSequenceTrackProperty_MuteStatus, &mute, sizeof(Boolean)), bailout);
      didActionB = TRUE;
    }
    
  } // while
  
bailout:
    NSLog(@"result=%d",result);
  return result;
  
  [pool release];
  
}
