Gig Performer Notes

Andrew Hunt

Contents

Gig Performer Scripts

Introduction

This page steps through the basics of writing GP Scriptlets. It’s written as a programmer who’s learning to do good things with GP.

What this is NOT…

The rig for the development and testing of this page:

GPScript for Gig Performer 4.5
The definitive guide to GPScript from the folks who created Gig Performer
GPScript for Gig Performer 4.0
The guide for GPScript in GP 4.0 (older product version)
GP 4.X manual on GPScript
This section of the GP4.X User Manual covers how to use scripts within GP.
GP 4.0 List of Callbacks / Events
400+ events including those for the Rackspace, MIDI, Widgets, Plugins, Scriptlets, Generators, OSC Messages, Playhead, Global state and Global events.
GP 4.0 List of Functions
Long list of built-in GP functions.

Learning the Basics

The GP Language Manual explains the basics of programming GPScript.

Term Quick Description
GPScript Special purpose programming language to customize Gig Performer
Event Something that is happened like a MIDI note, plugin parameter change, GP change. Handled by a Callback
Callback This is the code you write saying what to do what a particular event happens.
Script Types Rackspace scripts operate in a rackspace.
Song scripts are associated with a specific song.
Gig file scripts are “top-level” scripts operate across the entire GP application.
Scriptlet scripts allow you to create a custom plugin in a rackspace, for example, to process MIDI events.
Statements These are basic programming instructions for: <li> variables and assignments, <li> for loops, <li> while loops, <li> if-then-elsif-else-end statements, and <li> select statements.
Functions GPScript has hundreds of built-in functions plus you can write your own functions. What’s a function? In programming, you pass values (inputs) to a function. The function processes those values and can return another value.
Operators The “mathemtatical” capabilities of the script.
Types Scripts handle different “types” of data. There are strings (roughly, sets of letters), numbers (integer and double), booleans (for true and false), arrays. It’s best to read the GP documentation on all the types.

Simple Developer Setup for a Scriptlet Script

Step 1: Insert a Scriptlet

On a rackspace, insert a Scriptlet plugin. It’s under “MIDI Processing and Monitoring” in the insertion menu.

Insert a Scriptlet

Step 2: Rename the Scriptlet

Renaming the scriptlet indicate it’s function. It’s optional but recommended to make your rackspace easier to follow.

Rename a Scriptlet

Rename a Scriptlet

Step 3: Wire the Scriptlet

Connect “MIDI In” to the scriplet.

Optionally, connect the output to an instrument plugin and wire it to Audio Output. This just makes development easier.

Wired Scriptlet

Step 4: Optional MIDI Monitors

Since Scriptlets function to process MIDI, it’s sometimes useful to add a GP MIDI Monitor to the show the Input and Output of the scriptlet.

The “MIDI Monitor” can be inserted from the ““MIDI Processing and Monitoring” (same as for Scriptlet).

Scriptlet Wired with MIDI Monitors

Set 5: Open the Scriptlet and Monitors

Double click the scriptlet plugin and both the MIDI monitors.

In this screenshot, I’ve played a single MIDI note just to check things.

Rackspace with the plugins opened

Step 6: Copy and Compile the Hello World Script

Click the edit button in the scriptlet editor.

Copy the Hello World code below into the Scriptlet editor.

Hint: click the Copy icon in the code panel to below to copy the code to your clipboard. Just saves time and hassle.

Initialization
    SetInfoMessage("Hello World Scriptlet!")
    SetDisplayMessage("Hello World Scriptlet by AH")
End

Click the big green “Compile” button. Check that you see “Compilation successful” in the console.

Compiled Hello World script

Step 7: Hello World Initialization Event

This Hello World script handles a single “Initialization” “event”. Initialization happens just once when a rackspace is initially loaded. It also happens the Scriptlet is Compiled (when you press that big green button).

What are we Initializing? We’re initializing the scriptlet itself.

(1) SetDisplayMessage("Hello World Scriptlet by AH")

This sets the text at the bottom of the Scriptlet editor window.

Deskew - the creators of GP - often include a copyright message there. But you can put any other text that might be useful to your user.

Display Message

(2) SetInfoMessage("Hello World Scriptlet!")

This sets the text to display when the user clicks on the “Info” (I) button at the top-right of the Scriptlet editor.

Display Message

Understanding Events

A GPScript is all about “Events” which is programming-speak for something has happened.

For example, MIDI events include note pressed or released, pedal on or off, volume change and many more.

GP includes all these MIDI events and then adds events such as Initialization, rackspace activation/deactivation, variation changes and more. You can read more about GP events in the GP documentation.

In shorts, a GPScript is a set of “event handlers”. Again, that’s programming-speak for saying what to do each time a particular event happens.

In the Hello World script, it handles a single event – the “Initialization” event which happens any time the Scriptlet is started or restarted. This is a GP event (not a MIDI event).

The event is “declared” with the “Initialization” statement, followed by instructions of what to do, and closed with the “End” statement.

Initialization
    ...
End

Note: here ... is short-hand for “stuff goes here”.

In developer-speak, this is a “block”. By convention, developers like to indent the code within the block. This makes things easier to read. It’s not necessary but does help to reduce errors and when working with bigger scripts.

This simple example intercepts all MIDI Note events (note on and note off). It prints the event to the logger the passes on the note event. T

On NoteOnEvent(m : NoteMessage)
   Print(m)
   SendNow(m)
End

The GP List of Callbacks lists 100s of available events that you can catch and process in your scripts. (We’ll talk more about Print and Send later.)

Debugging with the Compiler

Things go wrong when coding - always.

Your first line of defense against bugs is the Compiler. Clicking “Compile” does a lot of checks for errors.

For example, can you spot the error in this script?

Initialisation
    // Comment here
End

The Compile error tells me that ‘Initialisation’ is not recognised. The reason is that this is the English spelling (“s” not “z”).

Here’s the GP compiler error which is (much) harder to understand. Fortunately, it highlights the incorrect line. If you’re stuck understanding a Compiler error then try a Google search. Or, go directly to the experts in the GP Community. But please do a search first in case your issue is already answered.

Scriptlet (Scriptlet) -  - Syntax Error in "Main": Line 1, Col 1: Unexpected or unrecognized token: 'Initialisation'
Extraneous input 'Initialisation' expecting {<EOF>, Var, Initialization, On, Function, Builtin}

Debugging with Print()

A Compiler can’t catch everything. Sometimes your code will run but won’t do what you expect. That’s when you need Print() and the Script Logger window.

First, from the GP application “Window” menu, select “Show Script Logger”. The shortcut is “⇧⌘S” on MacOS and “???” on Windows.

Next, load and compile this simple script. This is will send a simple debug message to the Script Logger.

Initialization
    Print("Send a debug message to the Script Logger")
End

Debug message in the Script Logger

Printing the Date & Time

Let’s say you want to know the Date and/or Time that something happens. GPScript provides the ClockTime and FormatTime.

ClockTime returns a Double with the current system time in milliseconds.

FormatTime converts the ClockTime to a human-readable string that you can print. But it needs to be told the format. GP uses the C-language strftime which supports about 40 different date / time items that you can put into the formatted output. Each item is the percent character "%" followed by a letter.

    // Print the date
    > Print(FormatTime(time, "%Y-%m-%d"))
    2022-12-29

    // Print the time
    > Print(FormatTime(time, "%H:%M:%S"))
    09:28:19

    // Print the date and time with some around it
    > Print(FormatTime(time, "This happened at %H:%M:%S on %A %Y-%m-%d"))
    This happened at 22:29:59 on Thursday 2022-12-29

Here are some of the more useful codes with the full list available here. Beware, it tends to use US formats rather than International formats.

Code Description Examples
%F Short YYYY-MM-DD date, equivalent to %Y-%m-%d 2023-04-01
%Y Year with 4 digits 2022
%y Last 2 digits of the year 22
%m Month as a decimal number (01-12) 08
%b Abbreviated month name Aug
%d Day of the month, zero-padded (01-31) 07
%a Abbreviated weekday name Thu
Code Description Examples
%T Time with HH:MM:SS) format equivalent to %H:%M:%S 14:55:02
%r 12-hour clock time 02:55:02 pm
%R 24-hour HH:MM time, equivalent to %H:%M 14:55
%H Hour in 24h format (00-23) 14
%I Hour in 12h format (01-12) 02
%p AM or PM designation PM
%M Minute (00-59) 55
%S Second (00-61) 02
%z Time offset from UTC in timezone (1 minute=1, 1 hour=100) +1000
%Z Timezone name or abbreviation GMT

Custom Date & Time Functions

Here are functions you can modify and use whenever you need to print the current date and/or time. The PrintableTimeMsec() function does a bit of extra work to append milliseconds to the time which is useful with the precise timing of MIDI events. This will print something like 2022:12:29 23:47:38.450.

Function PrintableDate() Returns String
    var format : String = "%Y:%m:%d"
    result = FormatTime(ClockTime(), format)
End

Function PrintableTime() Returns String
    var format : String = "%Y:%m:%d"
    result = FormatTime(ClockTime(), "%H:%M:%S")
End

Function PrintableTimeMsec() Returns String
    var 
        format : String = "%H:%M:%S"
        time : Double = ClockTime()
        hms : String = FormatTime(ClockTime(), format)
        timeStr : String = DoubleToString(time, 0)
        timeStrLen : Integer = Length(timeStr)
        msec : String = CopySubstring(timeStr, timeStrLen-3, 3)
    result = hms + "." + msec
End

Initialization
    Print(PrintableDate() + " " + PrintableTimeMsec())
End

Unicode?

Unicode is not supported yet. (Hint: It would be a good thing to have)

Some testing indicates that the basic European characters are supported (0x0000-0x3FF in Unicode).

This excludes many languages – think Arabic, Chinese, Japanese, Hindi, Hewbrew, Cyrillic and more.

It also excludes Emojis 😱

Who wouldn’t want emojis in their GP plugins? 🎹🎶🎸😀