Contents page

Rules for Tools/Transport Handlers


Writing a Transport Handler

You can install your own routine in the Transport Handler chain. Every time the user clicks on Start, Stop, Play, Record, Rewind, or Fast Forward, your routine is called by the Transport Handler. In addition, as the sequence plays, your routine is called on a regular basis, should you need to dump blocks of notes into the PipeLine (this is how the Sequencer works.)

Your routine is passed three parameters: the command, the starting time for the command, and the ending time for the command. Depending on the command, the two time parameters may or may not be used. Here are the commands (see Transport Commands):

`TC_TICK'
     This is essentially a very low resolution clock tick, called about
     every beat.  If your routine puts Events into the PipeLine (which
     queues them to be released on time,) it should do so here, sending
     all Events between the start and end times. See Transport Commands.

`TC_START'
     Start playback from the start of the song.  Queue all events from
     0 to the end time.

`TC_STOP'
     Stop playback.

`TC_PLAY'
     Start playback from the current song position.  Queue all events
     between the start and end times.

`TC_POSITION'
     Move the song position to starting time.

`TC_RECORDON'
     Start recording.

`TC_RECORDOFF'
     Stop recording.

   Here's a skeletal transport routine:

void transportcode(command,start,end) 
long command,start,end; 
{
    switch(command) {
        case TC_START :         /* Start playback.  Queue from 0 to end. */
            break;
        case TC_PLAY :          /* Continue playback from start to end. */
            break;
        case TC_STOP :          /* Stop playback. */
            break;
        case TC_POSITION :      /* Move to new song start position. */
            break;
        case TC_RECORDON :      /* Punch In. */
            break;
        case TC_RECORDOFF :     /* Punch Out. */
            break;
        case TC_TICK :          /* Play from start to end marker. */
            break;
        }
}

To install the routine, call the Bars&Pipes library routine `installtransport()'
(see installtransport()) to insert your transport server into the chain.

     (*functions->installtransport)(transportcode);

Later, to remove your handler, call `removetransport()' (see removetransport()):

     (*functions->removetransport)(transportcode);

Usually, the best place to install a transport handler routine is when your Tool or
Accessory is loaded, from the `inittoolmaster()' routine.  Then, remove the routine
from within your `removetool()' routine.  Here's an abbreviated piece of code that does
both:

/*    This is called when Bars&Pipes unloads the Tool.  */ 
void removetool() {
    (*functions->removetransport)(transportcode); 
}

struct ToolMaster master;

struct ToolMaster * inittoolmaster() {
    (*functions->installtransport)(transportcode);
    master.removetool = removetool; 
}

The source code for the Accompany B Tool has within it a good example of a transport
handler.