QLab Manual Typewriter

This workspace simulates a manual typewriter, complete with typing sound effects, a line ending bell, and a carriage return, using a Text cue and some scripting. This chapter and its scripts were written using QLab 5, but they can be adapted for QLab 3 by replacing the references to application id "com.figure53.qlab.5" with application id "com.figure53.qlab.3" and by replacing references to Text cues with references to Titles cues. To adapt to QLab 4, replace references to application id "com.figure53.qlab.5" with application id "com.figure53.qlab.4". Downloadable examples are provided for all three versions of QLab.

Here it is in action:

How It Works

There is one Text cue numbered “TYPE” in the workspace. This should be initially set up with a single space in the Text tab, formatted to taste with a suitable monospaced font, color, and size. The example uses Courier New in white at 36 points. The justification should be set to left and the width should be set to a fixed size e.g. 1024 (not auto). The line spacing should be set to 1, or whatever looks best based on your font choice.

There is a Relative Fade cue numbered “SCROLL” targeting cue “TYPE” which affects the movement of the text block on a carriage return.

Each typewriter cue is a Script cue, with the text to be typed stored in its notes field. At the top of the Script cue are settings which can be edited by the user to give a range of different typing effects:

  • typing speed
  • limits for random speed variation
  • approximate number of characters per line
  • initial first line screen position
  • movement of the text block when a carriage return occurs

Here’s the first block of the script:

set thespeed to 0.04         -- gap between typed characters in seconds
set theRange to 0.02         -- random variation between typed characters in seconds
set charPerLine to 45        -- Approximate Number of characters per line
set theScroll to 18          -- y translation of the text block on a carriage return
set theHomePosition to -290  -- Initial y position of the first line of text

This is the setup used in cue “3” in the example workspace. It results in very fast typing at around 300 characters per minute (one every 0.2 seconds), with a random range of plus or minus 0.02 seconds. The time between characters is therefore a random fraction of a second between .02 and .06 seconds. The position of the first line of typing on the screen is set by the value stored in the variable theHomePosition. Here, it is set to -290 which places it close to the bottom of the screen. The charactersPerLine variable is set to a conservative target value of 45. Eight characters before this character count is reached, the bell rings and typing continues until the next space. At that point, a carriage return occurs and the first letter of the next word begins the next line of type.

When the carriage return occurs, the “SCROLL” Fade cue performs a relative y translation of the Text cue using the value stored in the variable theScroll to determine the size of the translation. For the normal typewriter behavior in which the paper rises by one line on each character return, this should be set to approximately half the font height in pixels. Since we’re using 36 point type, theScroll is set to 18 to get a single line rise.

Cue “1” in the example uses this setup:

set thespeed to 0.08      -- gap between typed characters in seconds
set theRange to 0.04      -- random variation between typed characters in seconds
set charPerLine to 45     -- Number of characters per line
set theScroll to 0        -- y translation of the text block on a carriage return
set theHomePosition to 0  -- Initial y position of the first line of text

This generates typing at about half the speed of cue “3”, a character every 0.04 to 0.12 seconds. The variables theScroll and theHomePosition are both set to 0. This places the first line in the middle of the screen. On every carriage return the text block re-centers itself vertically. The effect of this is to move the text block up about half a line. When the text is completed, it will be precisely centered on the screen. This is an effective setting for short blocks of text where a full line of movement might be visually disruptive.

Cue “2” uses these settings:

set thespeed to 0.2       -- gap between typed characters in seconds
set theRange to 0.08      -- random variation between typed characters in seconds
set charPerLine to 45     -- Number of characters per line
set theScroll to 18       -- y translation of the text block on a carriage return
set theHomePosition to 0  -- Initial y position of the first line of text

This arrangement types slowly and deliberately in the center of the screen and raises the text block one line on each carriage return.

The second half of the script, beneath the do not edit line, is:

---Don't change anything below this line---------
tell application id "com.figure53.QLab.5" to tell front workspace
	set theCue to (last item of (cues whose running is true and q type is "script"))
	set the translation y of cue "TYPE" to theHomePosition
	set the cue target of cue "SCROLL" to cue "TYPE"
	set the translation y of cue "SCROLL" to theScroll
	stop cue "TYPE"
	set thetext to notes of theCue
	set thecount to number of characters in thetext
	set the text of cue "TYPE" to " "
	set thetype to ""
	start cue "TYPE"
	set theEOLflag to false
	set theLineCharCount to 0
	repeat with eachChar from 1 to thecount
		set thevar to (random number from (-theRange) to theRange)
		set thechar to text item eachChar of thetext
		if thechar is linefeed then
			set theEOLflag to true
			set thechar to " "
		end if
		set thetype to thetype & thechar
		set theLineCharCount to theLineCharCount + 1
		delay thespeed + thevar
		if theLineCharCount = (charPerLine - 8) then
			start cue "BELL"
			set theEOLflag to true
		end if
		if the theEOLflag is true then
			if thechar is " " then
				start cue "CR"
				set thetype to thetype & return
				start cue "SCROLL"
				set the live text of cue "TYPE" to thetype
				set theEOLflag to false
				set theLineCharCount to 0
				delay 0.5 + thevar
			end if
		end if
		set the live text of cue "TYPE" to thetype
		if thechar is space then
			start cue "SPC"
		else
			start cue "SND"
		end if
	end repeat
end tell

The script begins by identifying itself. It does this using a nifty line of script:

set theCue to (last item of (cues whose running is true and q type is "script"))

This sets the variable theCue to the id of the script cue that is currently running. Thereafter we can refer to the cue using just this variable:

set thetext to notes of theCue 

The script then sets the scroll and home position of the text block, stops cue “TYPE” in case it is currently running, and clears its text back to a single space.

It then sets a boolean variable theEOLflag to false. This will become true when the bell rings eight characters before the end of the line or if an explicit new line is encountered in the notes.

Next, it sets the character count for the line to 0 and sets a variable theType to an empty string. Later on, this variable will store the current state of the text block.

Next comes the repeat loop of the script. This steps through each character in the notes of the running Script cue, now stored in a variable thetext.

A random variation is calculated from theRange variable and stored in theVAR.

If the current character is a linefeed, i.e. a new line that is deliberately included in the text in the notes of theCue, then theEOLflag is set to true and theChar is set to space.

The variable theType is updated to include the current character after the existing text, and the lineCharCount variable is incremented by 1.

A random delay then occurs calculated from theSpeed plus theVAR.

Then, if the lineCharCount variable is eight characters less than the value of charPerLine, the Audio cue numbered “BELL” is started, and theEOLflag is set to true.

If theEOLflag has been set to true and the current character is a space, the Audio cue numbered “CR” is started, a return is added to the end of the text stored in theType, the fade cue numbered “SCROLL” is started to scroll the text block, and the live text of the cue numbered “TYPE” is set to the text stored in theType.

Setting the live text of a Text cue sets the text of the cue temporarily (until the cue is stopped) and does not mark the workspace as edited.

If the current character is a space, the Audio cue numbered “SPC” is started. If it is any other character, the Start random Group cue numbered “SND” is started. This cue will play one of the Audio cues inside the Group at random. Each child cue of the Group is a recording of a different key being hit. Using a randomized collection of these recordings stops the key sound from being boringly repetitive.

The repeat loop continues until all the characters in the notes of theCue have been processed.