This is an "external script" - see QLab Scripts and Macros
(* Make cues from a text file: add cues from a tab-delimited text file to a workspace in QLab based on the data in the file;
see second & third display dialogs for further explanation
This script is not designed to be run from within QLab!
v0.0: 06/10/09 Rich Walsh (very early, barely-written, proof of concept)
v0.5: 06/10/09 Starting to finish basic shape; have cracked groups & levels (I think)
v0.9: 07/10/09 Fixed a couple of mistakes; finished creating all commands
v0.9.1: 12/10/09 Snow Leopard can't "get running", so rewrote a sequence; also added some more instructions and the option to set
a common root path for media; corrected some more mistakes; changed ETA
v0.9.2: 16/10/09 Now "tested" in Snow Leopard; expanded makeNiceT for hours; general tidying; updates for QLab 2.2.5; new ETA figures
v0.9.3: 27/10/09 Added MSC translation; new note about file targets
v1.0: 11/01/10 Added better text-cleaning routine; "start value" is read-only, so fixed that; byte combo (and related) origin offset; corrected minor typos;
added tell front workspace for elegance; wrapped text for better wiki experience; implemented dialogTitle for cross-script pillaging
<<< Last tested with: QLab 2.2.6; Mac OS 10.5.8 & 10.6.2 >>>
<<< A LITTLE DISCLAIMER: This was quite a complex bit of work for me, so I make no guarantees whatsoever that it will work for you: if it does, use it;
if it doesn't, I'd like to know, but I may choose not to do anything about it... >>>
***CUSTOMISATION***
If you would prefer not to use the terms from QLab's AppleScript dictionary it is relatively painless to personalise this script
(although you should record what you've done so you can repeat it if the script ever gets updated,
and please DON'T release your private version into the wild!).
To change the strings that you need to use in the first row of your text file to associate a column with a property,
edit the relevant entry in the "set acceptableColumnHeaders" line, eg: change "continue mode" to "f/on" if you prefer
(just don't use commas - they identify level-setting columns).
To change the strings that you need to use in the rows to call a QLab constant, edit the contents of the relevant
"set constantsXXX" line, eg: change "set constants10_continue_mode" entries from "do_not_continue", "auto_continue" & "auto_follow"
to "no", "a/c" & "a/f" if you prefer. *)
-- ###FIXME### See 2x embedded comments in script
-- ###FIXME### QLab throws an error when trying to get/set smpte format for an MSC Cue (checked in 2.2.6 Build 1084)
-- ###FIXME### QLab and/or the "script runner" is, generally, increasingly unresponsive to scripts the more cues there are in a workspace
-- ###FIXME### Review dialogs in light of this (especially ETA)
-- ###ADD### Skip level setting for rows beyond number of audio input channels (?)
-- ###ADD### Maybe one day make it possible to make cuelists (NB: simpling changing the mode of a Group Cue to cue_list _doesn't_ do it!)
-- Declarations
global dialogTitle
set dialogTitle to "Make cues from a text file"
global currentTIDs
set currentTIDs to AppleScript's text item delimiters
set acceptableColumnHeaders to {"type", "q number", "q name", "notes", "cue target", "file target", "pre wait", "duration", "post wait", "continue mode", ¬
"armed", "midi trigger", "midi command", "midi byte one", "midi byte two", "timecode trigger", "wall clock trigger", "wall clock hours", "wall clock minutes", ¬
"wall clock seconds", "mode", "sync to timecode", "sync mode", "smpte format", "mtc sync source name", "ltc sync channel", "patch", "start time", "end time", ¬
"loop start time", "loop end time", "loop count", "infinite loop", "guarantee sync", "integrated fade", "fade mode", "stop target when done", "auto stop", "layer", ¬
"full screen", "preserve aspect ratio", "opacity", "translation x", "translation y", "rotation", "scale x", "scale y", "scale locked", "custom rendering", "do opacity", ¬
"do translation", "do rotation", "do scale", "command", "channel", "byte one", "byte two", "byte combo", "end value", "fade", "command format", ¬
"command number", "q_number", "q_list", "q_path", "macro", "control number", "control value", "hours", "minutes", "seconds", "frames", "subframes", ¬
"send time with set", "sysex message", "midi destination", "start time offset", "fire next cue when loop ends", "stop target when loop ends", "load time", ¬
"assigned number"} -- All possible properties (order is based on entries in QLab's AppleScript dictionary)
set customColumnHeaders to {"put in group"} -- Additional columns this script will understand
repeat with eachItem in customColumnHeaders
copy eachItem as string to end of acceptableColumnHeaders
end repeat
set reportingOnlyColumns to {"unique ID", "broken", "audio input channels"} -- Not needed in this script; for reference {text, boolean, integer}
set levelColumns to {} -- If a column header contains "," it will be added to this list
set acceptableTypes to {"Group", "Audio", "Fade", "Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Start", "Stop", "Pause", "Reset", ¬
"Devamp", "Load", "Script", "Goto", "Target", "Wait", "Memo", "Arm", "Disarm", "SoundMan"} -- The script will not process "Cue List" as it is too cumbersome
-- This is a list of properties that can be set for each cue type
-- set index2_q_number: every cue has q number (text)
-- set index3_q_name: every cue has q name (text)
-- set index4_notes: every cue has notes (text)
set index5_cue_target to {"Fade", "Animation", "Start", "Stop", "Pause", "Reset", "Devamp", "Load", "Goto", "Target", "Arm", "Disarm"} -- (cue)
set index6_file_target to {"Audio", "Video"} -- (file)
-- set index7_pre_wait: every cue has pre wait (real)
set index8_duration to {"Fade", "Animation", "Camera", "MIDI", "Wait"} -- Duration of Audio & Video cues can't be set, only read (real)
-- set index9_post_wait: every cue has post wait (real)
-- set index10_continue_mode: every cue has continue mode (constants)
-- set index11_armed: every cue has armed (boolean)
-- set index12_midi_trigger: every cue has midi trigger (constants)
-- set index13_midi_command: every cue has midi command (constants)
-- set index14_midi_byte_one: every cue has midi byte one (integer)
-- set index15_midi_byte_two: every cue has midi byte two (integer)
-- set index16_timecode_trigger: every cue has timecode trigger (constants)
-- set index17_wall_clock_trigger: every cue has wall clock trigger (constants)
-- set index18_wall_clock_hours: every cue has wall clock hours (integer)
-- set index19_wall_clock_minutes: every cue has wall clock minutes (integer)
-- set index20_wall_clock_seconds: every cue has wall clock seconds (integer)
set index21_mode to {"Cue List", "Group"} -- (constants)
set index22_sync_to_timecode to {"Cue List"} -- (constants)
set index23_sync_mode to {"Cue List"} -- (constants)
set index24_smpte_format to {"Cue List", "MTC"} -- (constants) ###FIXME### "MSC" removed from list as QLab throws an error
set index25_mtc_sync_source_name to {"Cue List"} -- (text)
set index26_ltc_sync_channel to {"Cue List"} -- (integer)
set index27_patch to {"Audio", "Video", "Camera", "MIDI", "MSC", "MIDI SysEx"} -- (integer)
set index28_start_time to {"Audio", "Video"} -- (real)
set index29_end_time to {"Audio", "Video"} -- (real)
set index30_loop_start_time to {"Audio"} -- (real)
set index31_loop_end_time to {"Audio"} -- (real)
set index32_loop_count to {"Audio"} -- (integer)
set index33_infinite_loop to {"Audio", "Video"} -- (boolean)
set index34_guarantee_sync to {"Audio"} -- (boolean)
set index35_integrated_fade to {"Audio"} -- (constants)
set index36_fade_mode to {"Fade"} -- (constants)
set index37_stop_target_when_done to {"Fade", "Animation"} -- (boolean)
set index38_auto_stop to {"Video"} -- (boolean)
set index39_layer to {"Video", "Camera"} -- (integer)
set index40_full_screen to {"Video", "Camera"} -- (boolean)
set index41_preserve_aspect_ratio to {"Video", "Camera"} -- (boolean)
set index42_opacity to {"Video", "Animation", "Camera"} -- (real)
set index43_translation_x to {"Video", "Animation", "Camera"} -- (real)
set index44_translation_y to {"Video", "Animation", "Camera"} -- (real)
set index45_rotation to {"Video", "Animation", "Camera"} -- (real)
set index46_scale_x to {"Video", "Animation", "Camera"} -- (real)
set index47_scale_y to {"Video", "Animation", "Camera"} -- (real)
set index48_scale_locked to {"Video", "Animation", "Camera"} -- (boolean)
set index49_custom_rendering to {"Video", "Camera"} -- (boolean)
set index50_do_opacity to {"Animation"} -- (boolean)
set index51_do_translation to {"Animation"} -- (boolean)
set index52_do_rotation to {"Animation"} -- (boolean)
set index53_do_scale to {"Animation"} -- (boolean)
set index54_command to {"MIDI"} -- (constants)
set index55_channel to {"MIDI"} -- (integer)
set index56_byte_one to {"MIDI"} -- (integer)
set index57_byte_two to {"MIDI"} -- (integer)
set index58_byte_combo to {"MIDI"} -- (integer)
set index59_end_value to {"MIDI"} -- (integer)
set index60_fade to {"MIDI"} -- (constants)
set index61_command_format to {"MSC"} -- (integer - with translation)
set index62_command_number to {"MSC"} -- (integer - with translation)
set index63_q__number to {"MSC"} -- (text)
set index64_q__list to {"MSC"} -- (text)
set index65_q__path to {"MSC"} -- (text)
set index66_macro to {"MSC"} -- (integer)
set index67_control_number to {"MSC"} -- (integer)
set index68_control_value to {"MSC"} -- (integer)
set index69_hours to {"MSC"} -- (integer)
set index70_minutes to {"MSC"} -- (integer)
set index71_seconds to {"MSC"} -- (integer)
set index72_frames to {"MSC"} -- (integer)
set index73_subframes to {"MSC"} -- (integer)
set index74_send_time_with_set to {"MSC"} -- (boolean)
set index75_sysex_message to {"MIDI SysEx"} -- (text)
set index76_midi_destination to {"MTC"} -- (text)
set index77_start_time_offset to {"MTC"} -- (real)
set index78_fire_next_cue_when_loop_ends to {"Devamp"} -- (boolean)
set index79_stop_target_when_loop_ends to {"Devamp"} -- (boolean)
set index80_load_time to {"Load"} -- (real)
set index81_assigned_number to {"Target"} -- (text)
set index_setLevel to {"Audio", "Fade", "Video"} -- Special private index for custom column headers
-- This is a list of values for any constants (which can be used to customise the entries required in the text file)
set constants10_continue_mode to {"do_not_continue", "auto_continue", "auto_follow"}
set constants11_armed to {"true", "false"}
set constants12_midi_trigger to {"enabled", "disabled"}
set constants13_midi_command to {"note_on", "note_off", "program_change", "control_change", "key_pressure", "channel_pressure"}
set constants16_timecode_trigger to {"enabled", "disabled"}
set constants17_wall_clock_trigger to {"enabled", "disabled"}
set constants21_mode to {"cue_list", "fire_first_enter_group", "fire_first_go_to_next_cue", "fire_all", "fire_random"}
set constants22_sync_to_timecode to {"enabled", "disabled"}
set constants23_sync_mode to {"mtc", "ltc"}
set constants24_smpte_format to {"fps_24", "fps_25", "fps_30_drop", "fps_30_non_drop"}
set constants33_infinite_loop to {"true", "false"}
set constants34_guarantee_sync to {"true", "false"}
set constants35_integrated_fade to {"enabled", "disabled"}
set constants36_fade_mode to {"absolute", "relative"}
set constants37_stop_target_when_done to {"true", "false"}
set constants38_auto_stop to {"true", "false"}
set constants40_full_screen to {"true", "false"}
set constants41_preserve_aspect_ratio to {"true", "false"}
set constants48_scale_locked to {"true", "false"}
set constants49_custom_rendering to {"true", "false"}
set constants50_do_opacity to {"true", "false"}
set constants51_do_translation to {"true", "false"}
set constants52_do_rotation to {"true", "false"}
set constants53_do_scale to {"true", "false"}
set constants54_command to {"note_on", "note_off", "program_change", "control_change", "key_pressure", "channel_pressure", "pitch_bend"}
set constants60_fade to {"enabled", "disabled"}
set constants74_send_time_with_set to {"true", "false"}
set constants78_fire_next_cue_when_loop_ends to {"true", "false"}
set constants79_stop_target_when_loop_ends to {"true", "false"}
-- These variables are used to translate MSC integers into English
set translation61_command_format to {"1", "Lighting (General)", "2", "Moving Lights", "3", "Color Changers", "4", "Strobes", "5", "Lasers", "6", "Chasers", ¬
"16", "Sound (General)", "17", "Music", "18", "CD Players", "19", "EPROM Playback", "20", "Audio Tape Machines", "21", "Intercoms", "22", "Amplifiers", ¬
"23", "Audio Effects Devices", "24", "Equalizers", "32", "Machinery (General)", "33", "Rigging", "34", "Flys", "35", "Lifts", "36", "Turntables", "37", "Trusses", ¬
"38", "Robots", "39", "Animation", "40", "Floats", "41", "Breakaways", "42", "Barges", "48", "Video (General)", "49", "Video Tape Machines", ¬
"50", "Video Cassette Machines", "51", "Video Disc Players", "52", "Video Switchers", "53", "Video Effects", "54", "Video Character Generators", ¬
"55", "Video Still Stores", "56", "Video Monitors", "64", "Projection (General)", "65", "Film Projectors", "66", "Slide Projectors", "67", "Video Projectors", ¬
"68", "Dissolvers", "69", "Shutter Controls", "80", "Process Control (General)", "81", "Hydraulic Oil", "82", "H2O", "83", "CO2", "84", "Compressed Air", ¬
"85", "Natural Gas", "86", "Fog", "87", "Smoke", "88", "Cracked Haze", "96", "Pyrotechnics (General)", "97", "Fireworks", "98", "Explosions", "99", "Flame", ¬
"100", "Smoke Pots", "127", "All Types"}
set translation62_command_number to {"1", "GO", "2", "STOP", "3", "RESUME", "4", "TIMED_GO", "5", "LOAD", "6", "SET", "7", "FIRE", "8", "ALL_OFF", ¬
"9", "RESTORE", "10", "RESET", "11", "GO_OFF", "16", "GO/JAM_CLOCK", "17", "STANDBY_+", "18", "STANDBY_-", "19", "SEQUENCE_+", ¬
"20", "SEQUENCE_-", "21", "START_CLOCK", "22", "STOP_CLOCK", "23", "ZERO_CLOCK", "24", "SET_CLOCK", "25", "MTC_CHASE_ON", ¬
"26", "MTC_CHASE_OFF", "27", "OPEN_CUE_LIST", "28", "CLOSE_CUE_LIST", "29", "OPEN_CUE_PATH", "30", "CLOSE_CUE_PATH"}
-- General variables
set propertiesToColumns to {}
set annotateEveryLine to "No"
set cuesToMove to {}
try -- This overall try makes sure TIDs are reset if any "Cancel" button is pushed
-- Preamble
set theNavigator to "Review instructions"
repeat until theNavigator is "Get on with it"
set theNavigator to button returned of (display dialog "Would you like to review the instructions for this script?" with title ¬
dialogTitle with icon 1 buttons {"Review instructions", "Cancel", "Get on with it"} default button "Get on with it" cancel button "Cancel")
if theNavigator is "Review instructions" then
set finishedReading to false
repeat until finishedReading is true
set instructionButton1 to "Copy headers to Clipboard"
repeat until instructionButton1 is not "Copy headers to Clipboard"
set instructionButton1 to button returned of (display dialog "This script will take a tab-delimited text file and attempt " & ¬
"to turn it into a set of cues in QLab's current cue list.
Although it is relatively non-prescriptive in its approach, the script does ask a few things:
1. The first row of the text file must contain the \"column headers\", ie: it should define which properties you are hoping to set in your cues. " & ¬
"Unless you customise the script (look inside it to find out more about that), these column headers must exactly match the strings " & ¬
"used in QLab's AppleScript dictionary. For a list you can look at the dictionary, see the \"set acceptableColumnHeaders\" line inside " & ¬
"this script, or push the button below to copy it to the Clipboard (as a tab-delimited row).
2. You have to have a \"type\" column to tell the script what to make!
3. Entries in the \"cells\" should also conform to QLab's AppleScript expectations, eg: \"do_not_continue\", \"auto_continue\" & \"auto_follow\" " & ¬
"for \"continue mode\"; again, these are customisable at script level. An exception to this is that MSC command formats & numbers " & ¬
"should be expressed as the text you see in the Inspector, not as the integers that AppleScript deals with.
The script will make any kind of cue (except Cue Lists: too complicated; make a Group Cue instead and move it later) and set any kind of property " & ¬
"currently defined in the AppleScript hooks. File targets work if you paste the full path in \"POSIX\" form, ie: " & ¬
"\"/System/Library/Sounds/Basso.aiff\". Optionally, if all your media files share a common root path, you can choose this folder " & ¬
"and the script will add this to the file targets - saving you a bit of typing. Since a file target column is processed before most " & ¬
"other columns (regardless of the order in the text file), you don't need to worry about settings being reset when a file target changes...
One obvious, but significant, limiting factor is that you can't of course target cues that don't exist yet - since the script trundles through your text file " & ¬
"in a linear way, making cues as it goes, if Q3 is supposed to arm Q4 that won't work because Q4 hasn't been made yet " & ¬
"when Q3 is made. Clear?
The next page has some details about error protection, groups and levels..." with title dialogTitle with icon 1 ¬
buttons {"Back to start", "Copy headers to Clipboard", "To page 2 >>>"} default button "To page 2 >>>")
if instructionButton1 is "Copy headers to Clipboard" then
my toTheClipboard(acceptableColumnHeaders)
else if instructionButton1 is "Back to start" then
set finishedReading to true
end if
end repeat
if instructionButton1 is "To page 2 >>>" then
set instructionButton2 to "Copy headers to Clipboard"
repeat until instructionButton2 is not "Copy headers to Clipboard"
set instructionButton2 to button returned of (display dialog "There's not a lot of protection against you getting things " & ¬
"in your file wrong; there are no doubt hundreds of ways you can find to break the script. There is a basic error flag: \"!!!!\" " & ¬
"will be prepended to the q name of any cue when a process involved in making the cue went wrong; the line used to make the " & ¬
"cue will be copied to the cue's notes for reference: it's over to you to figure it out (trying to flag what exactly went wrong " & ¬
"is too complicated).
The script is capable of moving cues into groups when it's finished making them all: add a column called \"put in group\" and enter the q number " & ¬
"of the destination group in that cell for the cues you wish to move. This only works if you have set q numbers for both " & ¬
"the cue and the group.
In fact, quite a lot of the actions rely on cues having q numbers (eg: anything that requires setting a cue target). There are probably complex ways " & ¬
"round this, but for now you'll have to make do with using q numbers for most of the cues in the text file and then removing " & ¬
"those you don't want from the workspace. You can entertain yourself working out when you can get away without a q number! " & ¬
"All kinds of exciting things can go wrong if a q number is missing or invalid (eg: if you move a cue to a group that doesn't exist, " & ¬
"the cue vanishes...). Watch out for q numbers that already exist in the workspace as they will be unceremoniously dropped...
Since there are currently 833 possible scriptable levels for those cues that take them, it's up to you which levels to set in your file. " & ¬
"For any crosspoint you wish to set, add a column header of the form \"row,column\" and enter the levels in that column. " & ¬
"For example: column header \"0,0\" specifies row 0 column 0 (ie: the Master level), \"2,42\" would be row 2 column 42 " & ¬
"(the crosspoint between channel 2 of your audio file and output 42). Watch out for default gangs in your workspace, " & ¬
"as they'll override any attempt to set levels independently.
For the sake of simplicity, if you want \"-INF\" you'll need to put \"-120\" in your text file - although, since it's the default level, why bother? " & ¬
"Likewise, for the \"top\" layer, use \"1000\".
The bigger the file the longer and longer the script takes, in a kind of exponential way (so you may want to split the file up into chunks, and do a bit at a time). " & ¬
"The speed also depends on the number of columns; with 200 lines setting 100 properties/levels expect it to take at least " & ¬
"15 minutes..." with title dialogTitle with icon 1 ¬
buttons {"<<< To page 1", "Copy headers to Clipboard", "Back to start"} default button "Get on with it")
if instructionButton2 is "Copy headers to Clipboard" then
my toTheClipboard(acceptableColumnHeaders)
else if instructionButton2 is "Back to start" then
set finishedReading to true
end if
end repeat
end if
end repeat
end if
end repeat
-- Check QLab is running
tell application "System Events"
set qLabIsRunning to count (every process whose name is "QLab")
end tell
if qLabIsRunning is 0 then
display dialog "QLab is not running." with title dialogTitle with icon 0 buttons {"OK"} default button "OK" giving up after 5
return
end if
-- Test for a workspace
tell application "QLab"
try
get selected of front workspace
on error
display dialog "There is no workspace open in QLab." with title dialogTitle with icon 0 ¬
buttons {"OK"} default button "OK" giving up after 5
return
end try
end tell
-- Get the file
set theFile to choose file with prompt "Please select a tab-delimited text file:" default location (path to desktop) without invisibles
set AppleScript's text item delimiters to ""
try
set theText to read theFile
on error
my exitStrategy()
return
end try
tell application "System Events" -- Get just the name of the file, without the extension
set theExtension to name extension of theFile
if theExtension is "" then
set theName to name of theFile
else
set theFullName to name of theFile
set theName to text 1 through ((length of theFullName) - (length of theExtension) - 1) of theFullName
end if
end tell
-- Set up translation matrices
set AppleScript's text item delimiters to tab
try
set headerRow to every text item of paragraph 1 of theText -- Pull headers from file
on error
my exitStrategy()
return
end try
if "type" is not in headerRow then -- Won't know what cues to make without a type column!
display dialog "The header row of this file doesn't contain the word \"type\", " & ¬
"so I don't know which column to look in to specify what cues to make..." with title dialogTitle with icon 0 ¬
buttons {"OK"} default button "OK"
set AppleScript's text item delimiters to currentTIDs
return
end if
repeat with i from 1 to count acceptableColumnHeaders -- Find which properties are in text file, and which column they are in
copy 0 to end of propertiesToColumns
repeat with j from 1 to count headerRow
if item j of headerRow is item i of acceptableColumnHeaders then
set item i of propertiesToColumns to j
end if
end repeat
end repeat
set propertiesToColumnsRef to a reference to propertiesToColumns
repeat with i from 1 to count headerRow -- Make a list of all columns flagged as levels
if item i of headerRow contains "," then
copy i to end of levelColumns
end if
end repeat
set typeColumn to item 1 of propertiesToColumnsRef
-- Add a root path?
set setRootPath to button returned of (display dialog "Would you like me to prefix the file targets in your text file with a common root path?" with title ¬
dialogTitle with icon 1 buttons {"Yes", "No"} default button "No")
if setRootPath is "Yes" then
set pathFinder to (choose folder with prompt ¬
"Please select the folder that contains your audio & video files:" default location (path to home folder) without invisibles)
set pathPrefix to POSIX path of pathFinder
else
set pathPrefix to ""
end if
-- Annotate every line?
delay 0.5 -- Otherwise you don't notice the dialog has changed!
set annotateEveryLine to button returned of ¬
(display dialog "Would you like me to copy each line from the text file into the notes of the cue that is made from it?" with title ¬
dialogTitle with icon 1 buttons {"Yes", "No"} default button "No")
-- How long is this going to take?
set countText to count paragraphs of theText
set fudgeFactor to countText * ((count headerRow) / 100) -- Account for variable number of steps that will be run for each cue;
(* testing was done with 100 headers *)
-- ###FIXME### Current estimate based on second order polynomial interpolation of 3 sample data points (!): get more data
set theETA to 70 + 0.25 * fudgeFactor + 0.019 * (fudgeFactor ^ 2)
if theETA is greater than 40 then -- Don't waste 10s telling you it's going to take 30s!
set timeString to my makeNiceT(theETA)
set spuriousPlurals to " seconds"
repeat with i from 10 to 1 by -1
if i is 1 then
set spuriousPlurals to " second"
end if
set goOnThen to button returned of (display dialog (("There are " & countText as string) & " lines in this text file.
Based on current tests, this may take about " & timeString & " to process, possibly longer.
You have " & i as string) & spuriousPlurals & " to hit \"Cancel\"..." with title dialogTitle with icon 0 ¬
buttons {"Cancel", "OK"} default button "OK" cancel button "Cancel" giving up after 1)
if goOnThen is "OK" then
exit repeat
end if
end repeat
end if
-- Now, to business
tell application "QLab"
activate
display dialog "One moment caller..." with title dialogTitle with icon 1 buttons {"OK"} default button "OK" giving up after 1
set startTime to time of (current date)
tell front workspace
-- Record the header row, if required
if annotateEveryLine is "Yes" then
set niceParagraph to my makeNiceParagraph(headerRow)
make type "Memo"
set newCue to last item of (selected as list)
set q name of newCue to "<<<< Header from text file >>>>"
set notes of newCue to "Line 1 of text file \"" & theName & "\": | " & niceParagraph & " |"
end if
repeat with i from 2 to countText -- Skip the header row
set theRecord to every text item of paragraph i of theText
set niceParagraph to my makeNiceParagraph(theRecord)
repeat while (count theRecord) is less than (count headerRow) -- Pad out any missing cells from end of line, just in case
copy "" as string to end of theRecord
end repeat
set theRecordRef to (a reference to theRecord)
try
set theType to item typeColumn of theRecordRef
on error
set theType to "Unacceptable" -- Flag it for the next stage
end try
if theType is not in acceptableTypes then
make type "Memo"
set newCue to last item of (selected as list)
set q name of newCue to "!!!! Unprocessed line !!!!"
set notes of newCue to "Unprocessed line " & i & " of text file \"" & theName & "\": | " & niceParagraph & " |"
else
make type theType
set newCue to last item of (selected as list)
if annotateEveryLine is "Yes" then
set notes of newCue to "Made from line " & i & " of text file \"" & theName & "\": | " & niceParagraph & " |"
end if
set ohDear to false -- A simple flag to detect problems (not worth the effort of trying to attach a code to show which property(s) failed)
-- These if…then clauses set the relevant property on newCue based on the contents of the text file
if item 2 of propertiesToColumnsRef is not 0 then -- index2_q_number
try -- Putting try round every step stops the whole thing grinding to a halt if a field has a rogue entry that QLab doesn't like
set theItem to item (item 2 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then -- Had to put all these in to stop empty lines being interpreted as "0" (etc)
set q number of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if item 3 of propertiesToColumnsRef is not 0 then -- index3_q_name
try
set theItem to item (item 3 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set q name of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if item 4 of propertiesToColumnsRef is not 0 then -- index4_notes
try
set theItem to item (item 4 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then -- Prevents returns being added before line from text file if no notes given for cue
set existingNotes to notes of newCue as string
if existingNotes is not "missing value" then
set notes of newCue to theItem & return & return & existingNotes
else
set notes of newCue to theItem
end if
end if
on error
set ohDear to true
end try
end if
if theType is in index5_cue_target and item 5 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 5 of propertiesToColumnsRef) of theRecordRef as string
if theItem is not "" then
set targetCue to (first cue whose q number is theItem)
set cue target of newCue to targetCue
end if
on error
set ohDear to true
end try
end if
if theType is in index6_file_target and item 6 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 6 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
tell application "System Events"
file (pathPrefix & theItem) -- Check file exists
end tell
set file target of newCue to (pathPrefix & theItem)
end if
on error
set ohDear to true
end try
end if
if item 7 of propertiesToColumnsRef is not 0 then -- index7_pre_wait
try
set theItem to item (item 7 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set pre wait of newCue to theItem as real -- Try to protect against invalid entry
(* (anything that expects text should be fine with a string from theText;
hopefully this qualifier means only numbers are passed when numbers are expected) *)
end if
on error
set ohDear to true
end try
end if
if theType is in index8_duration and item 8 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 8 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set duration of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if item 9 of propertiesToColumnsRef is not 0 then -- index9_post_wait
try
set theItem to item (item 9 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set post wait of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if item 10 of propertiesToColumnsRef is not 0 then -- index10_continue_mode
try
set theItem to item (item 10 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants10_continue_mode then
set continue mode of newCue to do_not_continue
else if theItem is item 2 of constants10_continue_mode then
set continue mode of newCue to auto_continue
else if theItem is item 3 of constants10_continue_mode then
set continue mode of newCue to auto_follow
end if
on error
set ohDear to true
end try
end if
if item 11 of propertiesToColumnsRef is not 0 then -- index11_armed
try
set theItem to item (item 11 of propertiesToColumnsRef) of theRecordRef -- This prevents empty entries being treated as "false"
if theItem is item 1 of constants11_armed then
set armed of newCue to true
else if theItem is item 2 of constants11_armed then
set armed of newCue to false
end if
on error
set ohDear to true
end try
end if
if item 12 of propertiesToColumnsRef is not 0 then -- index12_midi_trigger
try
set theItem to item (item 12 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants12_midi_trigger then
set midi trigger of newCue to enabled
else if theItem is item 2 of constants12_midi_trigger then
set midi trigger of newCue to disabled
end if
on error
set ohDear to true
end try
end if
if item 13 of propertiesToColumnsRef is not 0 then -- index13_midi_command
try
set theItem to item (item 13 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants13_midi_command then
set midi command of newCue to note_on
else if theItem is item 2 of constants13_midi_command then
set midi command of newCue to note_off
else if theItem is item 3 of constants13_midi_command then
set midi command of newCue to program_change
else if theItem is item 4 of constants13_midi_command then
set midi command of newCue to control_change
else if theItem is item 5 of constants13_midi_command then
set midi command of newCue to key_pressure
else if theItem is item 6 of constants13_midi_command then
set midi command of newCue to channel_pressure
end if
on error
set ohDear to true
end try
end if
if item 14 of propertiesToColumnsRef is not 0 then -- index14_midi_byte_one
try
set theItem to item (item 14 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set midi byte one of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if item 15 of propertiesToColumnsRef is not 0 then -- index15_midi_byte_two
try
set theItem to item (item 15 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set midi byte two of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if item 16 of propertiesToColumnsRef is not 0 then -- index16_timecode_trigger
try
set theItem to item (item 16 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants16_timecode_trigger then
set timecode trigger of newCue to enabled
else if theItem is item 2 of constants16_timecode_trigger then
set timecode trigger of newCue to disabled
end if
on error
set ohDear to true
end try
end if
if item 17 of propertiesToColumnsRef is not 0 then -- index17_wall_clock_trigger
try
set theItem to item (item 17 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants17_wall_clock_trigger then
set wall clock trigger of newCue to enabled
else if theItem is item 2 of constants17_wall_clock_trigger then
set wall clock trigger of newCue to disabled
end if
on error
set ohDear to true
end try
end if
if item 18 of propertiesToColumnsRef is not 0 then -- index18_wall_clock_hours
try
set theItem to item (item 18 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set wall clock hours of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if item 19 of propertiesToColumnsRef is not 0 then -- index19_wall_clock_minutes
try
set theItem to item (item 19 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set wall clock minutes of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if item 20 of propertiesToColumnsRef is not 0 then -- index20_wall_clock_seconds
try
set theItem to item (item 20 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set wall clock seconds of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index21_mode and item 21 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 21 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants21_mode then
set mode of newCue to cue_list
else if theItem is item 2 of constants21_mode then
set mode of newCue to fire_first_enter_group
else if theItem is item 3 of constants21_mode then
set mode of newCue to fire_first_go_to_next_cue
else if theItem is item 4 of constants21_mode then
set mode of newCue to fire_all
else if theItem is item 5 of constants21_mode then
set mode of newCue to fire_random
end if
on error
set ohDear to true
end try
end if
if theType is in index22_sync_to_timecode and item 22 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 22 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants22_sync_to_timecode then
set sync to timecode of newCue to enabled
else if theItem is item 2 of constants22_sync_to_timecode then
set sync to timecode of newCue to disabled
end if
on error
set ohDear to true
end try
end if
if theType is in index23_sync_mode and item 23 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 23 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants23_sync_mode then
set sync mode of newCue to mtc
else if theItem is item 2 of constants23_sync_mode then
set sync mode of newCue to ltc
end if
on error
set ohDear to true
end try
end if
if theType is in index24_smpte_format and item 24 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 24 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants24_smpte_format then
set smpte format of newCue to fps_24
else if theItem is item 2 of constants24_smpte_format then
set smpte format of newCue to fps_25
else if theItem is item 3 of constants24_smpte_format then
set smpte format of newCue to fps_30_drop
else if theItem is item 4 of constants24_smpte_format then
set smpte format of newCue to fps_30_non_drop
end if
on error
set ohDear to true
end try
end if
if theType is in index25_mtc_sync_source_name and item 25 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 25 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set mtc sync source name of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if theType is in index26_ltc_sync_channel and item 26 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 26 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set ltc sync channel of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index27_patch and item 27 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 27 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set patch of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index28_start_time and item 28 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 28 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set start time of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index29_end_time and item 29 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 29 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set end time of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index30_loop_start_time and item 30 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 30 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set loop start time of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index31_loop_end_time and item 31 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 31 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set loop end time of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index32_loop_count and item 32 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 32 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set loop count of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index33_infinite_loop and item 33 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 33 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants33_infinite_loop then
set infinite loop of newCue to true
else if theItem is item 2 of constants33_infinite_loop then
set infinite loop of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index34_guarantee_sync and item 34 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 34 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants34_guarantee_sync then
set guarantee sync of newCue to true
else if theItem is item 2 of constants34_guarantee_sync then
set guarantee sync of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index35_integrated_fade and item 35 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 35 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants35_integrated_fade then
set integrated fade of newCue to enabled
else if theItem is item 2 of constants35_integrated_fade then
set integrated fade of newCue to disabled
end if
on error
set ohDear to true
end try
end if
if theType is in index36_fade_mode and item 36 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 36 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants36_fade_mode then
set fade mode of newCue to absolute
else if theItem is item 2 of constants36_fade_mode then
set fade mode of newCue to relative
end if
on error
set ohDear to true
end try
end if
if theType is in index37_stop_target_when_done and item 37 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 37 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants37_stop_target_when_done then
set stop target when done of newCue to true
else if theItem is item 2 of constants37_stop_target_when_done then
set stop target when done of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index38_auto_stop and item 38 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 38 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants38_auto_stop then
set auto stop of newCue to true
else if theItem is item 2 of constants38_auto_stop then
set auto stop of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index39_layer and item 39 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 39 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set layer of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index40_full_screen and item 40 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 40 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants40_full_screen then
set full screen of newCue to true
else if theItem is item 2 of constants40_full_screen then
set full screen of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index41_preserve_aspect_ratio and item 41 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 41 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants41_preserve_aspect_ratio then
set preserve aspect ratio of newCue to true
else if theItem is item 2 of constants41_preserve_aspect_ratio then
set preserve aspect ratio of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index42_opacity and item 42 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 42 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set opacity of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index43_translation_x and item 43 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 43 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set translation x of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index44_translation_y and item 44 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 44 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set translation y of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index45_rotation and item 45 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 45 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set rotation of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index46_scale_x and item 46 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 46 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set scale x of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index47_scale_y and item 47 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 47 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set scale y of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index48_scale_locked and item 48 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 48 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants48_scale_locked then
set scale locked of newCue to true
else if theItem is item 2 of constants48_scale_locked then
set scale locked of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index49_custom_rendering and item 49 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 49 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants49_custom_rendering then
set custom rendering of newCue to true
else if theItem is item 2 of constants49_custom_rendering then
set custom rendering of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index50_do_opacity and item 50 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 50 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants50_do_opacity then
set do opacity of newCue to true
else if theItem is item 2 of constants50_do_opacity then
set do opacity of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index51_do_translation and item 51 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 51 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants51_do_translation then
set do translation of newCue to true
else if theItem is item 2 of constants51_do_translation then
set do translation of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index52_do_rotation and item 52 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 52 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants52_do_rotation then
set do rotation of newCue to true
else if theItem is item 2 of constants52_do_rotation then
set do rotation of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index53_do_scale and item 53 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 53 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants53_do_scale then
set do scale of newCue to true
else if theItem is item 2 of constants53_do_scale then
set do scale of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index54_command and item 54 of propertiesToColumnsRef is not 0 then -- index13_midi_command
try
set theItem to item (item 54 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants54_command then
set command of newCue to note_on
else if theItem is item 2 of constants54_command then
set command of newCue to note_off
else if theItem is item 3 of constants54_command then
set command of newCue to program_change
else if theItem is item 4 of constants54_command then
set command of newCue to control_change
else if theItem is item 5 of constants54_command then
set command of newCue to key_pressure
else if theItem is item 6 of constants54_command then
set command of newCue to channel_pressure
else if theItem is item 7 of constants54_command then
set command of newCue to pitch_bend
end if
on error
set ohDear to true
end try
end if
if theType is in index55_channel and item 55 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 55 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set channel of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index56_byte_one and item 56 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 56 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set byte one of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index57_byte_two and item 57 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 57 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set byte two of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index58_byte_combo and item 58 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 58 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set byte combo of newCue to ((theItem as integer) + 8192) -- Pitch bend of 0 needs to be set as 8192
end if
on error
set ohDear to true
end try
end if
if theType is in index59_end_value and item 59 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 59 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
if command of newCue is not pitch_bend then
set end value of newCue to theItem as integer
else
set end value of newCue to ((theItem as integer) + 8192) -- This origin shift won't work if command isn't set!
end if
end if
on error
set ohDear to true
end try
end if
if theType is in index60_fade and item 60 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 60 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants60_fade then
set fade of newCue to enabled
else if theItem is item 2 of constants60_fade then
set fade of newCue to disabled
end if
on error
set ohDear to true
end try
end if
if theType is in index61_command_format and item 61 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 61 of propertiesToColumnsRef) of theRecordRef
if theItem is in translation61_command_format then
repeat with j from 2 to count translation61_command_format by 2
if theItem is item j of translation61_command_format then
set command format of newCue to item (j - 1) of translation61_command_format as integer
exit repeat
end if
end repeat
else
set ohDear to true
end if
on error
set ohDear to true
end try
end if
if theType is in index62_command_number and item 62 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 62 of propertiesToColumnsRef) of theRecordRef
if theItem is in translation62_command_number then
repeat with j from 2 to count translation62_command_number by 2
if theItem is item j of translation62_command_number then
set command number of newCue to item (j - 1) of translation62_command_number as integer
exit repeat
end if
end repeat
else
set ohDear to true
end if
on error
set ohDear to true
end try
end if
if theType is in index63_q__number and item 63 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 63 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set q_number of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if theType is in index64_q__list and item 64 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 64 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set q_list of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if theType is in index65_q__path and item 65 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 65 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set q_path of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if theType is in index66_macro and item 66 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 66 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set macro of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index67_control_number and item 67 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 67 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set control number of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index68_control_value and item 68 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 68 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set control value of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index69_hours and item 69 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 69 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set hours of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index70_minutes and item 70 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 70 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set minutes of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index71_seconds and item 71 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 71 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set seconds of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index72_frames and item 72 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 72 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set frames of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index73_subframes and item 73 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 73 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set subframes of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if
if theType is in index74_send_time_with_set and item 74 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 74 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants74_send_time_with_set then
set send time with set of newCue to true
else if theItem is item 2 of constants74_send_time_with_set then
set send time with set of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index75_sysex_message and item 75 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 75 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set sysex message of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if theType is in index76_midi_destination and item 76 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 76 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set midi destination of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if theType is in index77_start_time_offset and item 77 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 77 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set start time offset of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index78_fire_next_cue_when_loop_ends and item 78 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 78 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants78_fire_next_cue_when_loop_ends then
set fire next cue when loop ends of newCue to true
else if theItem is item 2 of constants78_fire_next_cue_when_loop_ends then
set fire next cue when loop ends of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index79_stop_target_when_loop_ends and item 79 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 79 of propertiesToColumnsRef) of theRecordRef
if theItem is item 1 of constants79_stop_target_when_loop_ends then
set stop target when loop ends of newCue to true
else if theItem is item 2 of constants79_stop_target_when_loop_ends then
set stop target when loop ends of newCue to false
end if
on error
set ohDear to true
end try
end if
if theType is in index80_load_time and item 80 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 80 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set load time of newCue to theItem as real
end if
on error
set ohDear to true
end try
end if
if theType is in index81_assigned_number and item 81 of propertiesToColumnsRef is not 0 then
try
set theItem to item (item 81 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
set assigned number of newCue to theItem
end if
on error
set ohDear to true
end try
end if
if item 82 of propertiesToColumnsRef is not 0 then -- Make a list of cues to move later
try
set theItem to item (item 82 of propertiesToColumnsRef) of theRecordRef
if theItem is not "" then
copy item (item 2 of propertiesToColumnsRef) of theRecordRef to end of cuesToMove -- This cue's q number
copy theItem to end of cuesToMove -- The destination group
end if
on error
set ohDear to true
end try
end if
-- Deal with levels
if theType is in index_setLevel then
repeat with eachLevelColumn in levelColumns
set AppleScript's text item delimiters to "\""
set excelCleanup to word 1 of item eachLevelColumn of headerRow
-- Deal with Excel formatting: 0,0 becomes "0,0" when exported
set AppleScript's text item delimiters to ","
try
if item eachLevelColumn of theRecordRef is not "" then
set theRow to text item 1 of excelCleanup as integer
set theColumn to text item 2 of excelCleanup as integer
set theLevel to item eachLevelColumn of theRecordRef as real
newCue setLevel row theRow column theColumn db theLevel
end if
on error
set ohDear to true
end try
end repeat
set AppleScript's text item delimiters to tab
end if
-- Flag any errors
if ohDear is true then
set existingName to q name of newCue as string
if existingName is not "" then -- q name returns "" if it's empty; notes returns "missing value"; go figure (53)... ;-)
set q name of newCue to "!!!! " & existingName
else
set q name of newCue to "!!!!"
end if
if annotateEveryLine is "No" then
set existingNotes to notes of newCue as string
if existingNotes is not "missing value" then
set notes of newCue to existingNotes & return & return & "Made from line " & i & " of text file \"" & ¬
theName & "\": | " & niceParagraph & " |"
else
set notes of newCue to "Made from line " & i & " of text file \"" & theName & "\": | " & niceParagraph & " |"
end if
end if
end if
end if
-- Countdown timer (and opportunity to escape)
if i mod 50 is 0 and (countText - i) > 25 then
set timeTaken to ((time of (current date)) - startTime) as integer
set timeString to my makeMMSS(timeTaken)
if application "QLab" is frontmost then
display dialog (("Time elapsed: " & timeString & " - " & i as string) & " of " & countText as string) & " lines done..." with title ¬
dialogTitle with icon 1 buttons {"Cancel", "OK"} default button "OK" cancel button "Cancel" giving up after 1
end if
end if
end repeat
-- Move cues into groups
repeat with i from 1 to count cuesToMove by 2
try
set cueToMoveNumber to item i of cuesToMove
set destinationNumber to item (i + 1) of cuesToMove
move cue cueToMoveNumber of current cue list to end of cue destinationNumber
end try
end repeat
end tell
-- All done. Hoopla!
set timeTaken to ((time of (current date)) - startTime) as integer
set timeString to my makeNiceT(timeTaken)
activate
display dialog "Done.
(That took " & timeString & ".)
I hope it all worked out OK..." with title dialogTitle with icon 1 buttons {"OK"} default button "OK" giving up after 60
end tell
set AppleScript's text item delimiters to currentTIDs
on error number -128
set AppleScript's text item delimiters to currentTIDs
end try
-- Subroutines
on toTheClipboard(textToCopy)
set AppleScript's text item delimiters to tab
set the clipboard to textToCopy as text
set AppleScript's text item delimiters to currentTIDs
end toTheClipboard
on exitStrategy()
display dialog "I'm afraid that file tasted funny so I've had to spit it out. Please check the file and try again. Sorry." with title ¬
dialogTitle with icon 0 buttons {"OK"} default button "OK"
set AppleScript's text item delimiters to currentTIDs
end exitStrategy
on makeNiceParagraph(dirtyColumns)
set tempTIDS to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
set cleanRow to ""
set theSeparator to ""
repeat with eachColumn in dirtyColumns
if eachColumn starts with "\"" then
if eachColumn does not end with "\"" then
set cleanRow to cleanRow & theSeparator & (rest of characters of eachColumn as string)
else
set cleanRow to cleanRow & theSeparator & (characters 2 thru ((count eachColumn) - 1) of eachColumn as string)
end if
else if eachColumn does not end with "\"" then
set cleanRow to cleanRow & theSeparator & eachColumn
else
set cleanRow to cleanRow & theSeparator & (characters 1 thru ((count eachColumn) - 1) of eachColumn as string)
end if
set theSeparator to " | "
end repeat
set AppleScript's text item delimiters to tempTIDS
return cleanRow
end makeNiceParagraph
on makeNiceT(howLong)
if howLong is 0 then
return "less than a second"
end if
set howManyHours to howLong div 3600
if howManyHours is 0 then
set hourString to ""
else if howManyHours is 1 then
set hourString to "1 hour"
else
set hourString to (howManyHours as string) & " hours"
end if
set howManyMinutes to (howLong mod 3600) div 60
if howManyMinutes is 0 then
set minuteString to ""
else if howManyMinutes is 1 then
set minuteString to "1 minute"
else
set minuteString to (howManyMinutes as string) & " minutes"
end if
set howManySeconds to howLong mod 60 as integer
if howManySeconds is 0 then
set secondString to ""
else if howManySeconds is 1 then
set secondString to "1 second"
else
set secondString to (howManySeconds as string) & " seconds"
end if
if hourString is not "" then
if minuteString is not "" and secondString is not "" then
set theAmpersand to ", "
else if minuteString is not "" or secondString is not "" then
set theAmpersand to " and "
else
set theAmpersand to ""
end if
else
set theAmpersand to ""
end if
if minuteString is not "" and secondString is not "" then
set theOtherAmpersand to " and "
else
set theOtherAmpersand to ""
end if
return hourString & theAmpersand & minuteString & theOtherAmpersand & secondString
end makeNiceT
on makeMMSS(howLong)
set howManyMinutes to howLong div 60
set minuteString to (howManyMinutes as string)
set howManySeconds to howLong mod 60 as integer
if howManySeconds > 9 then
set secondString to (howManySeconds as string)
else
set secondString to "0" & (howManySeconds as string)
end if
return minuteString & ":" & secondString
end makeMMSS
(* END: Make cues from a text file *)