loopy
To complete the progress bar, I'm going to need to figure out how to do a few things in MSL.
How can I determine which loop is the "master loop", and how can I get its
loopPosition and loopLength? Would I use "loopFrame" and "loopFrames"?
If so, how to access those variables for the master loop when a
different loop is selected?
Yes. First some terminology...I use the word "frame" a lot. In scripts you can think of that as "sample number" or "location". Loops are like an array of samples, and the playback position is an index into that array.
Frame is less common term and means a collection of samples that are considered to be a single addressable unit. Mobius always deals with stereo audio streams so each frame contains two samples. If I ever get around to supporting surround, then a frame may contain 4, 5, or 6 samples. Script writers don't need to care about this. The frame is the smallest unit of audio data that can be dealt with. In retrospect, I should have just used the words location and length instead of frame and frames but that won't change any time soon.
So...loopFrame is the current playback location of the loop and loopFrames is the length of the loop.
When you say "master loop", that could mean a few things.
Mobius has multiple tracks, and each track can contain multiple loops. Within each track, there is an active loop which is the one that the track is playing.
There is also an active track which is the one that has the white box drawn around it in the UI.
Most of the time when you reference a symbol in a script or in the console it is retrieving a value from the active loop in the active track. This is the default scope for symbol evaluation. So if a script contained a single line with "Record", what that means is the Record function will be sent to the active track, which causes recording to start in that track's active loop. If the script contained a single line "loopFrames" it would return the length of the active loop in the active track.
So "master loop" could mean "which of the 8 tracks is active" or "which loop in this track is active". The variables to do those are:
activeTrack
activeLoop
activeTrack is a global variable which means there is only one of them and it will have the number 1 through 8 (assuming the default configuration).
activeLoop is a track variable which means each track has a different value.
When a script needs to look at or do things to a specific track, it uses the in statement to specify which track it wants to operate in. To get the active loop number in track 5 you would write:
in 5 activeLoop
If you do not use in in a script, any functions or variables you reference are happening inside whatever track is active. This is the default scope. The in statement overrides this default scope and let's you target any of the tracks.
As an example, let's say you want to know the location of the loop playing in track 5. That would be:
in 5 loopFrame
This is where MSL is more like Lisp than anything else. Everything in MSL is an expression that returns a value. in returns a value, it is the value of the last thing inside the in block. In this case there is only one thing loopFrame so it returns that. But in also sets the track scope to 5 for loopFrame so it returns the value of loopFrame in track 5.
The equivalant in C++ would be somthing like this:
return tracks[5]->loopFrame;
Most of the though you don't do things with the result of an in you do things inside the in.
// this prints the current loop location in track 5
print (in 5 loopFrame)
// this does the same thing, but the printing happens inside the in
in 5 { print(loopFrame) }
The second example is what you will almost always see in scripts. The only time you you would use the first example is when you were assembling data from several tracks.
print("Location in track 1 is" in 1 loopFrame " and location in track 2 is" in 2 loopFrame)
You could also do this but they are two different prints:
in 1 print("Location in track 1 is" loopFrame)
in 2 print("Locaion in track 2 is" loopFrame)
Another question too... Since the documentation seems to be behind the
development of MSL, is there a way to discover the available variables
and functions in MSL programatically? I'd like to basically print all
of the available variables and functions in the current context.
Yeah, the documentation is woefully incomplete, I add things now and then
but it isn't as fun so I procrastinate.
Something close to what you want is the Symbol Table. From the Test menu
select Symbol Table. This table contains every symbol name that you can
reference in a script. Most of these correspond to the functions and parameters
that you see in the UI. A few like loopFrames are called script variables or
just variables. These you can only access from within a script.
Once you start writing scripts, scripts may export custom functions and varables
that will also be seen in this table, and they can be used by other scripts or
in bindings.
Unfortunately you can't easily capture the contents of this table to have as an offline
reference. If you want to dig deep in the dirt, all of the built-in symbols have
definitions in a file called symbols.xml which you can find in the Mobius installation
directory. It's basically the same thing, minus script contributions, surrounded by a lot
of XML noise.
"print all of the available variables and functions in the current context"
I'm guessing that means you want to see all of the values of those symbols at
a moment in time. There isn't a good way to do that in bulk, but that's a good idea.
Some kind of state dump to a file so you can see what the system is doing.
You can do that to a degree in the console window, just one symbol at a time. Take
loopFrame for example. Bring up Script->Console and type "loopFrame" at the prompt.
That symbol is evaluated, which causes a query to be run on the selcted track to return
the current loop location. When the query result comes back it is printed in the console.
You can type in the name of any parameter or variable and see the value, but you can only
do them one at a time, there is no "show me everything" command yet.
You can also run functions from the console. Type "Record" and see what happens. This
is basically my testing tool, but it can be useful when debugging scripts as well.