[QLab] Script Requests

724 views
Skip to first unread message

Matt Otto

unread,
Oct 4, 2009, 6:04:38 PM10/4/09
to QLab List
Hey all,
I was pursuing the Tracker today and saw that an old feature request of mine was solved by the new scripting feature: (http://tracker.figure53.com/qlab/ticket/115#comment:2  

I have no idea if this is really possible but...

I was hoping someone could write a script that would create a XML file that had all the cues and settings for each that FileMaker or Excel could open. Ideally it includes level settings but I won’t hold my breath for that. 

I’d also love a script that could take a XML file and create cues from it. Meaning that it would create the correct type of cue and name it. 

I’d gladly pay for both scripts. 

Rich Walsh

unread,
Oct 4, 2009, 8:33:00 PM10/4/09
to Discussion and support for QLab users.
On 4 Oct 2009, at 23:04, Matt Otto wrote:

> Hey all,
> I was pursuing the Tracker today and saw that an old feature
> request of mine was solved by the new scripting feature: (http://tracker.figure53.com/qlab/ticket/115#comment
> :2
>
> I have no idea if this is really possible but...
>
> I was hoping someone could write a script that would create a XML
> file that had all the cues and settings for each that FileMaker or
> Excel could open. Ideally it includes level settings but I won’t
> hold my breath for that.
>
> I’d also love a script that could take a XML file and create cues
> from it. Meaning that it would create the correct type of cue and
> name it.

I've done most of the legwork for the latter with the "Bodging a MIDI
player" script, in that it will take a file with a very precise and
known structure and turn it into a list of cues in QLab. To
extrapolate that more generally I'd need to know more about the
content of your XML files, and how much work you would like to achieve
within QLab.

First off though, I'd rather work with tab-delimited text files as I
suspect that XML files contain a great deal of unnecessary gumph that
has nothing to do with the actual content; I can't be sure as nothing
on my Mac seems overly happy about trying to open them (another reason
to avoid them). They seem to default to trying to open Adobe
Illustrator for some reason; I'm always wary of anything that can't be
handled by TextEdit myself...

Secondly, how much information are you actually going to the trouble
of creating in your XML file before you start programming in QLab? I
ask because I used to spend an awful lot of time turning my scribbles
in scripts (those paper things with words from plays in) into
elaborate Excel files and then programming from there. One day I
decided not to bother with the Excel step and programmed the cues
directly into SFX from my scribbles, marking up the script in pen as I
went; I haven't ever wished to go back, as for me this gives me an
extra day or two making noise rather than making spreadsheets. Of
course, this only works when I have the luxury of an operator who is
prepared to go through my marked up script to give the cues to Stage
Management, and who will be operating from a script rather than a cue
list.

I wonder what steps are easier to do in a spreadsheet than with the
tools in QLab that are specifically designed to achieve the cues
you're trying to get to?

Anyway, say you have a text file like this:

Number Name Type Target Pre Wait Duration Post Wait Continue
Mode Notes
0.5 Preshow Audio /Sounds/Preshow.wav 5:00 Auto-continue
House opens
Build preshow Fade Q0.5 0:10

It wouldn't be too painful to turn that into cues (there'd be lots of
elephant traps along the way: how to handle Group Cues, how to work
out Fade Cue targets, establishing fully-qualified path names for
audio files, etc), but how much more effort is it to type all that
stuff into the text file in the first place? That's supposed to be an
open-minded enquiry, not anything judgemental, by the way.

I can see the merit in a list of just Number, Name, Type & Notes as a
starting point for a workspace, however. I might prod that idea some
time.

As for reporting, again I wonder how much information you would want
to extract from a QLab workspace? As above, a quick list of Number,
Name & Notes would be quite straightforward - and probably quite handy
to give to Stage Management - but if you need to know every single
setting of every single thing in a workspace why can't you open it in
QLab and have a look? This approach has served me well for years, but
maybe I've been lucky to work with applications with good backwards
compatibility? (If it ever comes to it I do have a Mac OS 9 machine
lying around just in case I need a Vision file from 1998!).

As for levels, there are (I think) potentially 16+16*48+48+1 = 833
levels for each Audio Cue (not counting Trim); how would you lay that
out in your XML file? To my mind Chris has already designed quite a
good interface for interrogating an XML file and displaying _all_ that
information...

I think I can see the value in having a tool that can do some
reporting, but is it a corkscrew, a penknife with a corkscrew on it or
a wine waiter? I'm interested to know more about your workflow.

Rich
________________________________________________________
WHEN REPLYING, PLEASE QUOTE ONLY WHAT YOU NEED. Thanks!
Change your preferences or unsubscribe here:
http://lists.figure53.com/listinfo.cgi/qlab-figure53.com

Andy Dolph

unread,
Oct 4, 2009, 10:29:23 PM10/4/09
to Discussion and support for QLab users.

I'll let Matt speak for himself - but for me a text file -> cues
function would be very useful - when I do large projection designs
with hundreds to thousands of bits of media (stills and video) I use
FilemakerPro as a storyboarding tool so that I can easily flip through
my cues as I'm working out the design conceptually. this was
particularly helpful when I did one design where a single projector
was used to cover 6 different areas that were sometimes used
separately and sometimes together. I used FMP to storyboard and then
output files named as <area><qnumber> (ie AboveDoor0007) then used a
script in Shake to automatically composite the individual chunks into
the correct "full screen" composites that ran from qlab. (BTW -
this was in qlab 1 days so it was not practical for me to do the
composites on the fly)

Even without that complexity - by storyboarding in FMP I can do much
more of the work on my laptop were ever I happen to be before I need
to move to the multi machine, multi display qlab rig.

since i already know the cue numbers and file names and can easily add
things like fade times and opacity information in FMP if I wanted to -
I'd love to be able to export that data from FMP and import it to
Qlab.

In fact Chris did a custom one time hack for me along these lines (I
sent him an excel export from FMP and he wrote some code to generate a
qlab1 file from it....) It saved me something like 1500 cues I would
have needed to create manually - so I'd love to have a way to do that
easily with a script (and will learn the applescript to write it
myself if need be - but I don't have the need now, and don't have the
time to learn applescript a the moment...)

So if it's something that would be easy for you to do, Rich (or
whoever else) I'd be eternally grateful.


another use for this sort of thing comes to mind - apps like FMP are
very good at complex find and replace operations - when I've had to
move lighting designs between very different houses I use a set of FMP
hacks I put together to be able to adapt the cues from the rig in one
venue to another (using USITT standard Ascii cue files)

being able to do something similar with Qlab could be very useful.

andy

Andy Leviss

unread,
Oct 5, 2009, 1:03:04 AM10/5/09
to Discussion and support for QLab users.
On Sun, Oct 4, 2009 at 6:04 PM, Matt Otto <mott...@gmail.com> wrote:
> I was hoping someone could write a script that would create a XML file that
> had all the cues and settings for each that FileMaker or Excel could open.
> Ideally it includes level settings but I won’t hold my breath for that.

I may be mistaken, but I was pretty sure that Jeremy Lee was pretty
close on something along these lines, which is why he'd been posting
for certain things such as matrix/bus assignments to be available to
AppleScript a week or two ago. But maybe I misunderstood?

--A

Jeremy Lee

unread,
Oct 5, 2009, 9:47:38 AM10/5/09
to Discussion and support for QLab users.
Yeah- I did this.  It's not perfect, but it works for just about anything audio and MIDI related.  Haven't bothered with Video as I don't do that very much (although that may change in the Spring).  I just haven't posted it, mostly because I didn't want to deal with tech support on it.

Since I don't seem the be the only one interested in this, I'll put it on the WIKI and you can do with it what you will.  But *please* don't expect me to be able to provide any support for it.  I have enough trouble finding time to eat breakfast with a 4 month old at home...

Actually, I just looked at the Wiki page again, and realize that I don't have time to figure out how to put the script on there without messing the rest of the page up.  So here it is- someone else can put it up there...

(*
QLab reporter with Levels
© 2009 Jeremy Lee
*)

global tempContents, file_name, NewContents


tell application "QLab"
set tempContents to {}
set progress_factor to 10


set file_name to (choose file name with prompt "Enter a name for the exported QLab file:" default name "QLab Export")
if file_name is false then error number -128 -- cancel
if file_name as string does not end with ".txt" then set file_name to ((file_name as string) & ".txt")


my tell_everybody("Getting started...", 1)



(* This stuff is for the matrix reporting *)


set numOfColumns to 24 (* How many matrix outs do you want to look at? *)


set matrixTitles to {"Master" & tab & "Input 1" & tab & "Input 2"}


set surTitle to "Output "


repeat with curNum from 1 to numOfColumns
copy (tab & surTitle & " " & curNum) as string to end of matrixTitles
end repeat


set surTitle to "Matrix 1/"


repeat with curNum from 1 to numOfColumns
copy (tab & surTitle & " " & curNum) as string to end of matrixTitles
end repeat


set surTitle to "Matrix 2/"


repeat with curNum from 1 to numOfColumns
copy (tab & surTitle & " " & curNum) as string to end of matrixTitles
end repeat


(* End matrix reporting titles *)


tell me to add_this_to_tempContents("Index" & tab & "CueID" & tab & "Q Number" & tab & "Q Type" & tab & "Q Name" & tab & "Q Target" & tab & "File Target" & tab & "Pre Wait" & tab & "Duration" & tab & "Post Wait" & tab & "Continue" & tab & "Cue Start" & tab & "Cue End" & tab & "Loop Start" & tab & "Loop End" & tab & "Num Loops" & tab & "Inf Loop" & tab & "Internal Fade" & tab & "Fade Mode" & tab & "Stop Fade" & tab & "MIDIPatch" & tab & "MIDICmd" & tab & "MIDIChan" & tab & "MIDIByte1" & tab & "MIDIByte2" & tab & "MIDIStart" & tab & "MIDIEnd" & tab & "MIDIFade" & tab & "Broken?" & tab & matrixTitles & return)




tell workspace 1
set numCues to count of cues
repeat with curCueNum from 1 to numCues




set fullCue to (a reference to cue curCueNum)


set cueIndex to curCueNum


set cueID to uniqueID of fullCue
set currentNum to q number of fullCue
set currentType to q type of fullCue


tell me to set pWait to transform_wait_to_time(pre wait of fullCue)
tell me to set curDur to transform_seconds_to_time(duration of fullCue)
tell me to set pstWait to transform_wait_to_time(post wait of fullCue)


set curCont to continue mode of fullCue
if curCont as string is "do_not_continue" then set curCont to ""
if curCont as string is "auto_continue" then set curCont to "Cont."
if curCont as string is "auto_follow" then set curCont to "Follow"


set cueBroken to broken of fullCue


if currentType as string is "Group" then
set currentMode to mode of fullCue
if currentMode as string is "cue_list" then set currentType to "Cue List"
if currentMode as string is "fire_first_enter_group" then set currentType to "Group - Enter"
if currentMode as string is "fire_first_go_to_next_cue" then set currentType to "Group - Go To Next"
if currentMode as string is "fire_all" then set currentType to "Group - Fire All"
if currentMode as string is "fire_random" then set currentType to "Group - Random"


set curDur to ""


set CuesInGroup to count of cues in fullCue -- Do something with this later to indicate individual cues in groups
set currentType to currentType & "; Cues in group: " & CuesInGroup


end if


if currentType as string is "Audio" then


tell me to set cueStart to transform_seconds_to_time(start time of fullCue)


(* Can't quite remember why this is in here


if start time of fullCue > 0 then
set cueStart to start time of fullCue
else
set cueStart to "0"
end if
*)



tell me to set cueEnd to transform_seconds_to_time(end time of fullCue)


if loop start time of fullCue > 0 then
tell me to set loopStart to transform_seconds_to_time(loop start time of fullCue)
else
set loopStart to "Top"
end if


tell me to set loopEnd to transform_seconds_to_time(loop end time of fullCue)
if loopEnd = cueEnd then set loopEnd to "End"


set loopNum to loop count of fullCue
set loopInf to infinite loop of fullCue


(* This is here because QLab 2.07 does not properly report the infiniteloop value - is this fixed? *)
if loopInf as string is not "true" then set loopInf to "False"


set intFade to integrated fade of fullCue


else
set cueStart to ""
set cueEnd to ""
set loopStart to ""
set loopEnd to ""
set loopNum to ""
set loopInf to ""
set intFade to ""
end if


if currentType as string is "Fade" then
(*
set fadeMode to mode of fullCue
*)
set stopFade to stop target when done of fullCue
set fadeMode to ""


else
set fadeMode to ""
set stopFade to ""


end if


if currentType as string is "MIDI" then
set MIDIPatch to patch of fullCue
set MIDICmd to command of fullCue
set MIDIChan to channel of fullCue
set MIDIByte1 to byte one of fullCue
set MIDIByte2 to byte two of fullCue
set MIDIFade to fade of fullCue
if MIDIFade as string is "enabled" then
set MIDIStart to start value of fullCue
set MIDIEnd to end value of fullCue
set currentType to "MIDI Fade"
else
set MIDIStart to ""
set MIDIEnd to ""
set curDur to ""
end if
else
set MIDIPatch to ""
set MIDICmd to ""
set MIDIChan to ""
set MIDIByte1 to ""
set MIDIByte2 to ""
set MIDIStart to ""
set MIDIEnd to ""
set MIDIFade to ""


end if


set currentName to q name of fullCue


if exists (q name of cue target of fullCue) then
set cueTarget to q name of cue target of fullCue
else
set cueTarget to ""
end if


try
set fileTarget to (file target of fullCue as string)
on error
set fileTarget to ""
end try


set levelMAtrix to {}


if (currentType as string is "Audio") or (currentType as string is "Fade") then



set masterLevel to fullCue getLevel row 0 column 0
set inputOne to fullCue getLevel row 1 column 0
set inputTwo to fullCue getLevel row 2 column 0


set IOMaster to {masterLevel & tab & inputOne & tab & inputTwo & tab}


set outputRow to {}
set inputOneRow to {}
set inputTwoRow to {}
set levelMAtrix to {}



repeat with colNum from 1 to numOfColumns
set cueLevel to fullCue getLevel row 0 column colNum
if cueLevel = -120 then set cueLevel to "x"
copy (cueLevel & tab) as string to end of outputRow
end repeat


repeat with colNum from 1 to numOfColumns
set cueLevel to fullCue getLevel row 1 column colNum
if cueLevel = -120 then set cueLevel to "x"
copy (cueLevel & tab) as string to end of inputOneRow
end repeat


repeat with colNum from 1 to numOfColumns
set cueLevel to fullCue getLevel row 2 column colNum
if cueLevel = -120 then set cueLevel to "x"
copy (cueLevel & tab) as string to end of inputTwoRow
end repeat


set levelMAtrix to {IOMaster & outputRow & inputOneRow & inputTwoRow}


end if




tell me to add_this_to_tempContents(cueIndex & tab & cueID & tab & currentNum & tab & currentType & tab & currentName & tab & cueTarget & tab & fileTarget & tab & pWait & tab & curDur & tab & pstWait & tab & curCont & tab & cueStart & tab & cueEnd & tab & loopStart & tab & loopEnd & tab & loopNum & tab & loopInf & tab & intFade & tab & fadeMode & tab & stopFade & tab & MIDIPatch & tab & MIDICmd & tab & MIDIChan & tab & MIDIByte1 & tab & MIDIByte2 & tab & MIDIStart & tab & MIDIEnd & tab & MIDIFade & tab & cueBroken & tab & levelMAtrix & return)



if (progress_factor 0) and (curCueNum mod progress_factor) = 0 then my tell_everybody((curCueNum as string) & " of " & (numCues as string) & " cues scanned so far...", 1)


end repeat
end tell



end tell


tell me to make_report()

set dMes to return & return & "Would you like to open the text file report with Excel now?  Times and Durations will not show up correctly unless you manually tell Excel to import all columns as 'text' rather than 'general' data."
set myEnding to (display dialog "Done!" & dMes buttons {"Done", "Yes"} default button 2 with icon 1 giving up after 30)
if button returned of myEnding is "Yes" or gave up of myEnding is true then
tell application "Microsoft Excel"
activate
try
open (file_name as alias)
on error errMs
display dialog errMs buttons {"Cancel"}
end try
end tell
end if -- button is "Done"


to make_report()
set NewContents to (tempContents as string)


try
copy (a reference to (open for access file_name with write permission)) to fileRefr
write NewContents to fileRefr
close access fileRefr
on error errx number errNum from badObj
try
close access fileRefr
end try
if (errNum is equal to -48) then
--display dialog "File exists"
do shell script "rm " & quoted form of POSIX path of file_name
my make_report()
else
display dialog "There has been an error creating the file:" & return & return & (badObj as string) & errx & return & "error number: " & errNum buttons {"Cancel"}
end if
end try
end make_report


to add_this_to_tempContents(x)
copy x as string to end of tempContents
end add_this_to_tempContents

to tell_everybody(theNews, sec)
tell application "QLab"
if frontmost then
display dialog theNews buttons {"*"} giving up after sec with icon 1
end if
end tell
end tell_everybody

to transform_seconds_to_time(x)


if x > 0 then
set curHour to (x div 3600)
set curHour to pad_number(curHour) as string


if x > 3600 then set x to (x - (curHour * 3600))


set curMin to (x div 60)
set curMin to pad_number(curMin) as string



set curSec to x mod 60
set curSec to ((curSec * 100) div 1) / 100 (* Set seconds to 1/100 places *)
set curSec to pad_number(curSec) as string
if length of curSec = 4 then set curSec to curSec & "0" (* need this in case the seconds is a clean 1/10 of a second *)
else
set curHour to "00"
set curMin to "00"
set curSec to "00.00"
end if




set fullTime to (curHour & ":" & curMin & ":" & curSec)


return fullTime


end transform_seconds_to_time

to transform_wait_to_time(x)


if x > 0 then
set curHour to (x div 3600)
set curHour to pad_number(curHour) as string


if x > 3600 then set x to (x - (curHour * 3600))


set curMin to (x div 60)
set curMin to pad_number(curMin) as string



set curSec to (x - ((curHour as number) * 3600) - ((curMin as number) * 60)) div 1
set curSec to pad_number(curSec) as string


set curFraction to ((x - ((curHour as number) * 3600) - ((curMin as number) * 60) - curSec as number) * 10) as string
set curFraction to (get text 1 of curFraction) & (get text 3 through end of curFraction)


else
set curHour to "00"
set curMin to "00"
set curSec to "00"
set curFraction to "00"
end if




set fullTime to (curHour & ":" & curMin & ":" & curSec & "." & curFraction)
return fullTime


end transform_wait_to_time



to pad_number(x)
if x < 10 and x 1 then
set x to "0" & x
else if (x < 1) and (x / 1 = x div 1) then (* Check for decimal point less than one*)
set x to "00" & x
else if (x < 1) and (x / 1 x div 1) then
set x to "0" & x
end if


if x = "000" then set x to "00"


return x
end pad_number

On Oct 5, 2009, at 1:03 AM, Andy Leviss wrote:

On Sun, Oct 4, 2009 at 6:04 PM, Matt Otto <mott...@gmail.com> wrote:
I was hoping someone could write a script that would create a XML file that
had all the cues and settings for each that FileMaker or Excel could open.
Ideally it includes level settings but I won’t hold my breath for that.

I may be mistaken, but I was pretty sure that Jeremy Lee was pretty
close on something along these lines, which is why he'd been posting
for certain things such as matrix/bus assignments to be available to
AppleScript a week or two ago. But maybe I misunderstood?

--A

-- 
Jeremy Lee
    Sound Designer, NYC - USA 829


Rich Walsh

unread,
Oct 5, 2009, 6:46:21 PM10/5/09
to Discussion and support for QLab users.
On 5 Oct 2009, at 03:29, Andy Dolph wrote:

> since i already know the cue numbers and file names and can easily add
> things like fade times and opacity information in FMP if I wanted to -
> I'd love to be able to export that data from FMP and import it to
> Qlab.

As I start to think about this, I'm interested in the scale of the data:

* There are 24 "cue types" that can be made or interrogated via a
script (I think), so which of these is essential in your non-QLab files?

Group, Cue List, Audio, Fade, Video, Animation, Camera, MIDI, MSC,
MIDI SysEx, MTC, Devamp, Load, Target, Start, Stop, Reset, Script,
Goto, Wait, Memo, Arm, Disarm, SoundMan

* There are a total of 80 properties (again, I think) for those cue
types, most of which don't apply to most of them (and some cue types,
such as Script & SoundMan, don't have scriptable properties for their
key content). How many of these 80 columns are going to be in your
files?

q name, q number, notes, 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, cue target, file target, 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,
start value, 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, fire next cue when loop ends, stop target
when loop ends, load time, assign number

* For reporting, there are 3 other variables of interest: uniqueID,
broken & audio input channels.

* Chris will no doubt add more as time progresses, eg: "hot key".

* I think there are 882 possible levels in any audio/video cue (not to
mention the device matrices).

I think an Excel file with type+properties+levels = 966 columns, or a
FileMaker database with 966 fields, would be unmanageable. Is the
subset that Jeremy has chosen too small, too big or just right for
most people?

I wonder if it's possible to extract the properties that are going to
be handled from the header row of a tab-delimited text file? That will
keep me busy for a bit...

Rich

Matt Otto

unread,
Oct 5, 2009, 7:04:52 PM10/5/09
to Discussion and support for QLab users.
I am only one man but here are the things that are interesting to me specifically


Cue Types:
Group, Cue List, Audio, Fade, Start, Stop, Pause, Goto, & Wait. 
I’d also throw in the MIDI cue stuff but I actually do not do much work with those so they’d really be for good measure only.

Properties:
q name, q number, pre wait, duration, post wait, continue mode, start time, end time, loop start time, loop end time, loop count, & infinite loop
As for levels I’d be happy with just the fader levels. What is displayed in the top field above each fader.

Concerning format Tab Delineated is fine but XML would be really great. Something similar to the iTunes Music Library.xml file. Where its able to be opened by a text editor and read easily without any other bubo jumbo screwing it up.

Christopher Ashworth

unread,
Oct 5, 2009, 7:28:31 PM10/5/09
to Discussion and support for QLab users.
A general "note from experience" on storing levels in a file:

QLab stores each level matrix as a sparse matrix. This was necessary
to keep workspace file sizes reasonable. Internally QLab is "future-
proof" to the tune of matrices up to 1024 inputs and outputs. It was
critical to store those as a sparse matrix, because a few of those
stored naively (i.e. actually storing all the values) would create
gigantic files. Using more realistic matrices (i.e. smaller ones)
this may or may not come up as an issue.

> Concerning format Tab Delineated is fine but XML would be really
> great.

Why?

> Where its able to be opened by a text editor and read easily without
> any other bubo jumbo screwing it up.

That sounds like tab delineated to me.

If there's a specific reason to use XML, then sure, but in my
experience XML has a tendency to be the "cool" format that's used even
when it's inappropriate.

Anyway, carry on. I speak primarily as a fascinated observer; don't
let me get in the way of whatever you want to do with scripting. I
continue to be awe-struck by the stuff Rich is making.

-C

Jeremy Lee

unread,
Oct 5, 2009, 8:24:17 PM10/5/09
to Discussion and support for QLab users.
Wow. Sparse Matrixes are something so cool that I'm glad I don't have
to get near them. I'd freeze my nose off...

On Oct 5, 2009, at 7:28 PM, Christopher Ashworth wrote:

> QLab stores each level matrix as a sparse matrix. This was
> necessary to keep workspace file sizes reasonable. Internally QLab

> is "future-proof" to the tune of matrices up to 1024 inputs and

> outputs. It was critical to store those as a sparse matrix, because
> a few of those stored naively (i.e. actually storing all the values)
> would create gigantic files. Using more realistic matrices (i.e.
> smaller ones) this may or may not come up as an issue.

--

Jeremy Lee
Sound Designer, NYC - USA 829
http://www.jjlee.com

Andy Dolph

unread,
Oct 5, 2009, 10:12:57 PM10/5/09
to Discussion and support for QLab users.
in addition to the ones that Matt listed, I'd need:
Video, Animation, Midi, MSC and Load cues

Properties
cue target, file target, 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

I'd be happy with some sort of limited number of levels like say 16 -
that'd be plenty for my needs...

Andy

Rich Walsh

unread,
Oct 5, 2009, 10:31:34 PM10/5/09
to Discussion and support for QLab users.
On 6 Oct 2009, at 00:28, Christopher Ashworth wrote:

> Anyway, carry on. I speak primarily as a fascinated observer; don't
> let me get in the way of whatever you want to do with scripting. I
> continue to be awe-struck by the stuff Rich is making.

Now if only someone would say that about my sound designs...

Still, this half-written bit of nonsense will (I think) take a tab-
delimited text file with column headers that match any selection of
the available properties for cues and then trundle through it making
cues and setting those properties. That way it's up to you what fields
to include - but you must have a "Type" column and you must use
entries that match those in QLab's AppleScript dictionary (for now).
For example, a column would have to be called "continue mode" and have
entries "do_not_continue", "auto_continue" or "auto_follow" to be of
any use. File targets work if you paste the full path in "alias" form,
ie: "/Users/You/Sounds/thesound.wav".

Oh, and because I got bored I've only set it up to handle (almost) all
the properties for Audio & Memo cues at the moment (other types will
be made, but not all properties will be set). I'll do the other 50 if
clauses at some point...

It would be really helpful if some of the people who want this could
try it out and check for hidden surprises (not least, typos), as I'm
not prepared to test it extensively myself! The kind of thing that is
useful to find out is that if you try to set a file target from a
blank entry in your text file then the Post Wait gets corrupted for
some reason, so I had to build some protection in there.

Have fun. Oh, I haven't even thought about levels yet.

Rich

****

(* 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

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)

<<< Last tested with: QLab 2.2.4 >>> *)

-- ###BUG TBC### Not tested at all!
-- ###ADD### Haven't thought about levels yet!

-- Declarations

global currentTIDs
set currentTIDs to AppleScript's text item delimiters

set acceptableColumnHeaders to {"Type", "q name", "q number", "notes",
"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", "cue target", "file target", "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", "start value", "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", "fire next cue when loop ends", "stop
target when loop ends", "load time", "assign number"} -- All possible
properties (order is based on entries in QLab's AppleScript dictionary)
set acceptableTypes to {"Group", "Cue List", "Audio", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"}
set propertiesToColumns to {}

-- This is a list of properties that can be set for each cue type ###
Check these! Rationalise (not all are needed, eg: q name)

set qnameIndex to {"Group", "Cue List", "Audio", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"}
set qNumberIndex to {"Group", "Cue List", "Audio", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"}
set notesIndex to {"Group", "Cue List", "Audio", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"}
set preWaitIndex to {"Group", "Cue List", "Audio", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"}
set durationIndex to {"Group", "Cue List", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"} -- Can't set one for Audio or
Memo Cues ### Info established so far
set postWaitIndex to {"Group", "Cue List", "Audio", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"}
set continueModeIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set armedIndex to {"Group", "Cue List", "Audio", "Fade", "Video",
"Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC", "Devamp",
"Load", "Target", "Start", "Stop", "Reset", "Script", "Goto", "Wait",
"Memo", "Arm", "Disarm", "SoundMan"}
set midiTriggerIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set midiCommandIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set midiByteOneIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set midiByteTwoIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set timecodeTriggerIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set wallClockTriggerIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set wallClockHoursIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set wallClockMinutesIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set wallClockSecondsIndex to {"Group", "Cue List", "Audio", "Fade",
"Video", "Animation", "Camera", "MIDI", "MSC", "MIDI SysEx", "MTC",
"Devamp", "Load", "Target", "Start", "Stop", "Reset", "Script",
"Goto", "Wait", "Memo", "Arm", "Disarm", "SoundMan"}
set cueTargetIndex to {"Fade", "Animation", "Devamp", "Load",
"Target", "Start", "Stop", "Reset", "Goto", "Arm", "Disarm"}
set fileTargetIndex to {"Audio", "Video"}
set modeIndex to {"Group", "Cue List"}
set syncToTimecodeIndex to {"Cue List"}
set syncModeIndex to {"Cue List"}
set smpteFormatIndex to {"Cue List", "MSC", "MTC"}
set mtcSyncSourceNameIndex to {"Cue List"}
set ltcSyncChannelIndex to {"Cue List"}
set patchIndex to {"Audio", "Video", "Camera", "MIDI", "MSC", "MIDI
SysEx"}
set startTimeIndex to {"Audio", "Video", "MTC"}
set endTimeIndex to {"Audio", "Video"}
set loopStartTimeIndex to {"Audio"}
set loopEndTimeIndex to {"Audio"}
set loopCountIndex to {"Audio"}
set infiniteLoopIndex to {"Audio", "Video"}
set guaranteeSyncIndex to {"Audio"}
set integratedFadeIndex to {"Audio"}
set fadeModeIndex to {"Fade"}
set stopTargetWhenDoneIndex to {"Fade", "Animation"}
set autoStopIndex to {"Video"}
set layerIndex to {"Video", "Camera"}
set fullScreenIndex to {"Video", "Camera"}
set preserveAspectRatioIndex to {"Video", "Camera"}
set opacityIndex to {"Video", "Animation", "Camera"}
set translationXIndex to {"Video", "Animation", "Camera"}
set translationYIndex to {"Video", "Animation", "Camera"}
set rotationIndex to {"Video", "Animation", "Camera"}
set scaleXIndex to {"Video", "Animation", "Camera"}
set scaleYIndex to {"Video", "Animation", "Camera"}
set scaleLockedIndex to {"Video", "Animation", "Camera"}
set customRenderingIndex to {"Video", "Camera"}
set doOpacityIndex to {"Animation"}
set doTranslationIndex to {"Animation"}
set doRotationIndex to {"Animation"}
set doScaleIndex to {"Animation"}
set commandIndex to {"MIDI"}
set channelIndex to {"MIDI"}
set byteOneIndex to {"MIDI"}
set byteTwoIndex to {"MIDI"}
set byteComboIndex to {"MIDI"}
set startValueIndex to {"MIDI"}
set endValueIndex to {"MIDI"}
set fadeIndex to {"MIDI"}
set commandFormatIndex to {"MSC"}
set commandNumberIndex to {"MSC"}
set q_NumberIndex to {"MSC"}
set q_ListIndex to {"MSC"}
set q_PathIndex to {"MSC"}
set macroIndex to {"MSC"}
set controlNumberIndex to {"MSC"}
set controlValueIndex to {"MSC"}
set hoursIndex to {"MSC"}
set minutesIndex to {"MSC"}
set secondsIndex to {"MSC"}
set framesIndex to {"MSC"}
set subframesIndex to {"MSC"}
set sendTimeWithSetIndex to {"MSC"}
set sysExMessageIndex to {"MIDI SysEx"}
set midiDestinationIndex to {"MTC"}
set fireNextCueWhenLoopEndsIndex to {"Devamp"}
set stopTargetWhenLoopEndsIndex to {"Devamp"}
set loadTimeIndex to {"Load"}
set assignNumberIndex to {"Target"}

try -- This overall try make sure TIDs are reset if any "Cancel"
button is pushed

-- Preamble ### Write all this... Have to use very specific script
terms (do_not_continue) at the moment...

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 "Make
cues from a text file" 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
display dialog "This script will take seven and a half million
years to write..." with title "Make cues from a text file" with icon 1
buttons {"OK"} default button "OK"
end if
end repeat

-- Check QLab is running

if running of application "QLab" is false then
display dialog "QLab is not running." with title "Make cues from a
text file" 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
"Make cues from a text file" with icon 0 buttons {"OK"} default button
"OK" giving up after 5
return
end try
end tell

-- Get the file & set up translation matrix

set theFile to choose file with prompt "Please select a tab-delimited
text file:" default location (path to desktop) without invisibles

set theText to read theFile

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! ### Put custom dialog here
my exitStrategy()
return
end if

repeat with i from 1 to count of 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 of headerRow
if text j of headerRow is item i of acceptableColumnHeaders then
set item i of propertiesToColumns to j
end if
end repeat
end repeat

set typeColumn to item 1 of propertiesToColumns

-- How long is this going to take? ### Write this bit

set countText to count paragraphs of theText

-- Now, to business

tell application "QLab"

activate

display dialog "One moment caller..." with title "Make cues from a
text file" with icon 1 buttons {"OK"} default button "OK" giving up
after 2

set startTime to time of (current date)

repeat with i from 2 to countText -- Skip the header row
set theRecord to every text item of paragraph i of theText
set theType to item typeColumn of theRecord

if theType is in acceptableTypes then
make front workspace type theType
else
exit repeat
end if

set newCue to last item of (selected of front workspace as list)
set notes of newCue to "Made from line " & i & " of text file:" &
tab & paragraph i of theText -- ### Add name of file?

if theType is in qnameIndex and item 2 of propertiesToColumns is
not 0 then
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 q name of newCue to item (item 2 of propertiesToColumns) of
theRecord as text
end try
end if

if theType is in qNumberIndex and item 3 of propertiesToColumns is
not 0 then
try
set q number of newCue to item (item 3 of propertiesToColumns) of
theRecord as text
end try
end if

if theType is in notesIndex and item 4 of propertiesToColumns is
not 0 then -- ### Some properties are in every cue so this could be
tidied up
try
set newNotes to item (item 4 of propertiesToColumns) of theRecord
if newNotes is not "" then
set existingNotes to notes of newCue
set notes of newCue to newNotes & return & return & existingNotes
end if
end try
end if

if theType is in preWaitIndex and item 5 of propertiesToColumns is
not 0 then
try
set pre wait of newCue to item (item 5 of propertiesToColumns) of
theRecord as real
end try
end if

if theType is in durationIndex and item 6 of propertiesToColumns is
not 0 then
try
set duration of newCue to item (item 6 of propertiesToColumns) of
theRecord as real
end try
end if

if theType is in postWaitIndex and item 7 of propertiesToColumns is
not 0 then
try
set post wait of newCue to item (item 7 of propertiesToColumns)
of theRecord as real
end try
end if

if theType is in continueModeIndex and item 8 of
propertiesToColumns is not 0 then
set continueModeConstant to item (item 8 of propertiesToColumns)
of theRecord
if continueModeConstant is "do_not_continue" then
set continue mode of newCue to do_not_continue
else if continueModeConstant is "auto_continue" then
set continue mode of newCue to auto_continue
else if continueModeConstant is "auto_follow" then
set continue mode of newCue to auto_follow
end if
end if

if theType is in armedIndex and item 9 of propertiesToColumns is
not 0 then
try
set armed of newCue to item (item 9 of propertiesToColumns) of
theRecord as boolean
end try
end if

if theType is in midiTriggerIndex and item 10 of
propertiesToColumns is not 0 then
try
set midiTriggerConstant to item (item 10 of propertiesToColumns)
of theRecord
if midiTriggerConstant is "enabled" then
set midi trigger of newCue to enabled
else if midiTriggerConstant is "disabled" then
set midi trigger of newCue to disabled
end if
end try
end if

(* if theType is in midiCommandIndex and item 11 of
propertiesToColumns is not 0 then
try
set midi command of newCue to item (item 11 of
propertiesToColumns) of theRecord
end try
end if ### Come back to this one! *)

if theType is in midiByteOneIndex and item 12 of
propertiesToColumns is not 0 then
try
set midi byte one of newCue to item (item 12 of
propertiesToColumns) of theRecord as integer
end try
end if

if theType is in midiByteTwoIndex and item 13 of
propertiesToColumns is not 0 then
try
set midi byte two of newCue to item (item 13 of
propertiesToColumns) of theRecord as integer
end try
end if

if theType is in timecodeTriggerIndex and item 14 of
propertiesToColumns is not 0 then
try
set timecodeTriggerConstant to item (item 14 of
propertiesToColumns) of theRecord
if timecodeTriggerConstant is "enabled" then
set timecode trigger of newCue to enabled
else if timecodeTriggerConstant is "disabled" then
set timecode trigger of newCue to disabled
end if
end try
end if

if theType is in wallClockTriggerIndex and item 15 of
propertiesToColumns is not 0 then
try
set wallClockTriggerConstant to item (item 15 of
propertiesToColumns) of theRecord
if wallClockTriggerConstant is "enabled" then
set wall clock trigger of newCue to enabled
else if wallClockTriggerConstant is "disabled" then
set wall clock trigger of newCue to disabled
end if
end try
end if

if theType is in wallClockHoursIndex and item 16 of
propertiesToColumns is not 0 then
try
set wall clock hours of newCue to item (item 16 of
propertiesToColumns) of theRecord as integer
end try
end if

if theType is in wallClockMinutesIndex and item 17 of
propertiesToColumns is not 0 then
try
set wall clock minutes of newCue to item (item 17 of
propertiesToColumns) of theRecord as integer
end try
end if


if theType is in wallClockSecondsIndex and item 18 of
propertiesToColumns is not 0 then
try
set wall clock seconds of newCue to item (item 18 of
propertiesToColumns) of theRecord as integer
end try
end if

-- ### Finish this list

if theType is in fileTargetIndex and item 20 of propertiesToColumns
is not 0 then
try
set targetTest to item (item 20 of propertiesToColumns) of
theRecord -- Protects against trying to set an empty field which seems
to corrupt the Post Wait
if targetTest is not "" then
set file target of newCue to targetTest
end if
end try
end if

-- ### Finish this list

if theType is in patchIndex and item 27 of propertiesToColumns is
not 0 then
try
set patch of newCue to item (item 27 of propertiesToColumns) of
theRecord as integer
end try
end if


if theType is in startTimeIndex and item 28 of propertiesToColumns
is not 0 then
try
set start time of newCue to item (item 28 of propertiesToColumns)
of theRecord as real
end try
end if


if theType is in endTimeIndex and item 29 of propertiesToColumns is
not 0 then
try
set end time of newCue to item (item 29 of propertiesToColumns)
of theRecord as real
end try
end if

if theType is in loopStartTimeIndex and item 30 of
propertiesToColumns is not 0 then
try
set loop start time of newCue to item (item 30 of
propertiesToColumns) of theRecord as real
end try
end if

if theType is in loopEndTimeIndex and item 31 of
propertiesToColumns is not 0 then
try
set loop end time of newCue to item (item 31 of
propertiesToColumns) of theRecord as real
end try
end if


if theType is in loopCountIndex and item 32 of propertiesToColumns
is not 0 then
try
set loop count of newCue to item (item 32 of propertiesToColumns)
of theRecord as integer
end try
end if

if theType is in infiniteLoopIndex and item 33 of
propertiesToColumns is not 0 then
try
set infinite loop of newCue to item (item 33 of
propertiesToColumns) of theRecord as boolean
end try
end if


if theType is in guaranteeSyncIndex and item 34 of
propertiesToColumns is not 0 then
try
set guarantee sync of newCue to item (item 34 of
propertiesToColumns) of theRecord as boolean
end try
end if

if theType is in integratedFadeIndex and item 35 of
propertiesToColumns is not 0 then
set integratedFadeConstant to item (item 35 of
propertiesToColumns) of theRecord
if integratedFadeConstant is "enabled" then
set integrated fade of newCue to enabled
else if integratedFadeConstant is "disabled" then
set integrated fade of newCue to disabled
end if
end if

-- ### Finish this list

end repeat

set timeTaken to ((time of (current date)) - startTime) as integer
set timeString to my makeNiceTWithZero(timeTaken)
display dialog "Done. (That took " & timeString & ".)" with title
"Make cues from a text file" with icon 1 buttons {"OK"} default button
"OK" giving up after 3

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 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 "Make
cues from a text file" with icon 0 buttons {"OK"} default button "OK"
set AppleScript's text item delimiters to currentTIDs
end exitStrategy

on makeNiceTWithZero(howLong)
if howLong is 0 then
return "less than a second"
end if
set howManyMinutes to howLong 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 minuteString is not "" and secondString is not "" then
set theAmpersand to " and "
else
set theAmpersand to ""
end if
return minuteString & theAmpersand & secondString
end makeNiceTWithZero

****

Here is an example of what could be in the text file:

q number Type q name post wait continue mode
1 Audio Make a noise 5 auto_follow
2 Memo Make a note 0 do_not_continue

Rich Walsh

unread,
Oct 6, 2009, 12:04:34 PM10/6/09
to Discussion and support for QLab users.
I've done some more work on the "Make cues from a text file" script; I
think there's just some tedious copying & pasting left to do now (all
those commented out lines need to be turned into commands) - and a lot
of testing...

I need to write the instructions properly, but hopefully you'll get
the gist. I'm quite proud of the levels bit, actually: if you add a
column titled "0,0" then entries in that column will be applied to
crosspoint row 0 column 0 (ie: the Master level) - and so on.

Please, please try to break it, and send me some text files to try
out! Properties 21-26 & 36-81 obviously won't work yet.

Rich

****

(* 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
display dialog 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)

<<< Last tested with: QLab 2.2.4 >>> *)

-- ###BUG TBC### Not tested at all!

-- Declarations

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", "start value", "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", "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 reportingOnlyColumns to {"unique ID", "broken", "audio input
channels"} -- Not needed in this script; for reference {text, boolean,
integer}

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 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:
do_not_continue/auto_continue/auto_follow)
-- set index11_armed: every cue has armed (boolean)
-- set index12_midi_trigger: every cue has midi trigger (constants:
enabled/disabled)
-- set index13_midi_command: every cue has midi command (constants:
note_on/note_off/program_change/control_change/key_pressure/
channel_pressure/pitch_bend)
-- 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: enabled/disabled)
-- set index17_wall_clock_trigger: every cue has wall clock trigger
(constants: enabled/disabled)
-- 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: cue_list/
fire_first_enter_group/fire_first_go_to_next_cue/fire_all/fire_random)
set index22_sync_to_timecode to {"Cue List"} -- (constants: enabled/
disabled)
set index23_sync_mode to {"Cue List"} -- (constants: mtc/ltc)
set index24_smpte_format to {"Cue List", "MSC", "MTC"} -- (constants:
4_fps/25_fps/30_fps_drop/30_fps_non_drop)
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", "MTC"} -- (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: enabled/
disabled)
set index36_fade_mode to {"Fade"} -- (constants: absolute/relative)
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: note_on/note_off/
program_change/control_change/key_pressure/channel_pressure/pitch_bend)
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_start_value to {"MIDI"} -- (integer)
set index60_end_value to {"MIDI"} -- (integer)
set index61_fade to {"MIDI"} -- (constants: enabled/disabled)
set index62_command_format to {"MSC"} -- (integer)
set index63_command_number to {"MSC"} -- (integer)
set index64_q_number to {"MSC"} -- (text)
set index65_q_list to {"MSC"} -- (text)
set index66_q_path to {"MSC"} -- (text)
set index67_macro to {"MSC"} -- (integer)
set index68_control_number to {"MSC"} -- (integer)
set index69_control_value to {"MSC"} -- (integer)
set index70_hours to {"MSC"} -- (integer)
set index71_minutes to {"MSC"} -- (integer)
set index72_seconds to {"MSC"} -- (integer)
set index73_frames to {"MSC"} -- (integer)
set index74_subframes to {"MSC"} -- (integer)
set index75_send_time_with_set to {"MSC"} -- (boolean)
set index76_sysex_message to {"MIDI SysEx"} -- (text)
set index77_midi_destination to {"MTC"} -- (text)
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_set_level to {"Audio", "Fade", "Video"}

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 ### Write all this...

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 "Make
cues from a text file" 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
display dialog "This script will take seven and a half million
years to write...

Working notes:

Column layout; need for \"type\" column; use strings exactly as in
AppleScript dictionary (see acceptableColumnHeaders in script file),
and values for each index variables.
Not doing cue lists; make a Group Cue instead and move it. Note that
if you select a cue within a Group Cue, cues will be added inside the
group.
How to do groups: add column \"put in group\", enter q number of
destination group; must have numbers in both cue & group
Rely quite heavily on q numbers! All kinds of exciting things can go
wrong if they already exist...
Levels: \"0,0\" header specifies row 0 column 0 (ie: Master), so add
column headers of this form for levels you want to set. Default gangs
will catch you out.
You can't reference cues that don't exist yet in cue targets :-(.
Not a lot of protection against you getting the file wrong..." with

title "Make cues from a text file" with icon 1 buttons {"OK"} default
button "OK"
end if
end repeat

-- Check QLab is running

if running of application "QLab" is false then
display dialog "QLab is not running." with title "Make cues from a
text file" 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
"Make cues from a text file" 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 ""

set theText to read theFile

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 theNameList to characters 1 through ((length of theFullName) -
(length of theExtension) - 1) of theFullName
set theName to theNameList as text
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 "Make cues from a text file" 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 of 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 of 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

repeat with i from 1 to count of 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 propertiesToColumns

-- Annotate every line?

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 "Make cues from a text file"
with icon 1 buttons {"Yes", "No"} default button "No")



-- How long is this going to take? ### Write this bit

set countText to count paragraphs of theText

-- Now, to business

tell application "QLab"

activate

display dialog "One moment caller..." with title "Make cues from a
text file" with icon 1 buttons {"OK"} default button "OK" giving up
after 2

set startTime to time of (current date)

repeat with i from 2 to countText -- Skip the header row
set theRecord to every text item of paragraph i of theText

try


set theType to item typeColumn of theRecord

on error
set theType to "Unacceptable" -- Flag it for the next stage
end try

if theType is not in acceptableTypes then
make front workspace type "Memo"


set newCue to last item of (selected of front workspace as list)

set q name of newCue to "!!!! Unprocessed line"


set AppleScript's text item delimiters to " | "

set niceParagraph to theRecord as text


set AppleScript's text item delimiters to tab

set notes of newCue to "Unprocessed line " & i & " of text file
\"" & theName & "\": | " & niceParagraph & " |"

else


make front workspace type theType

set newCue to last item of (selected of front workspace as list)

if annotateEveryLine is "Yes" then


set AppleScript's text item delimiters to " | "

set niceParagraph to theRecord as text


set AppleScript's text item delimiters to tab

set notes of newCue to "Made from line " & i & " of text file \""

& theName & "\": | " & niceParagraph & " |"
end if

if item 2 of propertiesToColumns 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

(or if a line is half-empty)
set q number of newCue to item (item 2 of propertiesToColumns)
of theRecord as string -- Not using "text" as TIDs are inappropriate
at the moment
end try
end if

if item 3 of propertiesToColumns is not 0 then -- index3_q_name
try
set q name of newCue to item (item 3 of propertiesToColumns) of
theRecord as string
end try
end if

if item 4 of propertiesToColumns is not 0 then -- index4_notes


try
set newNotes to item (item 4 of propertiesToColumns) of

theRecord as string
if newNotes is not "" then -- Prevents returns being added
before line from text file if no notes given for cue


set existingNotes to notes of newCue
set notes of newCue to newNotes & return & return & existingNotes
end if
end try
end if

if theType is in index5_cue_target and item 5 of

propertiesToColumns is not 0 then
try

set cueTargetTest to item (item 5 of propertiesToColumns) of
theRecord as string
set targetCue to (first cue in front workspace whose q number is
cueTargetTest)
set cue target of newCue to targetCue
end try
end if

if theType is in index6_file_target and item 6 of

propertiesToColumns is not 0 then
try

set fileTargetTest to item (item 6 of propertiesToColumns) of
theRecord
if fileTargetTest is not "" then
set file target of newCue to fileTargetTest


end if
end try
end if

if item 7 of propertiesToColumns is not 0 then -- index7_pre_wait
try
set pre wait of newCue to item (item 7 of propertiesToColumns)
of theRecord as number -- This seems to prevent empty entries being
parsed ("real" does not)
end try
end if

if theType is in index8_duration and item 8 of propertiesToColumns
is not 0 then
try
set duration of newCue to item (item 8 of propertiesToColumns)
of theRecord as number
end try
end if

if item 9 of propertiesToColumns is not 0 then -- index9_post_wait
try
set post wait of newCue to item (item 9 of propertiesToColumns)
of theRecord as number
end try
end if

if item 10 of propertiesToColumns is not 0 then --
index10_continue_mode
try
set continueModeConstant to item (item 10 of
propertiesToColumns) of theRecord


if continueModeConstant is "do_not_continue" then
set continue mode of newCue to do_not_continue
else if continueModeConstant is "auto_continue" then
set continue mode of newCue to auto_continue
else if continueModeConstant is "auto_follow" then
set continue mode of newCue to auto_follow
end if

end try
end if

if item 11 of propertiesToColumns is not 0 then -- index11_armed
try
set armedTest to item (item 11 of propertiesToColumns) of
theRecord -- This prevents empty entries being treated as "false"
if armedTest is "true" then
set armed of newCue to true
else if armedTest is "false" then
set armed of newCue to false


end if
end try
end if

if item 12 of propertiesToColumns is not 0 then --
index12_midi_trigger
try
set midiTriggerConstant to item (item 12 of propertiesToColumns)
of theRecord


if midiTriggerConstant is "enabled" then
set midi trigger of newCue to enabled
else if midiTriggerConstant is "disabled" then
set midi trigger of newCue to disabled
end if
end try
end if

if item 13 of propertiesToColumns is not 0 then --
index13_midi_command
try
set midiCommandConstant to item (item 13 of propertiesToColumns)
of theRecord
if midiCommandConstant is "note_on" then
set midi command of newCue to note_on
else if midiCommandConstant is "note_off" then
set midi command of newCue to note_off
else if midiCommandConstant is "program_change" then
set midi command of newCue to program_change
else if midiCommandConstant is "control_change" then
set midi command of newCue to control_change
else if midiCommandConstant is "key_pressure" then
set midi command of newCue to key_pressure
else if midiCommandConstant is "channel_pressure" then
set midi command of newCue to channel_pressure
else if midiCommandConstant is "pitch_bend" then
set midi command of newCue to pitch_bend


end if
end try
end if

if item 14 of propertiesToColumns is not 0 then --
index14_midi_byte_one
try
set midi byte one of newCue to item (item 14 of

propertiesToColumns) of theRecord as integer
end try
end if

if item 15 of propertiesToColumns is not 0 then --
index15_midi_byte_two
try
set midi byte two of newCue to item (item 15 of

propertiesToColumns) of theRecord as integer
end try
end if

if item 16 of propertiesToColumns is not 0 then --
index16_timecode_trigger
try
set timecodeTriggerConstant to item (item 16 of
propertiesToColumns) of theRecord


if timecodeTriggerConstant is "enabled" then
set timecode trigger of newCue to enabled
else if timecodeTriggerConstant is "disabled" then
set timecode trigger of newCue to disabled
end if
end try
end if

if item 17 of propertiesToColumns is not 0 then --
index17_wall_clock_trigger
try
set wallClockTriggerConstant to item (item 17 of
propertiesToColumns) of theRecord


if wallClockTriggerConstant is "enabled" then
set wall clock trigger of newCue to enabled
else if wallClockTriggerConstant is "disabled" then
set wall clock trigger of newCue to disabled
end if
end try
end if

if item 18 of propertiesToColumns is not 0 then --
index18_wall_clock_hours
try
set wall clock hours of newCue to item (item 18 of

propertiesToColumns) of theRecord as integer
end try
end if

if item 19 of propertiesToColumns is not 0 then --
index19_wall_clock_minutes
try
set wall clock minutes of newCue to item (item 19 of

propertiesToColumns) of theRecord as integer
end try
end if

if item 20 of propertiesToColumns is not 0 then --
index20_wall_clock_seconds
try
set wall clock seconds of newCue to item (item 20 of

propertiesToColumns) of theRecord as integer
end try
end if

-- ### set index21_mode to {"Cue List", "Group"} -- (constants:
cue_list/fire_first_enter_group/fire_first_go_to_next_cue/fire_all/
fire_random)
--set index22_sync_to_timecode to {"Cue List"} -- (constants:
enabled/disabled)
--set index23_sync_mode to {"Cue List"} -- (constants: mtc/ltc)
--set index24_smpte_format to {"Cue List", "MSC", "MTC"} --
(constants: 4_fps/25_fps/30_fps_drop/30_fps_non_drop)
--set index25_mtc_sync_source_name to {"Cue List"} -- (text)
--set index26_ltc_sync_channel to {"Cue List"} -- (integer)

if theType is in index27_patch and item 27 of propertiesToColumns

is not 0 then
try
set patch of newCue to item (item 27 of propertiesToColumns) of
theRecord as integer
end try
end if

if theType is in index28_start_time and item 28 of

propertiesToColumns is not 0 then
try
set start time of newCue to item (item 28 of

propertiesToColumns) of theRecord as number
end try
end if


if theType is in index29_end_time and item 29 of

propertiesToColumns is not 0 then
try
set end time of newCue to item (item 29 of propertiesToColumns)

of theRecord as number
end try
end if

if theType is in index30_loop_start_time and item 30 of

propertiesToColumns is not 0 then
try
set loop start time of newCue to item (item 30 of

propertiesToColumns) of theRecord as number
end try
end if

if theType is in index31_loop_end_time and item 31 of

propertiesToColumns is not 0 then
try
set loop end time of newCue to item (item 31 of

propertiesToColumns) of theRecord as number
end try
end if

if theType is in index32_loop_count and item 32 of

propertiesToColumns is not 0 then
try
set loop count of newCue to item (item 32 of
propertiesToColumns) of theRecord as integer
end try
end if

if theType is in index33_infinite_loop and item 33 of

propertiesToColumns is not 0 then
try

set infiniteLoopTest to item (item 33 of propertiesToColumns) of
theRecord -- This prevents empty entries being treated as "false"
if infiniteLoopTest is "true" then
set infinite loop of newCue to true
else if infiniteLoopTest is "false" then
set infinite loop of newCue to false


end if
end try
end if

if theType is in index34_guarantee_sync and item 34 of

propertiesToColumns is not 0 then
try

set guaranteeSyncTest to item (item 34 of propertiesToColumns)
of theRecord -- This prevents empty entries being treated as "false"
if guaranteeSyncTest is "true" then
set guarantee sync of newCue to true
else if guaranteeSyncTest is "false" then
set guarantee sync of newCue to false


end if
end try
end if

if theType is in index35_integrated_fade and item 35 of

propertiesToColumns is not 0 then
set integratedFadeConstant to item (item 35 of
propertiesToColumns) of theRecord
if integratedFadeConstant is "enabled" then
set integrated fade of newCue to enabled
else if integratedFadeConstant is "disabled" then
set integrated fade of newCue to disabled
end if
end if

-- ### set index36_fade_mode to {"Fade"} -- (constants: absolute/
relative)
--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: note_on/note_off/
program_change/control_change/key_pressure/channel_pressure/pitch_bend)
--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_start_value to {"MIDI"} -- (integer)
--set index60_end_value to {"MIDI"} -- (integer)
--set index61_fade to {"MIDI"} -- (constants: enabled/disabled)
--set index62_command_format to {"MSC"} -- (integer)
--set index63_command_number to {"MSC"} -- (integer)
--set index64_q_number to {"MSC"} -- (text)
--set index65_q_list to {"MSC"} -- (text)
--set index66_q_path to {"MSC"} -- (text)
--set index67_macro to {"MSC"} -- (integer)
--set index68_control_number to {"MSC"} -- (integer)
--set index69_control_value to {"MSC"} -- (integer)
--set index70_hours to {"MSC"} -- (integer)
--set index71_minutes to {"MSC"} -- (integer)
--set index72_seconds to {"MSC"} -- (integer)
--set index73_frames to {"MSC"} -- (integer)
--set index74_subframes to {"MSC"} -- (integer)
--set index75_send_time_with_--set to {"MSC"} -- (boolean)
--set index76_sysex_message to {"MIDI SysEx"} -- (text)
--set index77_midi_destination to {"MTC"} -- (text)
--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)

if item 82 of propertiesToColumns is not 0 then -- Make a list of
cues to move later
try
if item (item 82 of propertiesToColumns) of theRecord is not ""
then
copy item (item 2 of propertiesToColumns) of theRecord to end
of cuesToMove
copy item (item 82 of propertiesToColumns) of theRecord to end
of cuesToMove


end if
end try
end if

-- Deal with levels

if theType is in index_set_level then
set AppleScript's text item delimiters to ","
repeat with eachLevelColumn in levelColumns
try
if item eachLevelColumn of theRecord is not "" then
set theRow to text item 1 of item eachLevelColumn of headerRow
as integer
set theColumn to text item 2 of item eachLevelColumn of
headerRow as integer
set theLevel to item eachLevelColumn of theRecord as real
newCue setLevel row theRow column theColumn db theLevel
end if
end try
end repeat


set AppleScript's text item delimiters to tab

end if

end if

-- Countdown timer (and opportunity to escape)

if i mod 50 is 0 then


set timeTaken to ((time of (current date)) - startTime) as integer

set timeString to my makeMMSS(timeTaken)
if frontmost then
display dialog (("Time elapsed: " & timeString & " - " & i as
string) & " of " & countText as string) & " lines done..." with title
"Make cues from a text file" 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 of cuesToMove by 2
try
set cueToMoveNumber to item i of cuesToMove
set destinationNumber to item (i + 1) of cuesToMove
tell front workspace
move cue cueToMoveNumber of the current cue list to end of cue
destinationNumber
end tell
end try
end repeat

-- All done. Hoopla!



set timeTaken to ((time of (current date)) - startTime) as integer

set timeString to my makeNiceT(timeTaken)


display dialog "Done. (That took " & timeString & ".)" with title
"Make cues from a text file" with icon 1 buttons {"OK"} default button
"OK" giving up after 3

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 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 "Make
cues from a text file" with icon 0 buttons {"OK"} default button "OK"
set AppleScript's text item delimiters to currentTIDs
end exitStrategy

on makeNiceT(howLong)

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

****

Here is an example of a text file I have successfully processed
(taking 3 seconds); it includes some stuff I've worked out how to
protect against (it's much easier to read in Excel):

q number type q name duration post wait continue mode file target cue
target 0,0 0,1 0,2 put in group
1 Group Make a group
This line makes no sense
2 Audio Make a noise 5 auto_follow /System/Library/Sounds/
Basso.aiff -5 -10 1
3 Memo Make a note 3 auto_continue 1
4 Disarm Make a disarm 2 1
5 Fade Make a fade 17 2 -15 Gerald

Rich Walsh

unread,
Oct 6, 2009, 10:34:51 PM10/6/09
to Discussion and support for QLab users.
Sorry to keep posting; didn't think I'd get this finished today.

Here it is, basically finished & ready for testing. I'm not going to
do anything more with it until someone else spots a problem...

There's one rogue bit of AppleScript that won't compile: "smpte
format" won't accept the constants given in the dictionary for some
reason.

Let me know if this is useful and works for you. For my next trick I'm
going to reverse engineer this to ingest a text file with a header row
and then spit out a report based on what properties you asked for.

Rich

****

(* 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

<<< Last tested with: QLab 2.2.4 >>>

*** 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.

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. *)

-- ###BUG TBC### Not very thoroughly tested!
-- ###FIXME### QLab is, generally, increasingly unresponsive to
scripts the more cues it has in a workspace
-- ###FIXME### Review dialogs in light of this (especially ETA)
-- ###FIXME### Property "smpte format" appears to be broken in QLab

-- Declarations

-- 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", "MSC", "MTC"} -- (constants)


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", "MTC"} -- (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", "Animation", "Camera"} --
(boolean) ###FIXME### "Animation" not listed in AppleScript dictionary


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_start_value to {"MIDI"} -- (integer)
set index60_end_value to {"MIDI"} -- (integer)

set index61_fade to {"MIDI"} -- (constants)


set index62_command_format to {"MSC"} -- (integer)
set index63_command_number to {"MSC"} -- (integer)

set index64_q__number to {"MSC"} -- (text)
set index65_q__list to {"MSC"} -- (text)
set index66_q__path to {"MSC"} -- (text)


set index67_macro to {"MSC"} -- (integer)
set index68_control_number to {"MSC"} -- (integer)
set index69_control_value to {"MSC"} -- (integer)
set index70_hours to {"MSC"} -- (integer)
set index71_minutes to {"MSC"} -- (integer)
set index72_seconds to {"MSC"} -- (integer)
set index73_frames to {"MSC"} -- (integer)
set index74_subframes to {"MSC"} -- (integer)
set index75_send_time_with_set to {"MSC"} -- (boolean)
set index76_sysex_message to {"MIDI SysEx"} -- (text)
set index77_midi_destination to {"MTC"} -- (text)
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", "pitch_bend"}
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 {"24_fps", "25_fps", "30_fps_drop",
"30_fps_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 constants61_fade to {"enabled", "disabled"}
set constants75_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"}

-- 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; stupid button names needed to make dialog box big enough!



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 "Make
cues from a text file" 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.

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.

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.

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?

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 next page has some details about groups and levels..." with title
"Make cues from a text file" with icon 1 buttons {"Get on with it",
"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 "Get on with it" 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
"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.

The bigger the file the longer and longer the script takes, in a kind
of exponential way. With 500+ lines expect it to take as much as an
hour..." with title "Make cues from a text file" with icon 1 buttons
{"<<< To page 1", "Copy headers to Clipboard", "Get on with it"}
default button "Get on with it")
if instructionButton2 is "Copy headers to Clipboard" then
my toTheClipboard(acceptableColumnHeaders)
else if instructionButton2 is "Get on with it" then
set finishedReading to true
end if
end repeat
end if
end repeat

set propertiesToColumnsRef to (a reference to propertiesToColumns)



repeat with i from 1 to count of 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



-- Annotate every line?

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 "Make cues from a text file"
with icon 1 buttons {"Yes", "No"} default button "No")

-- How long is this going to take? ###TODO### These estimates are
from "Bodging a MIDI player"; data is needed for this script



set countText to count paragraphs of theText

if countText < 400 then
set theETA to 40 - 0.355 * countText + 0.005 * (countText ^ 2) --
###FIXME### Current estimate based on second order polynomial
interpolation of 3 sample data points (!); OK up to about 400 lines
else
set theETA to 158 - 1.83 * countText + 0.008 * (countText ^ 2) --
###FIXME### Current estimate based on second order polynomial
interpolation of 3 other sample data points; OK from about 400-800 lines
end if
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 "Make cues from a text file" 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 "Make cues from a
text file" with icon 1 buttons {"OK"} default button "OK" giving up
after 2

set startTime to time of (current date)

repeat with i from 2 to countText -- Skip the header row
set theRecord to every text item of paragraph i of theText

set AppleScript's text item delimiters to " | "
set niceParagraph to theRecord as text
set AppleScript's text item delimiters to tab

repeat while (count of theRecord) is less than (count of 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 front workspace type "Memo"
set newCue to last item of (selected of front workspace 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 front workspace type theType
set newCue to last item of (selected of front workspace 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 the 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 in front workspace 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
set file target of newCue to 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

else if theItem is item 7 of constants13_midi_command then


set midi command of newCue to pitch_bend
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 24_fps -- ###FIXME### Won't compile
else if theItem is item 2 of constants24_smpte_format then
set smpte format of newCue to 25_fps
else if theItem is item 3 of constants24_smpte_format then
set smpte format of newCue to 30_fps_drop
else if theItem is item 4 of constants24_smpte_format then
set smpte format of newCue to 30_fps_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
end if
on error
set ohDear to true
end try
end if

if theType is in index59_start_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
set start value of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index60_end_value and item 60 of
propertiesToColumnsRef is not 0 then
try
set theItem to item (item 60 of propertiesToColumnsRef) of
theRecordRef
if theItem is not "" then
set end value of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index61_fade and item 61 of
propertiesToColumnsRef is not 0 then
try
set theItem to item (item 61 of propertiesToColumnsRef) of
theRecordRef
if theItem is item 1 of constants61_fade then
set fade of newCue to enabled
else if theItem is item 2 of constants61_fade then
set fade of newCue to disabled
end if
on error
set ohDear to true
end try
end if

if theType is in index62_command_format and item 62 of
propertiesToColumnsRef is not 0 then
try
set theItem to item (item 62 of propertiesToColumnsRef) of
theRecordRef
if theItem is not "" then
set command format of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index63_command_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 command number of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index64_q__number 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_number of newCue to theItem
end if
on error
set ohDear to true
end try
end if

if theType is in index65_q__list 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_list of newCue to theItem
end if
on error
set ohDear to true
end try
end if

if theType is in index66_q__path 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 q_path of newCue to theItem
end if
on error
set ohDear to true
end try
end if

if theType is in index67_macro 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 macro of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index68_control_number 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 number of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index69_control_value 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 control value of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index70_hours 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 hours of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index71_minutes 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 minutes of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index72_seconds 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 seconds of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index73_frames 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 frames of newCue to theItem as integer
end if
on error
set ohDear to true
end try
end if

if theType is in index74_subframes and item 74 of
propertiesToColumnsRef is not 0 then
try
set theItem to item (item 74 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 index75_send_time_with_set and item 75 of
propertiesToColumnsRef is not 0 then
try
set theItem to item (item 75 of propertiesToColumnsRef) of
theRecordRef
if theItem is item 1 of constants75_send_time_with_set then
set send time with set of newCue to true
else if theItem is item 2 of constants75_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 index76_sysex_message 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 sysex message of newCue to theItem
end if
on error
set ohDear to true
end try
end if

if theType is in index77_midi_destination 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 midi destination of newCue to theItem
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
-- Get rid of nasty Excel formatting: 0,0 becomes \"0,0\"


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

I hope it all worked out OK..." with title "Make cues from a text

file" with icon 1 buttons {"OK"} default button "OK" giving up after 3

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 return
set the clipboard to textToCopy as text
set AppleScript's text item delimiters to currentTIDs
end toTheClipboard

****

Rich Walsh

unread,
Oct 11, 2009, 9:56:57 PM10/11/09
to Discussion and support for QLab users.
On 4 Oct 2009, at 23:04, Matt Otto wrote:

> I have no idea if this is really possible but...
>
> I was hoping someone could write a script that would create a XML
> file that had all the cues and settings for each that FileMaker or
> Excel could open. Ideally it includes level settings but I won’t
> hold my breath for that.
>
> I’d also love a script that could take a XML file and create cues
> from it. Meaning that it would create the correct type of cue and
> name it.

I have finished them both now and put them up on the wiki (I've also
put Jeremy's up there for him). They don't do XML, but as far as I can
test them they seem to work - except for a couple of little glitches
in QLab's AppleScript hooks.

"Make a text file from cues" turned out to be slightly more fiddly
than I thought having done "Make cues from a text file", otherwise I
might have finished it earlier in the week.

Let me know how you get on with them, or if you have any ideas for
improving them.

Rich

Reply all
Reply to author
Forward
0 new messages