Captain Slog

This is a simple workspace which logs times into a text file on the Desktop called “SHOW LOGGER”. You can copy and paste the example cues into your own show workspaces.

The scripts in this example were written in QLab 5 but can be used in QLab 3 or QLab 4 by replacing any reference to application id "com.figure53.QLab.5" with either application id "com.figure53.QLab.3" or application id "com.figure53.QLab.4". Downloadable examples are provided for all three versions of QLab.

Here it is in action:

How it works

The workspace uses Script cues to log times, which can be added anywhere in a show’s cue list. The scripts store their log data in the notes of a Script cue numbered “WRITE” and then start that cue. Cue “WRITE” appends the contents of its notes field to a text file on the desktop named “SHOW LOGGER”.

The scripts in this example make extensive use cue notes to pass values from one script to another. If we were writing a conventional computer program, we could modularize our code by separating each task into a function or subroutine. One function might handle writing to a file, another would convert seconds to an HH:MM:SS string, etc., and we’d pass data between these chunks of code using variables. Script cues in QLab, however, only preserve variables within themselves; there is no straightforward way to have blocks of AppleScript shared between Script cues.

However, by using the notes field of cues to hold variables, we can treat individual Script cues as reusable blocks of code. The main disadvantage of working this way is that these Script cues become interdependent and cannot function without each other, and moving them between workspaces can be cumbersome. This isn’t hard to get around, and it comes with enough benefits that it’s worth the effort.

The script for cue “WRITE” is:

set mycue to "WRITE"
tell application id "com.figure53.QLab.5" to tell front workspace
  set this_data to notes of cue mycue & return
  set target_file to (((path to desktop folder) as string) & "SHOW LOGGER")
  set append_data to true
  try
    set the target_file to the target_file as string
    set the open_target_file to open for access target_file with write permission
    if append_data is false then set eof of the open_target_file to 0
    write this_data to the open_target_file starting at eof
    close access the open_target_file
    
    return true
  on error
    try
      close access file target_file
    end try
    return false
  end try
  
end tell

Logging

The first script in the example workspace writes the name of the show (the name of the workspace) to the log file via cue “WRITE”. This Script cue can be copied to the top of any cue list in which you want to use this logging system.

tell application id "com.figure53.QLab.5" to tell front workspace
  set themessage to "----------------------------------------------------------------------" & return & "SHOW FILE: " & q number of front document of application id "com.figure53.QLab.5" & return as string
  set the notes of cue "WRITE" to themessage
  start cue "WRITE"
  
end tell

The example workspace then has four cues numbered “LOG1” to “LOG4”. These are the cues that create a log entry at the time that they are run. You can have as many of these as you need. The example is set up for a two-act play with intermission (interval) but it can easily be expanded for a three-act play or whatever your specific situation calls for. Later, we’ll look at how we can adapt the example workspace for a music festival.

Here’s the script for cue “LOG1”

set mycue to "LOG1"
set themessage to "Curtain Up"
tell application id "com.figure53.QLab.5" to tell front workspace
  set notes of cue mycue to (do shell script "date +%s") as integer
  set thedate to current date
  set this_data to (thedate as string) & space & themessage & return
  set the notes of cue "WRITE" to this_data
  start cue "WRITE"
end tell

The script needs to reference the number of the Script cue that contains it, so be sure to edit the script to set myCue to the number of the Script cue.

The variable themessage is set to the text you want to write to the file along with the timestamp.

The script then gets the current time in epoch seconds and stores that in the notes of its own cue.

On Unix systems, of which macOS is one variety, the Epoch time is defined as the number of seconds since midnight at the start of January 1, 1970. While this is quite esoteric, it turns out to be a pretty convenient way to keep track of time.

The epoch seconds will be used later on when it’s time to run some time calculations. This script also gets the current date as a conventional date and time string, e.g. Wednesday, 29 November 2023 at 15:42:11, and writes this to the file immediately along with themessage. This means that in the event of a power failure or other loss of data, there is still a record of the timestamps logged up to that point in your show.

To log curtain up and down times for act one and act two, copy the cues numbered “LOG1” through “LOG4” into your workspace and place them at the relevant spot in your cue list. For example, place “LOG2” in a Timeline Group together with house lights up after Act 1. Place “LOG3” in a Timeline Group together with the curtain up music for Act 2, etc.

Calculations

At the end of the show, we run some scripts to summarize the show and complete the log record for that performance.

All the calculation scripts run in a Timeline Group with sufficient pre-waits to allow the previous script to complete. The file writing is fast enough that one second between scripts is generally sufficient.

The cue numbered “LOGA” calculates the running time of Act One with this script:

set mycue to "LOGA"
tell application id "com.figure53.QLab.5" to tell front workspace
  try
    set mystring to q name of cue mycue
    repeat while the length of mystring is less than 50
      set mystring to " " & mystring
    end repeat
    set thesecs to (notes of cue "LOG2") - (notes of cue "LOG1")
    set the notes of cue "CALC1" to thesecs
    start cue "CALC1"
    delay 0.2
    set the notes of cue mycue to the notes of cue "CALC1"
    set the notes of cue "WRITE" to return & mystring & ": " & notes of cue mycue & return
    start cue "WRITE"
  end try
end tell

This will give us the duration of act one measured in seconds by subtracting the time saved in the notes of cue “LOG1” from the time saved in the notes of cue “LOG2”. To convert this to the more human-readable H:MM:SS format, the script writes the duration in seconds into the notes of a script cue numbered “CALC1” and then starts that script:

set mycue to "CALC1"
tell application id "com.figure53.QLab.5" to tell front workspace
  try
    set thesecs to notes of cue mycue
    set theHours to (thesecs div 3600)
    
    set theRemainderSeconds to (thesecs mod 3600) as integer
    set theMinutes to (theRemainderSeconds div 60)
    set theRemainderSeconds to (theRemainderSeconds mod 60)
    
    if length of (theHours as text) = 1 then
      set theHours to "0" & (theHours as text)
    end if
    
    if length of (theMinutes as text) = 1 then
      set theMinutes to "0" & (theMinutes as text)
    end if
    if length of (theRemainderSeconds as text) = 1 then
      set theRemainderSeconds to "0" & theRemainderSeconds as text
    end if
    set notes of cue mycue to (theHours & ":" & theMinutes & ":" & theRemainderSeconds)
  end try
end tell

Following that logic, this calculation will give us the playing time of a two-act play without intermission:

((notes of cue "LOG2") - (notes of cue "LOG1")) + ((notes of cue "LOG4") - (notes of cue "LOG3"))

In the downloadable example, this is exactly what cue “LOGP” does:

set mycue to "LOGP"
tell application id "com.figure53.QLab.5" to tell front workspace
  try
    set mystring to q name of cue mycue
    repeat while the length of mystring is less than 50
      set mystring to " " & mystring
    end repeat
    set thesecs to ((notes of cue "LOG2") - (notes of cue "LOG1")) + ((notes of cue "LOG4") - (notes of cue "LOG3"))
    
    set the notes of cue "CALC1" to thesecs
    start cue "CALC1"
    delay 0.2
    set the notes of cue mycue to the notes of cue "CALC1"
    set the notes of cue "WRITE" to return & mystring & ": " & notes of cue mycue & return
    start cue "WRITE"
  end try
  
end tell

Adding more calculations

You can include as many calculations as you need for the report.

Let’s adapt the example workspace to work for a music festival presenting five bands per day. We’ll want to log each band’s stage time and the duration of the changeovers between bands.

First, we’ll create pairs of cues for the start and finish times of each band numbered “LOG1S” and “LOG1F” (for the first band) through “LOG5S” and “LOG5F” (for the fifth.)

To save ourselves a lot of script editing (and if this was a 3-day festival, it would be a lot of editing!), we’ll create five Memo cues numbered “BAND1” - “BAND5” and enter the bands’ names there:

Band names

Once that’s done, cues “LOG1S” - “LOG5S” can use the following script to grab band names from the Memo cues:

set mycue to "LOG1S"
tell application id "com.figure53.QLab.5" to tell front workspace
  set themessage to q list name of cue "BAND1"
  set notes of cue mycue to (do shell script "date +%s") as integer
  set thedate to current date
  set this_data to (thedate as string) & space & themessage & return
  set the notes of cue "WRITE" to this_data
  start cue "WRITE"
end tell

You’ll need to change line 1 to the correct cue number and line 3 to the correct band number for each of the LOG cues.

Cues “LOG1F” - “LOG5F” can do the same thing using this script:

set mycue to "LOG1F"
set themessage to "OFF"
tell application id "com.figure53.QLab.5" to tell front workspace
  set notes of cue mycue to (do shell script "date +%s") as integer
  set thedate to current date
  set this_data to (thedate as string) & space & themessage & return
  set the notes of cue "WRITE" to this_data
  start cue "WRITE"
end tell

Again, change line 1 to the correct cue number and line 3 to the correct band number for each of the LOG cues.

To report the amount of time that, say, band number 3 was on stage, we’ll create a Script cue with number “LOGB3” and name “THE URBAN AXETHROWERS” and use this script:

set mycue to "LOGB3"
tell application id "com.figure53.QLab.5" to tell front workspace
  try
    set mystring to q list name of cue "BAND3"
    repeat while the length of mystring is less than 50
      set mystring to " " & mystring
    end repeat
    set thesecs to (notes of cue "LOG3F") - (notes of cue "LOG3S")
    set the notes of cue "CALC1" to thesecs
    start cue "CALC1"
    delay 0.2
    set the notes of cue mycue to the notes of cue "CALC1"
    set the notes of cue "WRITE" to return & mystring & ": " & notes of cue mycue & return
    start cue "WRITE"
  end try
end tell

To make that work for all five bands, cues “LOGB1” - “LOGB5” all use the same script, changing line 3 to the cue number of the relevant Memo cue.

To calculate the changeover time between the first two bands, we create a Script cue with number “LOGC12” and name “Changeover Band 1 to 2” and use this script:

set thesecs to (notes of cue "LOG2S") - (notes of cue "LOG1F")

If we need to report the total time that all bands were on stage, we use a cue numbered “LOGTOT” and named “Total Performance Duration” and change the reporting script to use this calculation:

set thesecs to ((notes of cue "LOG1F") - (notes of cue "LOG1S")+((notes of cue "LOG2F") - (notes of cue "LOG2S")+((notes of cue "LOG3F") - (notes of cue "LOG3S")+((notes of cue "LOG4F") - (notes of cue "LOG4S")+((notes of cue "LOG5F") - (notes of cue "LOG5S"))

The complete cue list looks like this:

Band logs

The report generated by these scripts look like this:

Band report

The cues that generate the reports and the cues “WRITE” and “CALC1” can be anywhere in the workspace, including in a separate cue list if you’d like to keep them out of the way. If you were going to use this extensively, you could put the whole of this list in a separate logging cue list in your template workspace, and then just cut and paste the LOG cues into the main cue list as needed. Alternately, you could use Start cues in the main cue list to trigger the Script cues as needed.