Mobius Scripting

March 2012


Contents

1Introduction
2Writing Scripts
3Running Scripts
4Debugging Scripts
5Script Language Fundamentals
5.1    Anatomy of a Statement
5.2    Intrinsic and Function Statements
5.3    Case Insensitivity
5.4    Parameters and Variables
5.5    Statement Blocks and Indentation
5.6    The Mysterious $
6Script Execution Environment
7Script Language Reference
7.1    Declarations
7.1.1        !autoload
7.1.2        !controller
7.1.3        !focuslock
7.1.4        !multiclick
7.1.5        !name
7.1.6        !quantize
7.1.7        !spread
7.1.8        !sustain
7.1.9        !switchQuantize
7.2    Expressions
7.3    Intrinsic Statements
7.3.1        break
7.3.2        call
7.3.2.1            Procedures
7.3.3        cancel
7.3.4        diff
7.3.5        end
7.3.6        endproc
7.3.7        echo
7.3.8        else
7.3.9        elseif
7.3.10        endif
7.3.11        end
7.3.12        for
7.3.13        if
7.3.14        initpreset
7.3.15        jump
7.3.16        label
7.3.17        load
7.3.18        message
7.3.19        next
7.3.20        preset
7.3.21        proc
7.3.22        prompt
7.3.23        repeat
7.3.24        save
7.3.25        set
7.3.26        setup
7.3.27        unittestsetup
7.3.28        variable
7.3.29        wait
7.3.30        while
7.4    Special Labels
7.4.1        reentry
7.4.2        sustain
7.4.3        endSustain
7.4.4        click
7.4.5        endClick
7.5    Functions
7.5.1        Divide
7.5.2        Backward
7.5.3        Forward
7.5.4        SpeedCancel
7.5.5        Halfspeed
7.5.6        InstantMultiply
7.5.7        Loop
7.5.8        MidiOut
7.5.9        Move
7.5.10        MuteOff
7.5.11        MuteOn
7.5.12        OverdubOff
7.5.13        OverdubOn
7.5.14        PitchBend
7.5.15        PitchOctave
7.5.16        PitchStep
7.5.17        SpeedBend
7.5.18        SpeedOctave
7.5.19        SpeedStep
7.5.20        SpeedToggle
7.5.21        Sample
7.5.22        Shuffle
7.5.23        Slip
7.5.24        Sustain Functions
7.5.25        TimeStretch
7.5.26        Track
7.5.27        Loop Windowing
7.6    Parameters
7.6.1        Comma Separated Values
7.7    Track Parameters
7.7.1        focus
7.7.2        group
7.7.3        preset
7.7.4        presetNumber
7.8    Track Controls
7.9    Variables
7.9.1        Script State
7.9.1.1            clickCount
7.9.1.2            midiChannel
7.9.1.3            midiNumber
7.9.1.4            midiType
7.9.1.5            midiValue
7.9.1.6            returnCode
7.9.1.7            sustainCount
7.9.1.8            triggerNumber
7.9.1.9            triggerOffset
7.9.1.10            triggerValue
7.9.2        Loop Sizes
7.9.2.1            cycleCount
7.9.2.2            cycleFrame
7.9.2.3            cycleFrames
7.9.2.4            cycleNumber
7.9.2.5            layerCount
7.9.2.6            loopCount
7.9.2.7            loopFrame
7.9.2.8            loopFrames
7.9.2.9            loopNumber
7.9.2.10            redoCount
7.9.2.11            subCycleNumber
7.9.2.12            subCycleFrame
7.9.2.13            subCycleFrames
7.9.2.14            subCycleCount
7.9.3        Loop Events
7.9.3.1            nextEvent
7.9.3.2            nextEventFunction
7.9.3.3            nextLoop
7.9.4        Loop Modes
7.9.4.1            effectiveFeedback
7.9.4.2            inHalfspeed
7.9.4.3            inMute
7.9.4.4            inOverdub
7.9.4.5            inPause
7.9.4.6            inRealign
7.9.4.7            inReturn
7.9.4.8            inReverse
7.9.4.9            isRecording
7.9.4.10            mode
7.9.5        Speed and Pitch
7.9.5.1            rate
7.9.5.2            rawPitch
7.9.5.3            rawSpeed
7.9.5.4            speedToggle
7.9.5.5            speedSequenceIndex
7.9.5.6            pitchSequenceIndex
7.9.6        Track State
7.9.6.1            globalMute
7.9.6.2            outSyncMaster
7.9.6.3            solo
7.9.6.4            track, trackNumber
7.9.6.5            trackCount
7.9.6.6            trackSyncMaster
7.9.7        Generic Sync
7.9.7.1            syncAudioFrame
7.9.7.2            syncBar
7.9.7.3            syncBeat
7.9.7.4            syncCorrections
7.9.7.5            syncCyclePulses
7.9.7.6            syncDealign
7.9.7.7            syncDrift
7.9.7.8            syncDriftChecks
7.9.7.9            syncLoopFrames
7.9.7.10            syncPreRealignFrame
7.9.7.11            syncPulse
7.9.7.12            syncPulseFrames
7.9.7.13            syncPulses
7.9.7.14            syncRawBeat
7.9.7.15            syncTempo
7.9.8        Out Sync
7.9.8.1            syncOutBar
7.9.8.2            syncOutBeat
7.9.8.3            syncOutRawBeat
7.9.8.4            syncOutSending
7.9.8.5            syncOutStarted
7.9.8.6            syncOutStarts
7.9.8.7            syncOutTempo
7.9.9        MIDI Sync
7.9.9.1            syncInBar
7.9.9.2            syncInBeat
7.9.9.3            syncInRawBeat
7.9.9.4            syncInReceiving
7.9.9.5            syncInStarted
7.9.9.6            syncInTempo
7.9.10        Host Sync
7.9.10.1            syncHostBar
7.9.10.2            syncHostBeat
7.9.10.3            syncHostRawBeat
7.9.10.4            syncHostReceiving
7.9.10.5            syncHostStarted
7.9.10.6            syncHostTempo
7.9.11        Miscellaneous
7.9.11.1            blockFrames
7.9.11.2            configurationDirectory
7.9.11.3            installationDirectory
7.9.11.4            noExternalAudio
7.9.11.5            sampleFrames
8Examples
8.1    Sustain Scripts
8.2    Long Press Scripts

1 Introduction

Mobius provides a powerful feature called scripting that can be used to add new functions or customize the behavior of Mobius to match your looping style. Some of the things that can be done with scripts include:

A script is simply a text file that can be created with any text editor. The contents of the script file are statements in a language called the Mobius Scripting Language. Once the script files have been written, they are registered so that Mobius knows their names and locations. Once a script file has been registered, it may be assigned one or more triggers which can be MIDI messages, computer keyboard presses, or buttons in the Mobius window.

When a trigger for a script is received, the statements in the script are performed. This process is called running the script, executing the script, or calling the script.

The following is an example of a simple script:

  wait loop
  Reverse
  Halfspeed

When this script is called, it will first wait until the loop reaches its start point, then perform a Reverse and Halfspeed function at exactly the same time.

2 Writing Scripts

You may write a script using any text editor, though it is critical that you save the files as "plain text". If you are not in the United States you need to be careful about the character encoding used for the script file. Scripts must be written in an 8-bit character encoding that is compatible with ASCII.

If you are using Notepad on Windows, you must save the file using the ANSI encoding, you must not use Unicode. If you are using Wordpad, in the Save as type: menu you must select either Text Document or Text Document - MS-DOS Format.

If you are using TextEdit on a Mac, you need to save the file in a plain text encoding, either Western (Mac OS Roman) or Western (Windows Latin 1). When you use the Save As menu item, if you see a File Format: menu with items like Rich Text Format or Web Page (.html) then you are editing the file using rich text rather than plain text. Open the TextEdit Preferences window and under the New Document tab select the Plain Text radio button under the Format section. Once you do this create a new document and the Save As window should show a Plain Text Encoding: menu, select Western (Mac OS Roman).

There are many text editors available that present encoding options in different ways or using different words. The presentation may also be different on different versions of the operating system. The main thing to keep in mind is that you must always pick the simplest text format available, usually this is referred to as "plain text" with encodings such as "ansi", "latin 1", "roman", or "MS-DOS". Stay away from anything that says "rich" or "unicode" or that looks like a word processor format.

A script file may have any name, but it is recommended that they have the extension .mos. Scripts may be stored in any directory. On OS X most people keep them in /Library/Application Support/Mobius/scripts. On Windows most people keep them in a directory under the Mobius installation directory, usually c:\Program Files\Mobius 2\scripts.

Once you have created the script file, you need to tell Mobius about it through a process called script registration. There are two ways to register scripts: by file and by directory. When you register a script file, that file is loaded into Mobius when it starts. If you register a script directory, all scripts in that directory are loaded. Registering script directories is convenient if you have a lot of scripts and you don't want to register all of them one at a time. You do need to be careful though to only put things in this directory you really need.

To register a script open the Configuration menu and select Scripts, the Script Registration window will open.

Graphic

On Windows you will see Add Script and Add Directory buttons that will bring up standard selection dialogs for files or directories. On Mac you will see a similar window but it will only have a single Add button because the standard Mac file selector lets you select both files and directories.

To register a new script or script directory, click one of the add buttons, navigate to the file or directory you want to register and click Open on Windows or Choose on Mac. The name of the file or directory should now appear in the list in the center of the script registration window. If you want to remove an item from the list, click on it so that it becomes highlighted then click the Delete button. Finally click the Ok button at the bottom of the widow to save the changes. The new set of scripts will be loaded into Mobius and are available for binding.

3 Running Scripts

Like build-in functions, scripts are run in response to a trigger such as a MIDI message, computer keyboard key, or a button in the Mobius user interface. The process of associating a trigger with a script is called binding. >See the Controlling Mobius in the Getting Started manual for a full description of how to create bindings. Once you have registered some scripts or script directories you will start seeing their names in the Scripts tab of the binding windows.

Note that scripts will usually appear in the binding windows with a name other than the raw file name. Most scripts include a line starting with !name at the top that specifies a user friendly name you want to see in the binding windows. For example:

    !name Global Fade Out

A typical script file may have a name like "fadeoutall.mos" but the name you see in the binding windows might be "Global Fade Out" or something else more meaningful than the file name. You will need to look in each script to see if it contains a !name line and remember to look for that name in the binding windows. If the script doesn't have a !name line you will just see the name of the script file without the ".mos" extension.

When binding a script to a trigger, consider whether you want to use advanced script features such as Sustain Scripts or Long Press Scripts. These features require that the script be bound to a Sustainable Trigger such as a MIDI note message.

4 Debugging Scripts

TODO: Introduce DBWIN32, Echo, Message, Prompt...

5 Script Language Fundamentals

A script is simply a text file containing lines of characters with each line ending with a return character. Each line of text will be one of the following types:

For a given line of text the first significant character determines the type. The first significant character is anything other than white space characters such as spaces and tabs.

If all the characters on a line are white space, the line is empty and is ignored.

If the first significant character is a # the line is a comment and the entire line is ignored.

If the first significant character is a ! the line is a declaration.

If the first significant character is anything other than whitespace, # or ! the line is a statement.

Declarations are used to give Mobius information about how to run the script. They can appear anywhere in the script but it is recommended that you put them all at the top. The order of declarations is not important.

Statements are performed in the order they are written in the script.

This example script shows each of the line types.

  # Do the NextLoop function after turning off switch quantize
  !name Next Loop Now

  set switchQuant off
  NextLoop

The first line begins with a # so it is a comment. You may put comments anywhere in the script to explain what the script is doing.

The second line is a declaration, in this example it is specifying the name you want to display in the binding windows.

The third line is empty.

The fourth and fifth lines are statements.

GEEK NOTE:If you have experience with other programming languages, note that Mobius does not support multi-line statements (with or without a line continuation character) and there are no block comments. If you don't know what that means don't worry. All that you need to remember is that a comment, declaration or statement must all be one line.

5.1 Anatomy of a Statement

A statement always begins with a Keyword which is a sequence of letters and numbers with no spaces. Example keywords are Record, set, and if. When we talk about statements, we usually identify them by their keyword, such as "a Record statement" or "an if statement".

After the keyword, a statement may contain arguments or expressions. An argument is a single word or number without spaces, an expression is a complex sequence of characters that may include spaces. Consider this example:

  variable nextLoop

In the previous example the keyword is Variable so this is called a Variable statement. After the keyword is the argument nextLoop. The meaning of the argument depends on the keyword, in this case the argument is the name of a script variable. Here is a more complex example:

  variable nextLoop loopNumber + 2

In a variable statement, all of the characters after the name argument are an expression. This expression is used to calculate the initial value of the variable. In this example loopNumber + 2 is the expression.

Some statements have no arguments, a few have more than one argument. Most statements will either zero or one expression. When a statement has both an argument and an expression, the argument comes first. In a few rare cases a statement may allow more than one expression, if so the expressions must be separated by a comma.

5.2 Intrinsic and Function Statements

There are two categories of statements: those that are an intrinsic part of the scripting language, and those that execute Mobius looping functions. Examples of intrinsic statements are variable, set, if and for. Examples of function statements are Record, Overdub and NextLoop.

The intrinsic statements do not change often, but new function statements are added frequently. All the Mobius functions that are visible in the binding windows may be used in scripts, as well as several special functions that are available only in scripts. Whenever we talk about new functions being added to Mobius, you can assume that these functions can also be used in scripts.

GEEK NOTE:If you are familiar with the C language, you can think of intrinsic statements as being similar to the core C language, and the functions being similar to the "stdio.h" standard library.

All of the intrinsic statements will be described in detail because you need to understand all of them to write complex scripts.

The names of the function statements will not be listed here. Instead consult the Mobius Reference manual and find the function you want to use, look for its Internal name, and use that internal name as the first word in the statement.

5.3 Case Insensitivity

The script language is case insensitive which means that upper case and lower case letters are considered to be the same. In the examples you will see, function names usually start with a capital letter and variable names start with a lowercase letter. When a function or variable name contains more than one word, a capitalization style called "camel case" is used which means that the initial letter of adjacent words are upper case and the other letters are in lower case. For example:

  NextLoop
  variable saveQuantize quantize

You do not have to follow this style, "NextLoop", "nextloop", "NEXTLOOP", or "NeXtLoOp" all mean the same thing.

Intrinsic statements will begin with a lower case letter in this document, but this is very inconsistent in older script examples. Keywords whose names are found in common programming languages are usually written in all lower case, these include if, else, for, and while. But other Other keywords are often capitalized, such as Variable, Label, and Jump.

5.4 Parameters and Variables

TODO: The difference between parameters and variables, User defined and system variables, variable scoping...

5.5 Statement Blocks and Indentation

A few statements are used to define a range of statements that may be executed more than once or not at all. The range of statements is called a statement block, the statements that surround the block are called block start and block end statements.

The following table lists the block start statements with their corresponding block end statements:

StartEnd
ifendif, else, elseif
elseifendif, else, elseif
elseendif
fornext
repeatnext
whilenext
procendproc

How the block statements behave will be described later. The important thing to know now is that statement blocks must have both a start and end statement and you must use the end statement that is appropriate for the start statement.

Here are some examples of statement blocks:

  if mode = record
    Overdub
  else
    Reset
  endif

  for *
    set 8thsPerCycle 8
  next

To help make it clear where the statement blocks start and end it is recommended that you use indentation for the lines inside the block. Most examples use 2 spaces of indentation but you can use any number. Indentation is not required but it makes the script easier to read and understand.

Block statements may be nested which means that a block may appear inside another block. Here is a simple example of a nested block:

  if mode = record
    if track = 1
      Overdub
    endif
  endif

When blocks are nested, the block start statement is paired with the nearest block end statement that follows. It is strongly recommended that you use indentation to make it clear which block start and end statements belong together.

5.6 The Mysterious $

The $ is a special character used to indicate that the word that follows it is a parameter or variable reference. In early versions of Mobius the $ was required for references, now it is optional in most places. Since it appears in example scripts it tends to keep reappearing even though it is not required.

The $ is required in a few statements where it is not clear whether a word is a reference, or simply a word. These statements are:

These functions all use the remainder of the line following the keyword as a message to be displayed to the user. The message will be displayed exactly as it is written. For example the statement "message mode" will display the string "mode". If you want to display a message with the name of the current looping mode, you reference the mode variable with a $.

  message The current mode is $mode

6 Script Execution Environment

NOTE: This section introduces concepts that may be difficult for people without programming experience to understand. It is not necessary to understand this section in order to write scripts. But if you write scripts using the wait statement, the !sustain declaration, or the !multiclick declaration, this section will help you understand how to get the most power out of these features.

Scripts are similar to a re-entrant function in a multi-threaded programming language. These concepts should be familiar to most programmers, but they basically mean that there can be several copies of the script running at the same time.

Each of the calls for the down transition, up transition, and sustain notifications are done in an environment similar to a thread. If you use Wait statements, it is possible for the script to be active in more than one thread. By using variables, the threads can communicate with each other.

More here...

7 Script Language Reference

7.1 Declarations

In this section we will describe the declarations. These may appear anywhere in the script though there are usually written at the top.

7.1.1 !autoload

Normally scripts are loaded once when Mobius is first started and remain in memory for as long as Mobius runs. If you make changes to the script file they will not be used by Mobius until you restart it.

The !autoload declaration will cause the script file to be reloaded from the file system every time the script is called. This is very useful when writing new scripts as it allows you to keep Mobius running while you make changes the script.

After the script is working properly you should remove this declaration. Reloading the script causes a small delay before the script is run. This can make it difficult to apply the script to exact locations in the loop.

7.1.2 !controller

This option identifies the script as a controller script. When the script is triggered by a MIDI continuous controller, the script is called whenever the value of the controller changes.

Normally, when a script is bound to a MIDI continuous controller, it is assumed that the controller messages are being sent by a momentary switch rather than an expression pedal. Momentary switches typically send a non-zero controller value when the switch is pressed and a zero value when the switch is released. Mobius will only call the script when it receives a non-zero value which means the switch has been pressed. It will not call the script when it receives a zero value after the switch is released, unless you also use the !sustain declaration.

This behavior is usually not desired when the continuous controller values are being generated by an expression pedal. With an expression pedal, you want the script called whenever the position of the pedal changes, even when it goes to zero.

Controller scripts are most often used to change the track controls : Input Level, Output Level, Feedback, Secondary Feedback, and Pan.

They may also be used to change speed and pitch shift for each track, and change preset parameters such as 8ths Per Cycle or any other parameter that has a range of values.

Including the !controller declaration in a script will disable the following directives if they also appear in the script.

Here is an example script that implements a basic volume control. The behavior of this script is exactly the same as binding a controller to the Output Level track control.

  !name Output Level
  !controller
  set output midiValue

The !controller declaration tells Mobius that this script should be called every time the value of the trigger changes. The word midiValue is a reference to a system variable that will contain the value of the continuous controller that triggered this script. The value will be from 0 to 127.

Here is a more interesting example that sets the output level to the inverse of the controller value. When the controller value is zero (toe up) the output level will be 127, when the controller value is 127 (toe down) the output level will be zero.

  !name Backwards Output Level
  !controller
  set output 127 - midiValue

If you are familiar with the EDP, controller scripts give you the ability to implement "flip mode" as well as many other combinations of Mobius controls that change in response to a single expression pedal.

7.1.3 !focuslock

Normally scripts do not obey focus lock or track groups. When a script is run it will only run in the selected track.

The !focuslock declaration makes the script sensitive to track focus lock. The script will be run simultaneously in all focused locked tracks. If the Groups Have Focus Lock parameter is true, this declaration will also cause the script to be run in all tracks that have the same group as the selected track.

This option is useful for simple scripts that only operate on one track. It makes the script behave more like the built-in Mobius functions. If however the script uses the for statement to operate on several tracks, you normally do not use the !focuslock option.

7.1.4 !multiclick

This option allows the script to change behavior if you trigger it more than once within a short time. Some people think of this as "double clicking". A script that uses this option is called a multi-click script.

To create a multi-click script, add this declaration:

  !multiclick 2000

The numeric argument is the trigger expiration period expressed as a number of milliseconds. The default expiration period is 1000 (1 second) so you only need to include this argument if you want a value other than 1000. In this example the expiration period will be two seconds.

Next add Label statements to the script with these names:

As always this is best described with an example:

  !name Multiclick Test

  # the default value is 1000 milliseconds, override to 2 seconds
  !multiclick 2000

  message Starting Click Test
  end

  label click
  message Click $clickCount
  end

  label endClick
  message Ending Click Test
  end

When you trigger the script for the first time, the message "Starting Click Test" is displayed. If you trigger the script again within 2 seconds, a message is displayed showing the number of triggers that have been received from the system variable clickCount. If you wait 2 seconds without triggering the script again, the "Ending Click Test" message is displayed and the script is finished.

Each time the script is triggered, the expiration period starts over at 2 seconds.

GEEK Note: As with sustain scripts, the click and endClick labels are called in different threads so the script may be active in more than one thread. Variables can be used for communication between threads.

7.1.5 !name

This declaration is used to specify the name to be displayed for this script in the binding windows. If no name is specified, the file name is displayed. It is very common to use a !name declaration since the script file name is not always meaningful to the user.

The name consists of all characters after the space after the !name declaration up to the end of the line. In the following example, the name displayed for the script would be "Auto Record 4".

  !name Auto Record 4

Like all declarations, !name may appear anywhere in the file but it is usually the first line to make it easier to see.

7.1.6 !quantize

Normally scripts will not obey the Quantize Mode parameter in the preset. When a script is triggered it will be run immediately.

The !quantize option makes the script sensitive to the Quantize Mode parameter, it will be run at the next quantization point. This makes scripts behave more like built-in functions.

This option is most often used when the script does not begin with a Wait statement.

TODO: The difference between !quantize and Wait...

7.1.7 !spread

This option will allow the script to be triggered by a range of MIDI note, controller, or program change messages. The script is bound once to the center of the range, but will then be triggered by messages on either side of the center.

This option is usually used when binding to MIDI note messages. If the script is bound to middle C, then notes on either side of middle C will automatically be bound to the script. This is similar to the way the Pitch Step and Speed Step functions behave. The note you select in the binding window is the center note, pressing notes below the center lowers the pitch/speed, pressing notes above the center raises the pitch/speed.

For spread scripts, the script will be run when any note in the range is pressed. The script can then reference internal variables to determine which note within the range was pressed.

While it will be most common to bind spread scripts to MIDI notes so that you can "play" the script chromatically, you can also bind the script to a range of program changes or continuous controller values.

To define a spread script, include this declaration at the top:

  !spread

The default range of the spread is 48 values on either side of the center, which for notes means 4 octaves up and 4 octaves down. You can reduce this range by adding an argument to the !spread declaration:

  !spread 4

In the previous example, the 4 argument means that the spread will be 4 notes on either side of the center.

If there is a conflict between a spread script binding and another function that is bound to a specific note, the other function will have priority. For example, if a spread script with a range of 12 is bound to note 64, the script will be called whenever notes 52 to 76 are received. If you also have the Record function bound to note 59, that note will call the Record function, but all the notes around it will still call the script. You can think of this like "holes being punched" into the spread range. You usually do not want to have a spread range conflict with another function binding so it is best to move the center notes so they do not overlap. If you want to have a large spread range, you will need to use different MIDI channels for the center notes.

When a spread script is called, the following system variables may be referenced to adjust the behavior of the script:

For example, if you bind the script to note 64 and you press note 63, the value of triggerOffset will be -1. If you press note 64 triggerOffset will be 0, and if you press note 65 triggerOffset will be 1.

The built-in Speed Step function could be implemented with this script:

  !name Script Speed Step
  !spread 12
  SpeedStep triggerOffset

Spread scripts are probably most useful with the SpeedStep, PitchStep, LoopTrigger, and TrackSelect functions. But you could also use them to set the output level or 8thsPerCycle parameter.

As a more interesting example, if you always want to speed shift in octave intervals, you could use this script and you would only need to reserve 9 notes:

  !name Speed Step Octaves
  !spread 4
  SpeedStep triggerOffset * 12

7.1.8 !sustain

This option will cause the script to be run on both the down and up transitions of the trigger. A down transition happens when you press a switch, an up transition happens when you release a switch. A script that uses this option is called a sustain script. Sustain scripts are effective only if you are using a momentary trigger such as a MIDI note, MIDI continuous controller, or computer keyboard key.

To use MIDI notes, the trigger device must send a Note On event when a switch is pressed and a Note Off event when the switch is released. To use MIDI continuous controllers, the switch must send a CC value greater than zero when the switch is pressed and zero when the switch is released. Note that you can not use MIDI program changes for sustain scripts since the program change is only sent when the switch is pressed.

Sustain scripts are also run repeatedly while the switch is held down, this allows it to change behavior depending on how long the switch is held. This allows scripts to have long press behavior like other built-in functions.

To be notified when the trigger goes up, you simply add this label to the script:

  label endSustain

The statements following this label will be run when the function trigger goes up.

To be notified while the trigger is held, add this label to the script:

  label sustain

The statements following this label will be run every 250 milliseconds (1/4 second) while the trigger is held. You can determine how long the trigger has been held by testing the sustainCount variable. This will have a number starting at 1 and incrementing by 1 every time the sustain script is called.

You can specify the duration of the sustain notifications by adding a number after the !sustain keyword. This number is the number of milliseconds between notifications. For example, this declaration will cause the sustain label to called every second rather than every 1/4 second.

  !sustain 1000

Here is a more complex example that demonstrates all of the features of sustain scripts.

  !name Sustain Test

  # default is 250 msec, raise it to 1 sec
  !sustain 1000

  # the Message statement can be used to display brief messages
  message Starting sustain test
  end

  label sustain
  message Sustained $sustainCount
  end

  label endSustain
  message Ending sustain test
  end

You can think of this as 3 scripts in one. From the top to the first end are the statements that are run when the switch is pressed.

The statements from label sustain to the next end are called as the switch is held.

The statements from label endSustain to the next end are called when the function trigger goes up.

You do not need to declare both labels, but you do need to remember to put an end before each of the sustain labels.

GEEK Note: Scripts are similar to a re-entrant function in a multi-threaded programming language. Each of the calls for the down transition, up transition, and sustain notifications are done in an environment similar to a thread. If you use Wait statements, it is possible for the script to be active in more than one thread. By using variables, the threads can communicate with each other.

Here is a more realistic example. A long-press of the Record function will normally perform a Reset. This script does something similar but with the Mute function.

  !name Mute/Reset

  Mute
  end

  label sustain
  if sustainCount = 1
  Reset
  endif

Under the sustain label, you can test the sustainCount variable to make the script change behavior the longer the trigger is held. Some examples of this might be:

Here is another example of simple sustain script that raises the speed a fifth while held and drops it back when released.

  !name SUSSpeedUp5

  SpeedUp 7
  end

  label endSustain
  SpeedDown 7
  end

7.1.9 !switchQuantize

When you change loops with the switchQantize parameter set something other than off, Mobius will enter a special Switch mode while it waits for the next switch quantization point. During this mode, many functions that you trigger are queued and performed after the loop switch.

By default scripts do not wait until after the loop switch, they are run immediately. The !switchQuanitze option will delay the execution of the script until after the loop switch. This makes scripts behave more like built-in functions.

Note however that the functions performed by the script are not treated like alternate endings to the switch function. For example, if you do an Overdub during the switch quantization and the next loop is empty, the current loop is copied into the next loop. But if you run a script whose first function is Overdub, this will not cause the loop to be copied.

7.2 Expressions

7.3 Intrinsic Statements

The syntax for each statement will be summarized using a notation that programmers should recognize as similar to BNF. For example:

    call <scriptName> | <procName> [<arg> ...]

A line in a script is divided into tokens separated by one or more spaces. The syntax notation describes what each token means. Tokens are often just words without spaces like call. If a token needs to contain spaces it must be surrounded in double quotes like "My Script".

In the syntax notation, tokens that are not surrounded by angle brackets must be written exactly as shown. Tokens that are surrounded by angle brackets must be replaced with tokens that are meaningful for your environment. For example the token <scriptName> would be replaced by the name of the script you want to call.

The vertical bar is used when there is a choice of several tokens that may appear at this location. In this example the token following the Call may be either a procedure name or a script name.

Square brackets are used to surround optional tokens. In this example the call statement may have an optional list of arguments. The ... means that the contents within the brackets may be repeated any number of times.

Two special tokens are used in syntax notation:

Note that some of the intrinsic statements are intended for use only in special testing scripts. The statement keywords are presented using the character case that is most often seen in the example scripts. As mentioned in the Case Insensitivity section, case in function names is ignored.

7.3.1 break

This statement is used only by developers running Mobius under a debugger. It will have no effect when running Mobius outside of a debugger. Return to your homes, there is nothing to see here.

7.3.2 call

    call <scriptName> | <procName> [<arg> ...]

Calls another script or a procedure, with optional arguments.

When a script is called, the statements in the script are executed as if they were written directly in the calling script. Only scripts that have been registered in the Scripts dialog can be called.

Normally scripts are referenced using the name defined by the !name declaration in the script. If the script has no !name you may reference the script using its file name.

  # Call a script using its !name
  # note that quotes must be used if the script name contains spaces

  call "My Script"

  # Call a script using its file name
  call myscript.mos

  # Call a script using its file name without the .mos extension
  call myscript

Script arguments may either be symbols, strings, or variable references. A symbol is simply a word without spaces. A string is a sequence of characters surrounded by double quotes. A variable reference is the name of a variable or parameter prefixed with the $ character.

  # Call a script passing a symbol argument
  call "Set Sub Cycles" 8

  # Call a script passing a string argument
  call ShowMessage "This is my message to you!"

  # Call a script passing a variable value
  variable message "This is my message to you!"
  call ShowMessage $message

In the script being called, arguments are referenced with a number preceded by the $ character. Script arguments are numbered starting from 1. For example:

  !name Set Sub Cycles
  message Changing subcycles to $1
  set 8thsPerCycle $1

The previous script will set the 8thsPerCycle preset parameter to the value of the first argument.

Note that scripts that are designed to be called from other scripts usually do not have any declarations other than !name and sometimes !autoload. Any other declarations in the called script will be ignored. If you want the called script to be quantized for example, you will need to use the wait statement in the calling script.

7.3.2.1 Procedures

A procedure is a set of statements defined within a script that will not be executed until you call them. Procedures are defined with the proc statement. Procedures are used in the Mobius test scripts but are not often used in user scripts. Their primary use is to prevent the duplication of a set of statements that are needed more than once in the script.


  # define a procedure
  # the statements within the Proc/Endproc will NOT be executed
  # until you call the procedure

  # Define a procedure
  proc ChangeDirection
    if inReverse
        Message Leaving reverse mode
    else
        Message Entering reverse mode
    endif
    Reverse
  endproc

  # toggle reverse mode with a message
  call ChangeDirection

  # wait for the end of the loop
  wait loop

  # toggle reverse mode with a message again
  call ChangeDirection

Arguments may also be passed to called procedures:

  # set 8thsPerCycle to the value of the first argument
  proc SetSubCycles
    set 8thsPerCycle $1
  endproc

  # call procedure passing number of subcycles desired
  call SetSubCycles 8

7.3.3 cancel

7.3.4 diff

7.3.5 end

7.3.6 endproc

7.3.7 echo

7.3.8 else

see if

7.3.9 elseif

see if

7.3.10 endif

see if

7.3.11 end

7.3.12 for

7.3.13 if

    if <condition>
      block
  { elsif <condition>
      block }
  [ else
      block ]
    endif

Executes a block of code if a condition is met.

A condition is a Boolean Expression. A Boolean expression is an expression that is interpreted as one of only two distinguishable values: True or False.

  bool_expression = bool_term { or bool_term }
  or              = | | ||
  bool_term       = bool_factor { and bool_factor }
  and             = & | &&
  bool_factor     = bool_constant | comparison | not bool_factor | ( bool_expression )
  bool_constant   = False | True
  not             = not | !
  comparison      = arithmetic_expression relation arithmetic_expression
  relation        = equal | < | <= | > | >=
  equal           = = | ==

  arithmetic_expression = term  { (+|-) term}
  term                  = factor  { (*|/) factor}
  factor                = constant | variable | (  arithmetic_expression )
  variable              = mobius_variable, e.g. mode
  constant              = numeric integer or float constant

(see Jeff Laron's post)

A real-world example employing if, else, endif


  # A script duplicating the Record function including long press to erase a loop.
  # In addition we're sending arbitrary MIDI controller messages to notify a
  # connected pedal board with display capabilities.

  !name Record And Signal

  # Mobius-Script
  # behaves like built-in Record but sends signal on events:
  #   - start recording
  #   - stop recording
  #   - delete
  #

  # default is 250 msec, raise it to 500 msec
  !sustain 500
    if mode = reset || mode = play
      Record
      MidiOut control 15 127 70
    else
      Play
      MidiOut control 15 126 70
    endif
  end

  label sustain
    if sustainCount = 1
      Reset
      MidiOut control 15 125 70
    endif
  end

7.3.14 initpreset

7.3.15 jump

7.3.16 label

7.3.17 load

7.3.18 message

7.3.19 next

7.3.20 preset

7.3.21 proc

    proc <procedureName>

This statement begins a procedure definition. The argument must be a literal string that defines the procedure name. The procedure definition must be terminated by an endproc statement.

See Procedures for more information on defining and calling procedures.

7.3.22 prompt

7.3.23 repeat

7.3.24 save

7.3.25 set

7.3.26 setup

7.3.27 unittestsetup

7.3.28 variable

7.3.29 wait

7.3.30 while

7.4 Special Labels

7.4.1 reentry

7.4.2 sustain

7.4.3 endSustain

7.4.4 click

7.4.5 endClick

7.5 Functions

All Mobius functions may be used in scripts. The names of the functions used in scripts may differ slightly from the names you will see in the UI. In particular, script function names never contain spaces. If a function name is displayed in the UI with spaces such as "Next Loop", the script function name is usually the same with the spaces removed such as "NextLoop".

The function reference section of the Mobius Reference manual contains a complete list of all functions arranged in alphabetical order by the display name you will see in the UI. Within the documentation for each function will be a line beginning with Internal name:, the word after this prefix is the name you would use in a script to execute this function.

Note that the function names displayed in the UI are taken from a file that may be modified by the user. This file is called a message catalog. The default message catalog is in the Mobius installation directory and is named Catalog_USEnglish.txt. If you have modified this file, or if you have asked Mobius to read messages from a different file, the names that appear in the reference manual may not be the same as what you will see in the UI.

We will not provide reference documentation for every function in this manual. We will only document functions and function features that are only accessible from scripts. For more information on what the functions do and how they are influenced by parameters, you must read the documentation in the reference manual.

7.5.1 Divide

The function named just Divide without a number is accessible only scripts. With this function the divisor is specified as an argument written after the function name. The argument may be a number or an expression. For example:

    Divide 6
    Divide subcycles / 2

In scripts you can also use the Divide functions that have a fixed divisor in the function name. These two script statements will have the same effect.

    # here the divisor is part of the function name
    Divide4

    # here the divisor is an argument
    Divide 4

See Divide in the Mobius Reference manual for more information.

7.5.2 Backward

Backward forces the loop direction into reverse and sets the Reverse minor mode. This function is provided as a convenience for script writers that need to ensure the loop is playing backward without having to test the inReverse variable. The following two code blocks have the same behavior.

    # Force reverse playback
    Backward

    # Toggle reverse if we're not already in reverse
    if !inReverse
       Reverse
    endif

See Backward in the Mobius Reference manual for more information.

7.5.3 Forward

Forward forces the loop into the normal forward direction. It is provided as a convenience for script writers that need to ensure the loop is playing forward without having to test the inReverse variable. The following two code blocks have the same behavior.

    # Force normal playback
    Forward

    # Toggle reverse if we're currently in reverse
    if inReverse
       Reverse
    endif

See Forward in the Mobius Reference manual for more information.

7.5.4 SpeedCancel

SpeedCancel forces the loop out of all speed shifting modes: SpeedToggle, SpeedOctave, SpeedStep and SpeedBend. This is provided as a convenience to script writers that need to ensure the loop is playing at normal speed without having to test the inHalfspeed or speedToggle varialbes or the speedOctave, speedStep, and speedBend controls. The following two code blocks have the same behavior:

    # Force normal playback
    SpeedCancel

    # Toggle speed if we're currently in 1/2 speed
    if inHalfspeed
       SpeedToggle
    endif

See Speed Cancel in the Mobius Reference manual for more information.

7.5.5 Halfspeed

Halfspeed changes the loop speed so that it plays twice as long and sounds one octave lower. It is an older function that is provided for backward compatibility. If you are writing scripts it is recommended that you use the more general SpeedStep function. Executing Halfspeed is identical to executing SpeedStep with an argument of -12.

The following threecode blocks have the same behavior.

    # Force 1/2 speed playback
    Halfspeed

    # Force 1/2 speed playback
    SpeedStep -12

    # Toggle speed if we're not currently in 1/2 speed
    if !inHalfspeed
       SpeedToggle
    endif

See Halfspeed in the Mobius Reference manual for more information.

7.5.6 InstantMultiply

The function with internal name InstantMultiply without a number may only be used in scripts. The multiplier is specified as an argument to the function. For example:

    InstantMultiply 6

You can also use the InstantMultiply functions with numbers in their names in scripts. These two script statements will have the same effect.

    # here the multiplier is part of the function name
    InstantMultiply4

    # here the multiplier is an argument
    InstantMultiply 4

See Instant Multiply in the Mobius Reference manual for more information.

7.5.7 Loop

The function named just Loop without a number is accessible only in scripts. With this function the loop you want to trigger is specified as a function argument, which may be a number or an expression. For example:

   Loop 3
   Loop loopNumber + 1

Scripts can also use the Loop functions with numbers in their names. These two script statements are the same.

   Loop4
   Loop 4

See Loop in the Mobius Reference manual for more information.

7.5.8 MidiOut

MidiOut can send any MIDI message to the configured MIDI output device. This function is accessible only from scripts. The MIDI message to send is specified with up to four function arguments. The syntax is:

    MidiOut <status> <channel> <value> <velocity>
    status: noteon noteoff control program stop start continue
    channel: 0-15
    value: 0-127
    velocity: 0-127

For example, to send a Note On event on channel 3, note 64, velocity 127, you would write:

    MidiOut noteon 3 64 127

This function does not change the current loop and has no effect on major or minor modes.

7.5.9 Move

Move will instantly move the loop playback position to a new location. It is accessible only from scripts. The new position is specified as a function argument which may either be a number or an expression whose result is a number. This number is used as a frame number within the loop. The first frame in a loop has frame number zero.

   # Jump to a fixed location 1 second from the beginning
   Move 44100

   # Jump to the center of the loop
   Move loopFrames / 2

See Move in the Mobius Reference manual for more information.

7.5.10 MuteOff

MuteOff will cancel the Mute minor mode. If the loop is not in mute mode the function has no effect. This function is not quantized and is accessible only in scripts. It is a convenience for script writers that want to make sure that mute mode is off without having to worry about the current mute state. You can also use the Mute function but since that toggles mute mode you have to test the current mute state. The following script examples are equivalent:

    # Force mute off, ignore if it is already off
    MuteOff

    # Toggle mute off if it is currently on
    if inMute
       Mute
    endif

See MuteOff in the Mobius Reference manual for more information.

7.5.11 MuteOn

MuteOn will activate the Mute minor mode and immediately silence the loop. If the loop is already muted the function has no effect. This function is not quantized and is accessible only in scripts. It is a convenience for script writers that want to make sure that the loop is muted without having to worry about the current mute state. You can also use the Mute function but since that toggles mute mode you have to test the current mute state. The following script examples are equivalent:

    # Force mute on, ignore if it is already on
    MuteOn

    # Toggle mute on if it is currently off
    if !inMute
       Mute
    endif

See MuteOn in the Mobius Reference manual for more information.

7.5.12 OverdubOff

OverdubOff forces the Overdub minor mode off. This function is not quantized and is accessible only scripts. It is provided as a convenience for the script writer that needs to turn overdub off, but is more convenient than using the Overdub function that toggles overdub mode. The following two script examples are equivalent:

    # Force overdub off
    OverdubOff

    # Toggle overdub off if it is on
    if inOverdub
       Overdub
    endif

See OverdubOff in the Mobius Reference manual for more information.

7.5.13 OverdubOn

OverdubOn activates the Overdub minor mode. If overdub mode is already active the function has no effect. This function is not quantized and is accessible only in scripts. It is a convenience for the script writer that needs to turn overdub on, but is more convenient than using the Overdub function that toggles overdub mode. The following two script examples are equivalent:

    # Force overdub on
    OverdubOn

    # Toggle overdub on if it is off
    if !inOverdub
       Overdub
    endif

See OverdubOn in the Mobius Reference manual for more information.

7.5.14 PitchBend

PitchBend will change the playback pitch of the loop up or down in small intervals. The number of intervals is specified as an argument to the fucntion. While this can be called as a function it is expected that pitch bend be usually performed by changing the value of the pitchBend control. Neither the function or the control are quantized.

The range of values is from -8192 to 8181 to match the MIDI pitch wheel.

   # change the pitch with the PitchBend function
   PitchBend 2091
   PitchBend -4087

   # change the pitch with the pitchBend control
   set pitchBend 2091
   set pitchBend -4087

See Pitch Bend in the Mobius Reference manual for more information.

7.5.15 PitchOctave

PitchOctave will change the playback pitch of the loop up or down in octave intervals. The number of octaves is specified as an argument to the fucntion. The octave can also be changed with the pitchOctave control. The difference between the control and the function is that the functions may be quantized but the control is never quantized.

   # setting pitch with functions
   PitchOctave 2
   PitchOctave -1

   # setting pitch with controls
   set pitchOctave 2
   set pitchOctave -1

See Pitch Octave in the Mobius Reference manual for more information.

7.5.16 PitchStep

PitchStep can change the playback pitch of the loop up or down to achieve a pitch change in a number of semitones. The number of semitones is specified as an argument to the function. You may also change the pitch step by setting the pitchStep control. The function may be quantized but the control is never quantized.

   # setting pitch with functions
   PitchStep 5
   PitchStep -7

   # setting pitch with controls
   set pitchStep 5
   set pitchStep -1

See Pitch Step in the Mobius Reference manual for more information.

7.5.17 SpeedBend

SpeedBend will change the playback speed of the loop up or down in small intervals. The number of intervals is specified as an argument to the fucntion. While this can be called as a function it is expected that speed bend be usually performed by changing the value of the speedBend control.

The range of values is from -8192 to 8181 to match the MIDI pitch wheel.

   # change the speed with the SpeedBend function
   SpeedBend 2091
   SpeedBend -4087

   # change the speed with the speedBend control
   set speedBend 2091
   set speedBend -4087

See Speed Bend in the Mobius Reference manual for more information.

7.5.18 SpeedOctave

SpeedOctave will change the playback speed of the loop up or down in octave intervals. The number of octaves is specified as an argument to the fucntion. The octave can also be changed with the speedOctave control. The difference between the control and the function is that the functions may be quantized but the control is never quantized.

   # setting speed with functions
   SpeedOctave 2
   SpeedOctave -1

   # setting speed with controls
   set speedOctave 2
   set speedOctave -1

See Speed Octave in the Mobius Reference manual for more information.

7.5.19 SpeedStep

SpeedStep can change the playback speed of the loop up or down to achieve a pitch change in a number of semitones. The number of semitones is specified as an argument to the function. You may also change the speed step by setting the speedStep control. The function may be quantized but the control is never quantized.

   # setting speed with functions
   SpeedStep 5
   SpeedStep -7

   # setting speed with controls
   set speedStep 5
   set speedStep -1

See Speed Step in the Mobius Reference manual for more information.

7.5.20 SpeedToggle

SpeedToggle is similar to SpeedStep in that it changes the speed of the loop up or down by some number of semitones specified as an argument to the function. The difference is that if you execute SpeedToggle a second time without an argument, the shift established by the previous call to SpeedToggle is canceled.

In the following example we raise the speed by 5 semitones, wait for the end of the loop, then lower it by 5 semitones.

   # setting the speed toggle
   SpeedToggle 5

   Wait loop

   # cancel the speed toggle
   SpeedToggle

See Speed Toggle in the Mobius Reference manual for more information.

7.5.21 Sample

The Sample family of functions will play one of the loaded samples. The function named just Sample without a number may only be used in scripts. The sample to trigger is specified as a function argument that may be a number or an expression.

   # trigger the first sample
   Sample1

   # another way to trigger the first sample with the number
   # specified as a function argument
   Sample 1

See Sample in the Mobius Reference manual for more information.

7.5.22 Shuffle

7.5.23 Slip

The Slip family of functions will instantly move the loop playback position forward or backward by a fixed amount. The amount of slippage for the Slip script function is specified as an argument. The value is a positive or negative number or an expression that evaluates to a number. This number is the number of 'units' to slip where the unit is defined by the Slip Mode parameter.

   # slip forward 2 cycles
   set slipMode cycle
   Slip 2

   # slip backward four subcycles
   set slipMode subcycle
   Slip -4

See Slip in the Mobius Reference manual for more information.

7.5.24 Sustain Functions

Explain how sustain functions can be used in scripts with the up/down arguments.

7.5.25 TimeStretch

TimeStretch is available only in scripts. It will change both the playback speed and the amount of pitch shift such that the observed pitch stays the same but the playback speed increases or decreases. This function must have a script argument that specifies the number of units of stretch. Time stretch may also be accomplished with the timeStretch track control. The function may be quantized, the control is never quantized.

The range of values is from -8192 to 8181 to match the MIDI pitch wheel.

   # change the duration with the function
   TimeStretch 2091
   TimeStretch -4087

   # change the duration with the control
   set timeStretch 2091
   set timeStretch -4087

See Time Stretch in the Mobius Reference manual for more information.

7.5.26 Track

The Track family of functions will activate one of the numbered tracks. If the track is already active, the function will have no effect. The function named just Track can only be used in scripts where the track to select is specified as a function argument.

   # Select a track using a numbered function
   Track2

   # Select a track using an argument
   Track 2

   # Select a track using an expression
   Track rand(1,8)

See Track in the Mobius Reference manual for more information.

7.5.27 Loop Windowing

For a complete description of the concept of loop windowing see the Loop Windowing section of the Mobius Techniques manual.

You may use any of the bindable windowing functions in scripts, but there are two functions available only in scripts that can be used to contorol the loop window. WindowMove sets the starting location of the window and WindowResize adjusts either the starting or ending edges of the window. These functions use arguments to specify the location and size of the window.

The syntax of the WindowMove function is:

    WindowMove [unit] amount

The unit argument is optional and if not specified defaults to the value of the Window Slide Unit parameter. The possible values in scripts are loop, cycle, subcycle, msec, frame, layer, start, and end.

    # move back one loop
    set windowSlideUnit loop
    WindowMove -1

    # move back one loop independent of the windowSlideUnit parameter
    WindowMove loop, -1

    # move forward 1 second
    WindowMove msec, 1000

    # move backward 2 subcycles
    WindowMove subcycle, -2

    # orient the window at the beginning of the previous layer
    WindowMove layer, -1

    # orient the window at the beginning of the loop history
    WindowMove start

    # orient the window at the end of the loop history
    WindowMove end

Note that in these examples a comma is required if you are using negative amounts. This is one of the rare functions whose argument list is completely parsed as an expression (Shuffle is another), and since operator precedence is like C, "x -1" is the same as "x - 1" which means to subtract 1 from x. So the arguments "subcycle -1" would be parsed as subtracting 1 from the variable named subcycle. To prevent this you need to put a comma between them, "subcycle,-1", or surround -1 in parantthesis, "subcycle (-1)". It is easier to use commas.

The start and end units are unusual becase they are not relative units for sliding, they are absolute locations within the history and do not need an amount.

The syntax of the WindowResize function is:

    WindowResize {start | end} [unit] amount

The first argument must be start or end to indiciate which edge you want to move. The unit and amount arguments are the same as those for the WindowMove function. If the unit is not specified, the value of the Window Edge Unit preset parameter is used.

   # Move the left edge back one subcycle
   WindowResize start,subcycle,-1

   # Move the right edge forward one second
   WindowResize end,msec,1000

7.6 Parameters

Describe in general how parameters can be accessed and set from scripts..

7.6.1 Comma Separated Values

When a parameter value is described as being a "comma separated list" it means that the value to assign in a set statement consists of a list of words separated by a comma. There may also be spaces before and after the commas. The following examples are all the same:

  set altFeedbackDisable Multiply,Overdub

  set altFeedbackDisable Multiply, Overdub

  set altFeedbackDisable Multiply  ,  Overdub

7.7 Track Parameters

Each track has a few parameters that are set in the Track Setup. These will have their initial values specified in the Track Setup but they may be changed in scripts.

7.7.1 focus

Value value: true, false

This parameter determines whether the track has focus lock. The parameter may be set with the Focus Lock function or by clicking on the Track Number in the track strip.

Script example:

    set focus true
    FocusLock

7.7.2 group

Value: an integer from 1 to 8

This parameter determines whether the track is a member of a track group. The value is an integer parameter that has the number of the track group in the current track. If the value is zero there is no track group. Positive group numbers are displayed as letters in the user interface. Group 1 is displayed as A group 2 is displayed as B etc. When setting this parameter from a script you may use either numbers staring from 1 or letters starting from A.

Script example:

    set group 1
    set group A

7.7.3 preset

Value: a preset name

This parameter has the name of the preset that is active in the track. This is intended for use only in scripts, in the user interface you select presets from the preset menu or from the preset window.

When setting this from scripts you may use either the preset name or the preset number from 1. While setting this parameter in scripts is allowed, it is preferable in scripts to use the Preset built-in script function.

Script example:

    set preset 1
    set preset "My Preset"
    Preset 1
    Preset "My Preset"

7.7.4 presetNumber

Value: an integer from 1 to infinity

This parameter has the number of the preset that is active in the track. This is intended for use only in scripts, in the user interface you select presets from the preset menu or from the preset window.

When setting this from scripts you may use either the preset name or the preset number from 1. While setting this parameter in scripts is allowed, it is preferable in scripts to use the Preset built-in script function.

Script example:

    set presetNumber 1
    Preset 1

The parameter is functionally the same as Preset but using it makes it clearer in the script that the value will be a number rather than a name.

7.8 Track Controls

Examples of setting track controls from scripts.

7.9 Variables

7.9.1 Script State

7.9.1.1 clickCount

Number of times the script has been reentered due to multi-clicks.

7.9.1.2 midiChannel

The MIDI channel number of the trigger event. This is also embedded in triggerNumber, but it is easier to use here.

7.9.1.3 midiNumber

The MIDI key/controller number of the trigger event.

7.9.1.4 midiType

The type of MIDI trigger: note, control, program.

7.9.1.5 midiValue

The same as triggerValue but has a more obvious name for use in !controller scripts.

7.9.1.6 returnCode

The return code of the last ThreadEvent. Currently used only by Prompt statements to convey the selected button. 0 means Ok, 1 means cancel.

7.9.1.7 sustainCount

Number of times the script has been notified of a sustain.

7.9.1.8 triggerNumber

The unique id of the trigger. For FunctionSourceMidi this will be a combination of the MIDI status, channel, and number. For other sources it will be a key code or other simple number.

7.9.1.9 triggerOffset

An optional extra value associated with the ranged triggers. This will have the relative position of the trigger from the center of the range.

7.9.1.10 triggerValue

Alias: triggerVelocity

An optional extra value associated with the trigger. For MIDI triggers this will be the second byte, the note velocity for notes or the controller value for controllers.

7.9.2 Loop Sizes

7.9.2.1 cycleCount

The number of cycles in the loop.

7.9.2.2 cycleFrame

The current frame relative the current cycle.

7.9.2.3 cycleFrames

The number of frames in one cycle.

7.9.2.4 cycleNumber

The current cycle number, relative to the beginning of the loop.

7.9.2.5 layerCount

The number of layers in the current loop. This is also in effect the current layer number since we are always "on" the last layer of the loop. This does not include the number of available redo layers.

7.9.2.6 loopCount

The current loop count. This is effectively the same as the "moreLoops" parameter but I like this name better. This should really be an alias of moreLoops so we can get and set it using the same name!!

7.9.2.7 loopFrame

The current record frame. The value of this variable changes automatically as the loop plays. You might think that setting this variable would cause the playback position to move but this is not allowed. Instead you must use the Move function to change the playback position.

7.9.2.8 loopFrames

The number of frames in the loop.

7.9.2.9 loopNumber

The number of the current loop within the track. The first loop number is 1 for consistency with the trigger functions Loop1, Loop2, etc.

7.9.2.10 redoCount

The number of redo layers in the current loop.

7.9.2.11 subCycleNumber

The current subcycle number, relative to the current cycle.

7.9.2.12 subCycleFrame

The current frame relative the current subcycle.

7.9.2.13 subCycleFrames

The number of frames in one subcycle.

7.9.2.14 subCycleCount

The number of subCycles in a cycle. This is actually the same as the Subcycles preset parameter and can change with the preset, but we expose it as an internal variable so it is consistent with the other loop variables.

7.9.3 Loop Events

7.9.3.1 nextEvent

Returns the type name of the next event. Child events are ignored so we will skip over JumpPlayEvents. Now that we have this, could eliminate InReturn and InRealign.

7.9.3.2 nextEventFunction

Returns the function name associated with the next event. We subclass NextEventVariableType for the getTrackValue logic.

7.9.3.3 nextLoop

The number of the next loop if we're in loop switch mode. Loops are numbered from 1. Returns zero if we're not loop switching.

7.9.4 Loop Modes

7.9.4.1 effectiveFeedback

The value of the feedback currently being applied. This will usually be either the Feedback or Secondary Feedback control values depending on which is being used. It will always be zero if we're in Replace, Insert or another mode that does not bring forward any content from the previous loop.

7.9.4.2 inHalfspeed

True if half-speed is enabled. From version 2.2 onward this is true only if the value of speedToggle is -12.

7.9.4.3 inMute

True if playback is muted. This usually means that we're also in Mute mode, but if Overdub is also on, mode will be Overdub. Note also that this tests the isMute flag which can be on for other reasons than being in Mute mode.

7.9.4.4 inOverdub

True if overdub is enabled. Note that this doesn't necessarily mean that the mode is overdub, only that overdub is enabled when we fall back into Play mode.

7.9.4.5 inPause

True if we're in Pause or Pause mode. This is available because the "mode" parameter is not always set to Pause. Once case is if Pause and Overdub are on at the same time mode will be Overdub (I think this is the only case).

7.9.4.6 inRealign

True if we're realigning. This similar to a mode, but it is indicated by having a Realign event scheduled.

7.9.4.7 inReturn

True if we're in "return" mode. This is a special minor mode that happens after a loop switch with SwitchDuration=OnceReturn, SwitchDuration=SustainReturn, or the RestartOnce function. It is indicated by the presence of a pending Return event.

7.9.4.8 inReverse

True if reverse is enabled.

7.9.4.9 isRecording

True any form of recording is being performed. Note that this does not necessarily mean you are in Record mode, you could be in Overdub, Multiply, Insert, etc.

7.9.4.10 mode

This variable will contain the name of the current major mode. The possible values are:

7.9.5 Speed and Pitch

7.9.5.1 rate

Speed shift, expressed as a scale degree. This is provided for backward compatibility with pre-2.2 scripts. This is now the same as the value of the speedStep track control.

7.9.5.2 rawPitch

Total pitch shift, expressed as a float times 1000000.

7.9.5.3 rawSpeed

Total speed shift, expressed as a float times 1000000.

7.9.5.4 speedToggle

The current amount of toggled speed shift being applied to the track. If this is -12 it is the same as inHalfspeed being true.

7.9.5.5 speedSequenceIndex

The current index into the speed sequence for the track. The index starts at zero and has a maximum value of one less than the length of the speed sequence.

This is one of the few variables that may be set in scripts to change the sequencnce position.

7.9.5.6 pitchSequenceIndex

The current index into the pitch sequence for the track. The index starts at zero and has a maximum value of one less than the length of the pitch sequence.

This is one of the few variables that may be set in scripts to change the sequencnce position.

7.9.6 Track State

7.9.6.1 globalMute

True if the track will be unmuted when Global Mute mode is over.

7.9.6.2 outSyncMaster

The number of the track operating as the output sync master, -1 if there is no master.

7.9.6.3 solo

True if the track will be unmuted when Global Mute mode is over.

7.9.6.4 track, trackNumber

The number of the current track. The first track is 1.

7.9.6.5 trackCount

The number of tracks configured.

7.9.6.6 trackSyncMaster

The number of the track operating as the track sync master, -1 if there is no master.

7.9.7 Generic Sync

7.9.7.1 syncAudioFrame

The actual Loop frame at the last pulse. The difference between this and syncPulseFrame is the amount of drift (after wrapping).

7.9.7.2 syncBar

The current bar count. This will be the same as syncOutBar, syncInBar, or syncHostBar depending on the SyncMode of the current track.

7.9.7.3 syncBeat

The current bar relative beat count. This will be the same as syncOutBeat, syncInBeat, or syncHostBeat depending on the SyncMode of the current track.

7.9.7.4 syncCorrections

The number of sync drift corrections that have been performed since the sync tracker was locked.

7.9.7.5 syncCyclePulses

The number of external sync pulses counted during recording.

7.9.7.6 syncDealign

The number of frames the current track is dealigned from the sync tracker for this track.

7.9.7.7 syncDrift

The current amount of drift, positive or negative.

7.9.7.8 syncDriftChecks

The number of sync drift checks that have been performed in this loop since it was recorded.

7.9.7.9 syncLoopFrames

The length of the sync tracker loop (external loop) in frames.

7.9.7.10 syncPreRealignFrame

The loopFrame prior to the last Realign.

7.9.7.11 syncPulse

The number of sync pulses we have received at the moment in the external loop.

7.9.7.12 syncPulseFrames

The length of a sync pulse in frames. The value is a float. Since tracks may have different sync sources, the pulse width may also be different for each track.

7.9.7.13 syncPulses

The total number of sync pulses in the external loop.

7.9.7.14 syncRawBeat

The current absolute beat count. This will be the same as syncOutRawBeat, syncInRawBeat, or syncHostRawBeat depending on the SyncMode of the current track.

7.9.7.15 syncTempo

The current sync tempo. For Sync=Out this is the tempo we calculated. For Sync=In this is the tempo we're smoothing from the external source. For Sync=Host this is the tempo reported by the host.

7.9.8 Out Sync

7.9.8.1 syncOutBar

The current bar count maintained by the internal clock. This is calculated from the raw beat count, modified by the effective beatsPerBar.

7.9.8.2 syncOutBeat

The current beat count maintained by the internal clock, relative to the bar.

7.9.8.3 syncOutRawBeat

The current raw beat count maintained by the internal clock. This will be zero if the internal clock is not running.

7.9.8.4 syncOutSending

"true" if we are currently sending MIDI clocks, "false" if not.

7.9.8.5 syncOutStarted

"true" if we have send a MIDI Start message, "false" if not.

7.9.8.6 syncOutStarts

The number of MIDI Start messages we've sent since the last time we were stopped.

7.9.8.7 syncOutTempo

The tempo of the internal clock used for out sync. This is the same value returned by "tempo" but only if the current track is in Sync=Out or Sync=OutUserStart.

7.9.9 MIDI Sync

7.9.9.1 syncInBar

The current bar count derived from the external MIDI clock.

7.9.9.2 syncInBeat

The current beat count derived from the external MIDI clock, relative to the bar.

7.9.9.3 syncInRawBeat

The current beat count derived from the external MIDI clock.

7.9.9.4 syncInReceiving

True if we are currently receiving MIDI clocks.

7.9.9.5 syncInStarted

True if we have received a MIDI start or continue message.

7.9.9.6 syncInTempo

The tempo of the external MIDI clock being received. This is the same value returned by "tempo" but only if the current track SyncMode is In, MIDIBeat, or MIDIBar.

7.9.10 Host Sync

7.9.10.1 syncHostBar

The current bar count given by the host.

7.9.10.2 syncHostBeat

The current beat count given by the host, relative to the bar.

7.9.10.3 syncHostRawBeat

The current beat count given by the host.

7.9.10.4 syncHostReceiving

True if we are currently receiving MIDI clocks from the host. Synchronizer has always returned false here, I guess because we make MIDI passing through the host look like MIDI In sync rather than host sync.

7.9.10.5 syncHostStarted

True if we have received a MIDI start or continue message from the host. Like syncHostReceiving we've always returned false here.

7.9.10.6 syncHostTempo

The tempo advertised by the plugin host.

7.9.11 Miscellaneous

7.9.11.1 blockFrames

The number of frames in one audio interrupt block.

7.9.11.2 configurationDirectory

Base directory where Mobius configuration is saved. Typically c:\Program Files\Mobius 2 on Windows and /Library/Application Support/Mobius 2 on Mac.

7.9.11.3 installationDirectory

Base directory where Mobius has been installed. Typically c:\Program Files\Mobius 2 on Windows and /Applications/Mobius 2 on Mac.

7.9.11.4 noExternalAudio

When set disables the pass through of audio received on the first port. This is used in the unit tests that do their own audio injection, and we don't want random noise coming in from the sound card to pollute it.

7.9.11.5 sampleFrames

The number of frames in the last sample we played.

8 Examples

8.1 Sustain Scripts

8.2 Long Press Scripts