Monitoring using Custom Messages
Using expressions, it is possible to customise the values sent by OSC Event Transport output messages. This page covers how to customise the output messages from the OSC Event Transport.
Adding a message
After the user clicks on the + button at the bottom of the Output Messages list, a new row is added. The row starts off with the entry for the OSC address selected and editable. All message rows must have a unique, non-blank OSC address to be valid.
Once the address is entered, a note in the Description column may be useful to keep track of what is being added. Alternatively, the user might want to dive straight in and press the Edit… button, to start entering the expression to create the desired value.
Invalid expressions cause the Edit… button to turn red. The error is described in mouse hover text on the button.
Variables
The OSC Event Transport has a number of local system variables which can be used to provide access to the transport which the OSC Event Transport is attached to.
Resource variables
Access to the current context of the transport is accomplished by accessing the Resources which make up the Transport. These variables can have fields referenced from them. Not all fields are documented, because this is directly accessing Designer internal objects, which are subject to change.
transport
- The Transport Manager which the Event Transport is monitoring.track
- The current track within the transport.
Track time variables
Finding the current section or time within the track is simplified by providing these variables.
currentBeat
- The current beat on the track (for use with the Quantiser.)currentTime
- The current time on the track.currentSection
- The current section number on the track (first section is numbered0
.)currentSectionName
- The name (note) at the start of the current section.nextSectionName
- The name (note) at the start of the next section.currentSectionTag
- The tag (e.g. TC time) at the current section.nextSectionTag
- The tag at the next section.
Feature variables
Features are either notes or tags. It is convenient to reference relative to a note or tag, whichever is closest. These variables deal with a complex set of lookups by storing that information in these variables.
currentFeatureTime
- The time of the most recent feature before the current track position. Evaluates to0.0
if no feature exists.currentFeatureName
- The name of the most recent feature before the current track position. Evaluates to"Start"
if not feature exists.nextFeatureTime
- The time of the next feature after the current track position. Evaluates totrack.lengthInSec
if no feature exists.nextFeatureName
- The name of the next feature after the current track position. Evaluates to"End"
if not feature exists.
See constructing feature variables for information on how these are constructed and for tips on how to get related information.
Function variable
Timecode
is a special function-style variable which converts a time in seconds (e.g. currentTime) into a string in timecode format “HH:MM:SS
.FF”.
Default output messages
It can be instructive to understand the meaning of the expressions which drive the default output messages.
Heartbeat
1 - (uptime % 1)
This counts down from 1 to 0 every second. uptime
is a global variable
Track name
track.description
This is the description of the current track - all Resources have a description
property which can be used to check which Resource an expression is accessing.
Track ID
track.trigger_note
This property is documented under Track ID. It is a discoverable via the alt-dragging technique.
Track position
Timecode(currentTime)
Converts the current time into the track into a Timecode string representation using the Timecode
function. Note the result is not a Timecode
object, but a string which looks like timecode. This may change in future versions of the software.
Timecode
transport.beatToTimecode(currentBeat).__str__()
The TransportManager’s beatToTimecode
function matches the current track time against TC tags and provides that time as the global timecode time.
The .__str__()
is an unfortunate issue with the current expression system being unable to seamlessly convert Timecode objects to string.
Current section name
track.noteAtBeat(track.sectionToBeat(currentSection))
The Track’s noteAtBeat
function is used to look up notes if at an exact beat. For example, track.noteAtBeat(currentBeat)
would only return a note if the play head was exactly on a note.
This expression attempts to provide more useful information by referencing back to the most recent section. Tracks’ sectionToBeat
converts the current section number into its corresponding beat, to enable the lookup of any note which may be at the beat at the beginning of that section.
Next section name
track.noteAtBeat(track.sectionToBeat(currentSection + 1))
This function is very similar to the above Current section name. However, instead of looking up the current section, it instead looks up currentSection + 1
, i.e. the next section.
Section hint
format::{currentFeatureName:s} +{Timecode(currentTime - currentFeatureTime):s} {nextFeatureName:s} -{Timecode(nextFeatureTime - currentTime):s}
This expression attempts to provide a readable overview of the position in the current track, relative to known feature points (either notes or tags).
Volume
transport.volume
The current volume of the Transport is discoverable via the alt-dragging technique.
Brightness
transport.brightness
The current master brightness of the Transport is discoverable via the alt-dragging technique.
BPM
track.bpmAt(currentBeat)
When working with quantised tracks, the BPM can vary between sections. The Track’s bpmAt
function converts from a beat to a BPM to allow for inspection.
Play mode
transport.player.playMode.__str__()
The TransportManager has a TrackPlayer
member called player
. This stores a number of relevant values to the current state of the play head. The playMode
member provides the current transport state as an enum value. The __str__()
call converts that to a string for display to the user.
Example expressions
Description | Expression |
---|---|
Name of the track | track.description |
Name of the transport | transport.description |
Transport engaged status | transport.engaged |
First beat of current section | track.sectionToBeat(currentSection) |
Convert current track time in beats to seconds | track.beatToTime(currentBeat) |
Convert current track time in seconds to beats | track.timeToBeat(currentTime) |
Time remaining until next track feature | Timecode(nextFeatureTime - currentTime) |
Time elapsed since last track feature | Timecode(currentTime - currentFeatureTime) |
Current section time elapsed | Timecode(currentBeat - track.sectionToBeat(currentSection)) |
Current section time remaining | Timecode(track.sectionToBeat(currentSection + 1)-(currentBeat)) |
Current incoming timecode | transport.timecode.current.__str__() |
Current Transport Manager monitoring status (e.g. timecode) | transport.monitorString |
Current Transport Manager status (e.g. “No matching timecode”) | transport.statusString |
Constructing feature variables
The variables currentFeature*
and nextFeature*
are constructed by the OSC event transport for the users convenience. A feature is composed from the notes and tags on the current track.
This section adds information on how they are constructed to enable access to lower level information for custom reporting. Note the functions used here are not guaranteed to remain, though they are very stable internal APIs.
First, the beat of the note or tag is found:
Action | Function | Not found value |
---|---|---|
Next note | track.findBeatOfNextNote(currentBeat) | 1.7976931348623157E+308 |
Previous note | track.findBeatOfLastNote(currentBeat) | -1.0 |
Next tag | track.findBeatOfNextTag(currentBeat) | 1.7976931348623157E+308 |
Previous tag | track.findBeatOfLastTag(currentBeat) | -1.0 |
Note that the results are in beats, not in time. track.beatToTime()
allows the beat to be converted to a track time, and Timecode()
allows the time to be shown as timecode.
The name of a note or tag can be found with track.noteAtBeat()
or track.tagAtBeat()
. If an invalid beat or a beat with no note or tag is passed, the function returns an empty string.
With the above information, we can therefore emulate the construction of the various feature variables (beware these are very long, hence why the convenience variables exist.) The variables currentFeatureBeat
and nextFeatureBeat
do not exist normally, but are used to simplify the construction of the others for the purposes of documentation.
Feature variable | Expression |
---|---|
currentFeatureBeat | max(track.findBeatOfLastNote(currentBeat), track.findBeatOfLastTag(currentBeat)) |
nextFeatureBeat | min(track.findBeatOfNextNote(currentBeat), track.findBeatOfNextTag(currentBeat)) |
currentFeatureTime | track.beatToTime(currentFeatureBeat) |
nextFeatureTime | track.beatToTime(nextFeatureBeat) |
currentFeatureName | format::{track.noteAtBeat(currentFeatureBeat)}|{track.tagAtBeat(currentFeatureBeat)} |
nextFeatureName | format::{track.noteAtBeat(nextFeatureBeat)}|{track.tagAtBeat(nextFeatureBeat)} |