MIDIGetEvent

Searches (within the search tracks) for the next event matching the specified event type and/or channel.

Synopsis

result = MIDIGetEvent(types, channels, time)

Args

types are the event types to match. They can be specified either by name (ie, "On Note", "Off Note", "(Off) Note", etc), or number (ie, 144, 128, etc). Several choices can be specified with a '|' between them. For example, "On Note|Off Note|(Off) Note". (For ID numbers, they can alternately be separated by blank space). If the first character of types is \, then these are the event types to ignore. All other types are then assumed to match. Therefore, a string of only '\' sets all event types as matched. If types is omitted, then no matching by event type is done. (ie, The next matching event can be of any type).

channels are the MIDI channels to match (ie, 1 to 16). Several choices can be specified with a '|' or blank space between them. For example, " 10 1 2". If the first character of channels is \, then these are the MIDI channels to ignore. All other channels are then assumed to match. Therefore, a string of only '\' sets all channels as matched. If channels is omitted, then no matching by MIDI channel is done. (ie, The next matching event can be on any MIDI channel).

If both types and channels are omitted, then MIDIGetEvent() returns the next event in the search track(s).

time is the start time at which to start the search, expressed in Measures:Beats:Clocks. For example, 1:1:0 starts the search at the downbeat of the first measure (ie, the start of playback). If omitted, the start time defaults to the time of the previous event returned by MIDIGetEvent(). (MIDITrack() automatically resets the start time to 1:1:0).

Returns

If an event matching the specified types and channels is found, then an empty string is returned. The following compound variables are also set to the matching event's values:

Variable name Meaning
MIDIEvent.!Measure
The measure where the event occurs, where 1 is the first measure. Not applicable for SMPTE resolution.
MIDIEvent.!Beat
The beat where the event occurs, where 1 is the first beat. Not applicable for SMPTE resolution.
MIDIEvent.!Clock
The PPQN clock where the event occurs, where 0 is right on the downbeat. For SMPTE timing, this will simply be the number of subframes since the start of the file.
MIDIEvent.!Type
The event's ID number. Use MIDIEventProp()'s TYPE option to convert to a name.
MIDIEvent.!Channel
The MIDI channel to which the event is assigned. Not applicable to events that have no channel.
MIDIEvent.!Data1
The event's data. The meaning of this will depend upon the event's Type. Some Types will have more data stored in further REXX variables named MIDIEvent.!Data2, MIDIEvent.!Data3, etc.

MIDI Rexx will also note which track the matching event is upon, and this becomes the currently selected track. The matching event itself becomes the currently selected event. Other MIDI Rexx functions, such as MIDISysex() and MIDISetEvent() reference these two items.

If no such matching event is found, or an error, then an error message is returned.

Notes

If you call MIDIGetEvent() before calling MIDIOpenFile() to load/create a file in RAM, then a REXX SYNTAX condition is raised. CONDITION('E') returns error number 40.1 and CONDITION('D') returns the message DLL function "MIDIGetEvent" reported MIDI file not yet loaded!.

If there is a problem allocating memory to set any variables, then a SYNTAX condition is raised. CONDITION('E') returns error number 5 and CONDITION('D') returns the message System resources exhausted.

If you pass a value for types or channels which is not one of the allowable ones, then a REXX SYNTAX condition is raised. CONDITION('E') returns error number 40.28 and CONDITION('D') returns the message MIDIGetEvent argument <x>, option must start with one of "<options>"; found "<badchoice>" where <x> is 1 for types or 2 for channels, <options> are the allowable choices, and <badchoice> is what you erroneously passed.

If you trap ERROR condition, then any MIDIGetEvent() error (other than the above, and also the "No currently selected event!" error) raises the ERROR condition. CONDITION('E') returns the error number and CONDITION('D') returns the error message (as normally returned by MIDIGetEvent()). Possible error numbers/messages include:

Number Message Causes
51 Failure fetching <name>: Value was not set! You forgot to set a required variable before calling MIDIGetEvent().
54 Failure fetching <name>: Value is too big! Perhaps too large an event for REXX to handle.

If you do not trap ERROR condition, then any one of above error messages may be returned by MIDIGetEvent().

If specifying an event name (instead of number) for types, only the first 4 letters need be supplied (ie, "On N" is the same as "On Note").

Examples

/* Print out the note numbers of all On Notes in track #1 */
tracknum = MIDITrack(1)
IF tracknum \== 0 THEN DO
   DO WHILE MIDIGetEvent('On Note') == ""
      SAY MIDIEvent.!Data1
   END
END

/* Find the next Program event on channel 10
 * in the currently selected track
 */
err = MIDIGetEvent('Program', '10')
IF err \== "" THEN SAY err

 /* Display the next On Note, Off Note, or (Off)
 * Note event in the currently selected track
 */
err = MIDIGetEvent('On N|Off |(Off')
IF err == "" THEN DO
   SAY '"' || MIDIEventProp() || '" found.'
   SAY "Note Number =" MIDIEvent.!Data1
   IF MIDIEventProp() \== "(Off) Note" THEN SAY "Velocity =" MIDIEvent.!Data2
END
ELSE SAY err

/* Find the next event on any channel except
 * 10 and 1, in the currently selected track
 */
err = MIDIGetEvent(, '\ 10 | 1')
IF err == "" THEN DO
   SAY 'ID number =' MIDIEvent.!Type 'Name =' MIDIEventProp()
END
ELSE SAY err