QLab Script - batch adjust selected

Contents

Table of Contents

This is an "external script" - see QLab Scripts and Macros

(* Batch adjust selected *)
 
--
 
set theExplanation to "This script will attempt to batch adjust properties of the cues currently selected in QLab according to your instructions.
 
There is some error protection, but it is impossible to make this process completely idiot-proof. You should be warned if something threw an error, " & ¬
    "but it's not possible to track exactly what it was."
 
--
 
(* This script is not designed to be run from within QLab!
 
v1.0: 11/01/10 Rich Walsh
v1.1: 31/01/10 Lots of new options; tweaks for consistency with "All purpose enquiry"; general tidying
 
<<< Last tested with: QLab 2.2.6; Mac OS 10.5.8 & 10.6.2 >>> *)
 
-- ###FIXME### QLab and/or the "script runner" is, generally, increasingly unresponsive to scripts the more cues there are in a workspace
 
-- Declarations
 
global dialogTitle
set dialogTitle to "Batch adjust selected"
 
global startTime, ohDear, abortAbort, subChoiceArmed, subChoiceContinueMode, subChoiceMode, subChoiceGuaranteeSync
set processChoices to {"Levels", "File target", "File target (keeping times)", "Name", "Notes", "Times", "MIDI", "Armed", "Continue mode", ¬
    "Guarantee sync", "Mode", "Finished adjusting"}
set subChoiceName to {"Set", "Reset to file target", "Basic search & replace", "Add prefix", "Add suffix", "Make series"}
set subChoiceNotes to {"Clear", "Set", "Basic search & replace", "Add prefix", "Add suffix"}
set subChoiceTimesParameter to {"pre wait", "duration", "post wait"}
set subChoiceTimes to {"Set", "Scale", "Add/subtract amount"}
set subChoiceMIDIParameter to {"channel", "byte one", "byte two", "byte combo", "end value"}
set subChoiceMIDI to {"Set", "Scale", "Add/subtract amount", "Make series"}
set subChoiceArmed to {"true", "false "} -- These values can be customised as they are never used explicitly (note "false " kludge for pick from list)
set subChoiceContinueMode to {"do_not_continue", "auto_continue", "auto_follow"} -- These values can be customised as they are never used explicitly
set subChoiceGuaranteeSync to {"true", "false "} -- These values can be customised as they are never used explicitly (note "false " kludge for pick from list)
set subChoiceMode to {"fire_first_enter_group", "fire_first_go_to_next_cue", "fire_all", ¬
    "fire_random"} -- These values can be customised as they are never used explicitly
 
-- Preamble
 
set theProcess to ""
set firstTime to true
repeat until theProcess is "Finished adjusting"
 
    set ohDear to false -- A simple flag to detect problems
    set abortAbort to false -- A flag for aborting!
 
    set theProcess to my pickFromList(processChoices, theExplanation & return & return & ¬
        "So that you can run more than one process, you'll keep coming back to this screen until you hit any \"Cancel\" button, or choose \"Finished adjusting\"." & ¬
        return & return & "Choose a property category:")
 
    -- Check QLab is running
 
    if firstTime is true then -- Only need to do this step once
        tell application "System Events"
            set qLabIsRunning to count (every process whose name is "QLab")
        end tell
        if qLabIsRunning is 0 then
            display dialog "QLab is not running." with title dialogTitle with icon 0 buttons {"OK"} default button "OK" giving up after 5
            return
        end if
    end if
 
    tell application "QLab"
 
        activate
 
        -- Test for a workspace and a selection; modify options if only one cue selected
 
        if firstTime is true then -- Only need to do this step once
 
            set noSelection to false
            try
                set theSelection to (selected of front workspace as list)
                set theSelectionRef to a reference to theSelection
                set countSelection to count theSelectionRef
                if countSelection is 0 then
                    set noSelection to true
                end if
            on error
                set noSelection to true
            end try
            if noSelection is true then
                display dialog "There is no selection in QLab." with title dialogTitle with icon 0 buttons {"OK"} default button "OK" giving up after 5
                return
            end if
 
            if countSelection is 1 then
                set subChoiceName to items 1 thru ((count subChoiceName) - 1) of subChoiceName -- Remove "Make series"
                set subChoiceMIDI to items 1 thru ((count subChoiceMIDI) - 1) of subChoiceMIDI -- Remove "Make series"
            end if
 
        end if
 
        -- Find out more about what we're doing, and then call a subroutine to do it...
 
        if theProcess is "Levels" then
 
            my adjustLevels(theSelectionRef, "selected cues")
 
        else if theProcess is "File target" then
 
            my adjustFileTarget(theSelectionRef, "Set", "selected cues")
 
        else if theProcess is "File target (keeping times)" then
 
            my adjustFileTarget(theSelectionRef, "Change", "selected cues")
 
        else if theProcess is "Name" then
 
            set theChoice to my pickFromList(subChoiceName, "Choose how you would like to adjust the names of the selected cues:")
 
            if theChoice is "Set" then
                my adjustSetName(theSelectionRef, "selected cues")
            else if theChoice is "Reset to file target" then
                my adjustResetNameToFileTarget(theSelectionRef)
            else if theChoice is "Basic search & replace" then
                my adjustSearchReplaceName(theSelectionRef, "selected cues")
            else if theChoice is "Add prefix" then
                my adjustPrefixName(theSelectionRef, "selected cues")
            else if theChoice is "Add suffix" then
                my adjustSuffixName(theSelectionRef, "selected cues")
            else if theChoice is "Make series" then
                my adjustSeriesName(theSelectionRef, "selected cues")
            end if
 
        else if theProcess is "Notes" then
 
            set theChoice to my pickFromList(subChoiceNotes, "Choose how you would like to adjust the notes of the selected cues " & ¬
                "(NB: scripting of notes is plain-text only):")
 
            if theChoice is "Clear" then
                my adjustClearNotes(theSelectionRef)
            else if theChoice is "Set" then
                my adjustSetNotes(theSelectionRef, "selected cues")
            else if theChoice is "Basic search & replace" then
                my adjustSearchReplaceNotes(theSelectionRef, "selected cues")
            else if theChoice is "Add prefix" then
                my adjustPrefixNotes(theSelectionRef, "selected cues")
            else if theChoice is "Add suffix" then
                my adjustSuffixNotes(theSelectionRef, "selected cues")
            end if
 
        else if theProcess is "Times" then
 
            set parameterChoice to my pickFromList(subChoiceTimesParameter, "Choose the time parameter to adjust:")
            set theChoice to my pickFromList(subChoiceTimes, "Choose how you would like to adjust the " & parameterChoice & " of the selected cues:")
 
            if theChoice is "Set" then
                my adjustSetTime(theSelectionRef, parameterChoice, "selected cues")
            else if theChoice is "Scale" then
                my adjustScaleTime(theSelectionRef, parameterChoice, "selected cues")
            else if theChoice is "Add/subtract amount" then
                my adjustAddSubractTime(theSelectionRef, parameterChoice, "selected cues")
            end if
 
        else if theProcess is "MIDI" then
 
            set parameterChoice to my pickFromList(subChoiceMIDIParameter, ¬
                "Choose the MIDI parameter to adjust (\"byte combo\" will only affect pitch bend commands):")
            if parameterChoice is "channel" then
                set theChoice to "set" -- The other options don't make a lot of sense for channel!
            else
                set theChoice to my pickFromList(subChoiceMIDI, "Choose how you would like to adjust the " & parameterChoice & " of the selected cues:")
            end if
 
            if theChoice is "Set" then
                my adjustSetMIDI(theSelectionRef, parameterChoice, "selected cues")
            else if theChoice is "Scale" then
                my adjustScaleMIDI(theSelectionRef, parameterChoice, "selected cues")
            else if theChoice is "Add/subtract amount" then
                my adjustAddSubractMIDI(theSelectionRef, parameterChoice, "selected cues")
            else if theChoice is "Make series" then
                my adjustSeriesMIDI(theSelectionRef, parameterChoice, "selected cues")
            end if
 
        else if theProcess is "Armed" then
 
            set parameterChoice to my pickFromList(subChoiceArmed, "Set the armed of the selected cues to:")
 
            my adjustArmed(theSelectionRef, parameterChoice)
 
        else if theProcess is "Continue mode" then
 
            set parameterChoice to my pickFromList(subChoiceContinueMode, "Set the continue mode of the selected cues to:")
 
            my adjustContinueMode(theSelectionRef, parameterChoice)
 
        else if theProcess is "Guarantee sync" then
 
            set parameterChoice to my pickFromList(subChoiceGuaranteeSync, "Set the guarantee sync of the selected cues to:")
 
            my adjustGuaranteeSync(theSelectionRef, parameterChoice)
 
        else if theProcess is "Mode" then
 
            set parameterChoice to my pickFromList(subChoiceMode, "Set the mode of the selected cues to:")
 
            my adjustMode(theSelectionRef, parameterChoice)
 
        end if
 
    end tell
 
    set firstTime to false
 
end repeat
 
-- Subroutines: input
 
on pickFromList(theChoice, thePrompt)
    tell application "QLab"
        choose from list theChoice with prompt thePrompt with title dialogTitle default items item 1 of theChoice
        if the result is not false then
            return item 1 of the result
        else
            error number -128
        end if
    end tell
end pickFromList
 
on enterSomeText(thePrompt, defaultAnswer)
    tell application "QLab"
        set theAnswer to ""
        repeat until theAnswer is not ""
            set theAnswer to text returned of (display dialog thePrompt with title dialogTitle default answer defaultAnswer buttons {"Cancel", "OK"} ¬
                default button "OK" cancel button "Cancel")
        end repeat
        return theAnswer
    end tell
end enterSomeText
 
on enterAnInteger(thePrompt, defaultAnswer)
    tell application "QLab"
        set theQuestion to ""
        repeat until theQuestion is not ""
            set theQuestion to text returned of (display dialog thePrompt with title dialogTitle default answer defaultAnswer buttons {"Cancel", "OK"} ¬
                default button "OK" cancel button "Cancel")
            try
                set theAnswer to theQuestion as integer
            on error
                set theQuestion to ""
            end try
        end repeat
        return theAnswer
    end tell
end enterAnInteger
 
on enterAnIntegerWithRange(thePrompt, defaultAnswer, lowRange, highRange)
    tell application "QLab"
        set theQuestion to ""
        repeat until theQuestion is not ""
            set theQuestion to text returned of (display dialog thePrompt with title dialogTitle default answer defaultAnswer buttons {"Cancel", "OK"} ¬
                default button "OK" cancel button "Cancel")
            try
                set theAnswer to theQuestion as integer
                if theAnswer < lowRange or theAnswer > highRange then
                    set theQuestion to ""
                end if
            on error
                set theQuestion to ""
            end try
        end repeat
        return theAnswer
    end tell
end enterAnIntegerWithRange
 
on enterATimeWithCustomButton(thePrompt, defaultAnswer, customButton)
    tell application "QLab"
        set theQuestion to ""
        repeat until theQuestion is not ""
            set theResult to (display dialog thePrompt with title dialogTitle default answer defaultAnswer ¬
                buttons customButton & {"Cancel", "OK"} default button "OK" cancel button "Cancel")
            set theQuestion to text returned of theResult
            set theButton to button returned of theResult
            if theButton is (customButton as string) then
                set theAnswer to theButton
                exit repeat
            end if
            try
                set theAnswer to theQuestion as number
                if theAnswer is less than 0 then
                    set theQuestion to ""
                end if
            on error
                if theQuestion contains ":" then
                    try
                        set currentTIDs to AppleScript's text item delimiters
                        set AppleScript's text item delimiters to ":"
                        set theMinutes to word 1 of theQuestion
                        set theSeconds to rest of words of theQuestion as string
                        set AppleScript's text item delimiters to currentTIDs
                        set theAnswer to (theMinutes as number) * 60 + (theSeconds as number)
                    on error
                        set theQuestion to ""
                    end try
                else
                    set theQuestion to ""
                end if
            end try
        end repeat
        return theAnswer
    end tell
end enterATimeWithCustomButton
 
on enterARatio(thePrompt, defaultAnswer)
    tell application "QLab"
        set theQuestion to ""
        repeat until theQuestion is not ""
            set theQuestion to text returned of (display dialog thePrompt with title dialogTitle default answer defaultAnswer ¬
                buttons {"Cancel", "OK"} default button "OK" cancel button "Cancel")
            try
                set theAnswer to theQuestion as number
                if theAnswer  0 then
                    set theQuestion to ""
                end if
            on error
                set theQuestion to ""
            end try
        end repeat
        return theAnswer
    end tell
end enterARatio
 
on enterANumber(thePrompt, defaultAnswer)
    tell application "QLab"
        set theQuestion to ""
        repeat until theQuestion is not ""
            set theQuestion to text returned of (display dialog thePrompt with title dialogTitle default answer defaultAnswer buttons {"Cancel", "OK"} ¬
                default button "OK" cancel button "Cancel")
            try
                set theAnswer to theQuestion as number
            on error
                set theQuestion to ""
            end try
        end repeat
        return theAnswer
    end tell
end enterANumber
 
-- Subroutines: output
 
on startTheClock()
    tell application "QLab"
        display dialog "One moment caller..." with title dialogTitle with icon 1 buttons {"OK"} default button "OK" giving up after 1
        set startTime to time of (current date)
    end tell
end startTheClock
 
on countdownTimer(thisStep, totalSteps, whichCues)
    tell application "QLab"
        set timeTaken to ((time of (current date)) - startTime) as integer
        set timeString to my makeMMSS(timeTaken)
        if frontmost then
            display dialog (("Time elapsed: " & timeString & " - " & thisStep as string) & " of " & totalSteps as string) & ¬
                " " & whichCues & " done..." with title dialogTitle with icon 1 buttons {"Cancel", "OK"} default button "OK" cancel button "Cancel" giving up after 1
        end if
    end tell
end countdownTimer
 
on finishedDialog()
    tell application "QLab"
        activate
        if abortAbort is true then
            display dialog "Process aborted due to errors!" with title dialogTitle with icon 0 buttons {"OK"} default button "OK" giving up after 120
        else
            if ohDear is true then
                set ohDearString to " There were some errors, so you should check the results."
                set ohDearIcon to 0
            else
                set ohDearString to ""
                set ohDearIcon to 1
            end if
            set timeTaken to ((time of (current date)) - startTime) as integer
            set timeString to my makeNiceT(timeTaken)
            display dialog "Done." & ohDearString & return & return & "(That took " & timeString & ".)" with title dialogTitle with icon ohDearIcon ¬
                buttons {"OK"} default button "OK" giving up after 60
        end if
    end tell
end finishedDialog
 
-- Subroutines: processing
 
on adjustLevels(theCues, whichCues)
    tell application "QLab"
 
        -- Get the levels
 
        set validEntry to false
        set previousTry to ""
        repeat until validEntry is true
 
            set levelsString to my enterSomeText("Enter the levels you wish to adjust as \"row,column,delta\" or \"row,column,@level\"; " & ¬
                "you can separate multiple entries with spaces.
 
For example, \"0,0,-10 0,2,@-20\" will take 10dB from the Master level (row 0 column 0) and set the Output 2 level (row 0 column 2) to -20dB.", previousTry)
            set previousTry to levelsString
 
            -- Convert string to array
 
            set currentTIDs to AppleScript's text item delimiters
            set AppleScript's text item delimiters to space
            set levelsWords to text items of levelsString
            set howManyLevels to count levelsWords
            set AppleScript's text item delimiters to ","
            set backToText to levelsWords as text
            set levelsArray to (text items of backToText) as list
            set countLevelsArray to count levelsArray
            set AppleScript's text item delimiters to currentTIDs
 
            -- Check for validity
 
            if howManyLevels * 3 is countLevelsArray then -- First hurdle
                set validEntry to true
                try
                    repeat with i from 1 to countLevelsArray by 3
                        set eachRow to (item i of levelsArray) as number
                        set eachColumn to (item (i + 1) of levelsArray) as number
                        set eachLevel to item (i + 2) of levelsArray
                        if eachRow < 0 or eachRow > 16 then -- Check for valid row
                            set validEntry to false
                            exit repeat
                        end if
                        if eachColumn < 0 or eachColumn > 48 then -- Check for valid column
                            set validEntry to false
                            exit repeat
                        end if
                        if eachLevel does not start with "@" then -- Check for valid level
                            if (eachLevel as number) is 0 then -- Delta level can't be 0 (also checks string is a number)
                                set validEntry to false
                                exit repeat
                            end if
                        else
                            set theCheck to (rest of characters of eachLevel as string) as number -- Rest of string after @ must be a number
                        end if
                    end repeat
                on error
                    set validEntry to false
                end try
            end if
 
            -- Alert and go back if invalid
 
            if validEntry is false then
                display dialog "\"" & levelsString & "\" is not a valid entry! Try again." with title dialogTitle with icon 0 ¬
                    buttons {"OK"} default button "OK" giving up after 5
            else
 
                -- Final check that the levels have been interpreted correctly
 
                set pleaseConfirm to ""
                repeat with i from 1 to countLevelsArray by 3
                    set eachRow to (item i of levelsArray) as number
                    set eachColumn to (item (i + 1) of levelsArray) as number
                    set eachLevel to item (i + 2) of levelsArray
                    if eachRow is 0 then
                        if eachColumn is 0 then
                            set eachLine to "Master Level"
                        else
                            set eachLine to "Output " & eachColumn & " Level"
                        end if
                    else
                        if eachColumn is 0 then
                            set eachLine to "Input " & eachRow & " Level"
                        else
                            set eachLine to "Crosspoint Level: Input " & eachRow & " to Output " & eachColumn
                        end if
                    end if
                    if eachLevel does not start with "@" then
                        set eachLine to "> Add " & eachLevel & "dB to " & eachLine
                    else
                        set eachLine to "> Set " & eachLine & " to " & (rest of characters of eachLevel as string) & "dB"
                    end if
                    set pleaseConfirm to pleaseConfirm & eachLine
                    if (i + 2) is not equal to countLevelsArray then
                        set pleaseConfirm to pleaseConfirm & return
                    end if
                end repeat
 
                set goBack to button returned of (display dialog "Please confirm you wish to adjust levels thus for the " & whichCues & ":" & ¬
                    return & return & pleaseConfirm with title dialogTitle with icon 0 buttons {"Cancel", "No, no! Stop! That's not right! Go back!", "OK"} ¬
                    default button "OK" cancel button "Cancel")
                if goBack is "No, no! Stop! That's not right! Go back!" then
                    set validEntry to false
                end if
 
            end if
 
        end repeat
 
        -- Now, to business
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- Skip over cues that don't take levels!
                repeat with j from 1 to countLevelsArray by 3
                    set eachRow to (item j of levelsArray) as number
                    set eachColumn to (item (j + 1) of levelsArray) as number
                    set eachLevel to item (j + 2) of levelsArray
                    set currentLevel to getLevel eachCue row eachRow column eachColumn ¬
                        -- This check will throw an error and exit the j repeat if the cue doesn't take levels
                    if eachLevel does not start with "@" then
                        set eachLevel to currentLevel + eachLevel
                    else
                        set eachLevel to (rest of characters of eachLevel as string) as number
                    end if
                    try -- This try will throw a detectable error if the next line doesn't work
                        setLevel eachCue row eachRow column eachColumn db eachLevel ¬
                            -- We're relying on QLab's ability to ignore spurious levels like "-200" or "+50"
                    on error
                        set ohDear to true
                    end try
                end repeat
            end try
            if i mod 10 is 0 and (countCues - i) > 5 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustLevels
 
on adjustFileTarget(theCues, changeType, whichCues)
    tell application "QLab"
 
        if changeType is "Change" then
            set promptHeader to "CHANGE FILE TARGET: start/end & loop start/end times maintained..."
        else
            set promptHeader to "SET FILE TARGET: this process will not maintain the start/end & loop start/end times!"
        end if
 
        set theTarget to choose file with prompt promptHeader & return & return & "Please select the file target to set for the " & whichCues & ":" without invisibles
 
        my startTheClock()
 
        set countCues to count theCues
        set checkTheFirst to true
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            if q type of eachCue is not "Group" then -- Setting file target on a Group Cue (or cue list) affects the first Audio Cue in it!
                try -- Skip over cues that don't take file targets!
 
                    if changeType is "Change" then
                        set currentStart to start time of eachCue
                        if currentStart is missing value then -- ### Mac OS X 10.6.2 fix for incorrectly returned items
                            set currentStart to 0
                        end if
                        set currentLoopStart to loop start time of eachCue
                        if currentLoopStart is missing value then -- ### Mac OS X 10.6.2 fix for incorrectly returned items
                            set currentLoopStart to 0
                        end if
                        set currentLoopEnd to loop end time of eachCue
                        set currentEnd to end time of eachCue
                    end if
 
                    set file target of eachCue to theTarget ¬
                        -- QLab doesn't appear to throw any errors even if the cue doesn't take a file target, so no detection is possible
 
                    if checkTheFirst is true then -- Check the first one worked (ie: didn't break the cue!) before going any further
                        if broken of eachCue is true then -- This protects against (some) inappropriate files
                            set abortAbort to true
                            exit repeat
                        end if
                    end if
 
                    if changeType is "Change" then
                        set start time of eachCue to currentStart
                        set loop start time of eachCue to currentLoopStart
                        set loop end time of eachCue to currentLoopEnd
                        set end time of eachCue to currentEnd
                    end if
 
                end try
                set checkTheFirst to false -- We need to check the first cue that took a target, not the first cue we tried
            end if
 
            if i mod 10 is 0 and (countCues - i) > 5 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
 
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustFileTarget
 
on adjustSetName(theCues, whichCues)
    tell application "QLab"
 
        set theName to my enterSomeText("Enter the name you wish to set for the " & whichCues & ":", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set q name of eachCue to theName
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSetName
 
on adjustResetNameToFileTarget(theCues)
    tell application "QLab"
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- Skip over cues that don't take file targets!
                set theFile to file target of eachCue as alias
                tell application "System Events"
                    set theName to name of theFile
                end tell
                try -- This try will throw a detectable error if the next line doesn't work
                    set q name of eachCue to theName
                on error
                    set ohDear to true
                end try
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustResetNameToFileTarget
 
on adjustSearchReplaceName(theCues, whichCues)
    tell application "QLab"
 
        set searchFor to my enterSomeText("Enter the search string you wish to replace in the names of the " & whichCues & " (not case-sensitive):", "")
        set replaceWith to my enterSomeText("Enter the string with which wish to replace all occurrences of \"" & ¬
            searchFor & "\" in the names of the " & whichCues & ":", "")
 
        my startTheClock()
 
        set countCues to count theCues
        set currentTIDs to AppleScript's text item delimiters
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set currentName to q name of eachCue
            set AppleScript's text item delimiters to searchFor
            set searchedName to text items of currentName
            set AppleScript's text item delimiters to replaceWith
            set theName to searchedName as text
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set q name of eachCue to theName
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        set AppleScript's text item delimiters to currentTIDs
        my finishedDialog()
 
    end tell
end adjustSearchReplaceName
 
on adjustPrefixName(theCues, whichCues)
    tell application "QLab"
 
        set thePrefix to my enterSomeText("Enter the string you wish to add to the beginning of the names of the " & whichCues & ¬
            " (include a space at the end if you expect one):", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set currentName to q name of eachCue
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set q name of eachCue to thePrefix & currentName
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustPrefixName
 
on adjustSuffixName(theCues, whichCues)
    tell application "QLab"
 
        set theSuffix to my enterSomeText("Enter the string you wish to add to the end of the names of the " & whichCues & ¬
            " (include a space at the beginning if you expect one):", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set currentName to q name of eachCue
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set q name of eachCue to currentName & theSuffix
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSuffixName
 
on adjustSeriesName(theCues, whichCues)
    tell application "QLab"
 
        set validEntry to false
        set previousBaseName to ""
        set previousStartNumber to ""
        set previousIncrement to ""
        set previousPadding to ""
        repeat until validEntry is true
            set baseName to my enterSomeText("Enter the base of the name series you wish to set for the " & whichCues & ¬
                " (include a space at the end if you expect one):", previousBaseName)
            set startNumber to my enterAnInteger("Enter an integer with which to start the series:", previousStartNumber)
            set theIncrement to my enterAnInteger("Enter the increment for each step:", previousIncrement)
            set thePadding to my enterAnIntegerWithRange("Enter the minimum number of digits - an integer between 1 & 10 " & ¬
                "(eg: entering 2 will result in the series 01, 02, etc):", previousPadding, 1, 10)
            set previousBaseName to baseName
            set previousStartNumber to startNumber
            set previousIncrement to theIncrement
            set previousPadding to thePadding
            set counterConfirm1 to startNumber as string
            repeat until length of counterConfirm1  thePadding
                set counterConfirm1 to "0" & counterConfirm1
            end repeat
            set pleaseConfirm1 to "> " & baseName & counterConfirm1
            set counterConfirm2 to (startNumber + theIncrement) as string
            repeat until length of counterConfirm2  thePadding
                set counterConfirm2 to "0" & counterConfirm2
            end repeat
            set pleaseConfirm2 to "> " & baseName & counterConfirm2
            set counterConfirm3 to (startNumber + 2 * theIncrement) as string
            repeat until length of counterConfirm3  thePadding
                set counterConfirm3 to "0" & counterConfirm3
            end repeat
            set pleaseConfirm3 to "> " & baseName & counterConfirm3
            set pleaseConfirm to pleaseConfirm1 & return & pleaseConfirm2 & return & pleaseConfirm3 & return & "> ..."
            set goBack to button returned of (display dialog "Please confirm you wish to set the names as a series of this ilk for the " & whichCues & ¬
                return & return & pleaseConfirm with title dialogTitle with icon 0 buttons {"Cancel", "No, no! Stop! That's not right! Go back!", "OK"} ¬
                default button "OK" cancel button "Cancel")
            if goBack is "OK" then
                set validEntry to true
            end if
        end repeat
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set theCounter to (startNumber + (i - 1) * theIncrement) as string
            repeat until length of theCounter  thePadding
                set theCounter to "0" & theCounter
            end repeat
            set theName to baseName & theCounter
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set q name of eachCue to theName
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSeriesName
 
on adjustClearNotes(theCues)
    tell application "QLab"
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set notes of eachCue to ""
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustClearNotes
 
on adjustSetNotes(theCues, whichCues)
    tell application "QLab"
 
        set theNotes to my enterSomeText("Enter the notes you wish to set for the " & whichCues & ":", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set notes of eachCue to theNotes
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSetNotes
 
on adjustSearchReplaceNotes(theCues, whichCues)
    tell application "QLab"
 
        set searchFor to my enterSomeText("Enter the search string you wish to replace in the notes of the " & whichCues & " (not case-sensitive):", "")
        set replaceWith to my enterSomeText("Enter the string with which wish to replace all occurrences of \"" & ¬
            searchFor & "\" in the notes of the " & whichCues & ":", "")
 
        my startTheClock()
 
        set countCues to count theCues
        set currentTIDs to AppleScript's text item delimiters
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set currentNotes to notes of eachCue as string
            if currentNotes is "missing value" then
                set currentNotes to ""
            end if
            set AppleScript's text item delimiters to searchFor
            set searchedNotes to text items of currentNotes
            set AppleScript's text item delimiters to replaceWith
            set theNotes to searchedNotes as text
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set notes of eachCue to theNotes
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        set AppleScript's text item delimiters to currentTIDs
        my finishedDialog()
 
    end tell
end adjustSearchReplaceNotes
 
on adjustPrefixNotes(theCues, whichCues)
    tell application "QLab"
 
        set thePrefix to my enterSomeText("Enter the string you wish to add to the beginning of the notes of the " & whichCues & ¬
            " (include a space at the end if you expect one):", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set currentNotes to notes of eachCue as string
            if currentNotes is "missing value" then
                set currentNotes to ""
            end if
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set notes of eachCue to thePrefix & currentNotes
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustPrefixNotes
 
on adjustSuffixNotes(theCues, whichCues)
    tell application "QLab"
 
        set theSuffix to my enterSomeText("Enter the string you wish to add to the end of the notes of the " & whichCues & ¬
            " (include a space at the beginning if you expect one):", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set currentNotes to notes of eachCue as string
            if currentNotes is "missing value" then
                set currentNotes to ""
            end if
            try -- This try will throw a detectable error if the next line doesn't work (hard to think of a reason why it wouldn't though!)
                set notes of eachCue to currentNotes & theSuffix
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSuffixNotes
 
on adjustSetTime(theCues, theParameter, whichCues)
    tell application "QLab"
 
        if theParameter is "post wait" then -- Special option to set post waits to the same time as the duration
            set specialCase to {"Set to duration"}
        else
            set specialCase to {}
        end if
 
        set theTime to my enterATimeWithCustomButton("Enter the time you wish to set as the " & theParameter & ¬
            " for the " & whichCues & " (seconds or minutes:seconds):", "", specialCase)
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the appropriate line doesn't work
                if theParameter is "pre wait" then
                    set pre wait of eachCue to theTime
                else if theParameter is "duration" then
                    set duration of eachCue to theTime
                else if theParameter is "post wait" then
                    if theTime is specialCase as string then
                        set theDuration to duration of eachCue
                        set post wait of eachCue to theDuration
                    else
                        set post wait of eachCue to theTime
                    end if
                end if
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSetTime
 
on adjustScaleTime(theCues, theParameter, whichCues)
    tell application "QLab"
 
        set theMultiplicand to my enterARatio("Enter the ratio with which you wish to scale the " & theParameter & ¬
            " for the " & whichCues & " (eg: 1.1 will make them 10% longer):", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the appropriate line doesn't work
                if theParameter is "pre wait" then
                    set currentTime to pre wait of eachCue
                    set pre wait of eachCue to currentTime * theMultiplicand
                else if theParameter is "duration" then
                    set currentTime to duration of eachCue
                    set duration of eachCue to currentTime * theMultiplicand
                else if theParameter is "post wait" then
                    set currentTime to post wait of eachCue
                    set post wait of eachCue to currentTime * theMultiplicand
                end if
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustScaleTime
 
on adjustAddSubractTime(theCues, theParameter, whichCues)
    tell application "QLab"
 
        set theAddend to my enterANumber("Enter the number of seconds you wish to add to " & theParameter & " for the " & whichCues & ":", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the appropriate line doesn't work
                if theParameter is "pre wait" then
                    set currentTime to pre wait of eachCue
                    set pre wait of eachCue to currentTime + theAddend
                else if theParameter is "duration" then
                    set currentTime to duration of eachCue
                    set duration of eachCue to currentTime + theAddend
                else if theParameter is "post wait" then
                    set currentTime to post wait of eachCue
                    set post wait of eachCue to currentTime + theAddend
                end if
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustAddSubractTime
 
on adjustSetMIDI(theCues, theParameter, whichCues) -- This is the only one that handles "channel"
    tell application "QLab"
 
        if theParameter is "channel" then
            set theMin to 1
            set theMax to 16
        else if theParameter is "byte combo" then
            set theMin to -8192
            set theMax to 8191
        else
            set theMin to 0
            set theMax to 127
        end if
 
        set theInteger to my enterAnIntegerWithRange("Enter the value to which you wish to set the " & theParameter & " for the " & whichCues ¬
            & ":", "", theMin, theMax)
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- Skip over cues that don't take MIDI!
                get command of eachCue -- Check for MIDI
                try -- This try will throw a detectable error if the appropriate line doesn't work
                    if theParameter is "channel" then
                        set channel of eachCue to theInteger
                    else if theParameter is "byte one" then
                        if command of eachCue is not pitch_bend then
                            set byte one of eachCue to theInteger
                        end if
                    else if theParameter is "byte two" then
                        if command of eachCue is not pitch_bend then
                            set byte two of eachCue to theInteger
                        end if
                    else if theParameter is "byte combo" then
                        if command of eachCue is pitch_bend then
                            set byte combo of eachCue to theInteger + 8192 -- Pitch bend of 0 in the Inspector is reported to AppleScript as 8192
                        end if
                    else if theParameter is "end value" then
                        if command of eachCue is not pitch_bend then
                            set end value of eachCue to theInteger
                        else
                            set end value of eachCue to theInteger + 8192
                        end if
                    end if
                on error
                    set ohDear to true
                end try
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSetMIDI
 
on adjustScaleMIDI(theCues, theParameter, whichCues)
    tell application "QLab"
 
        set theMultiplicand to my enterARatio("Enter the ratio with which you wish to scale the " & theParameter & ¬
            " for the " & whichCues & " (eg: 1.1 will make them 10% larger):", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- Skip over cues that don't take MIDI!
                get command of eachCue -- Check for MIDI
                try -- This try will throw a detectable error if the appropriate line doesn't work
                    if theParameter is "byte one" then
                        if command of eachCue is not pitch_bend then
                            set currentValue to byte one of eachCue
                            set byte one of eachCue to currentValue * theMultiplicand
                        end if
                    else if theParameter is "byte two" then
                        if command of eachCue is not pitch_bend then
                            set currentValue to byte two of eachCue
                            set byte two of eachCue to currentValue * theMultiplicand
                        end if
                    else if theParameter is "byte combo" then
                        if command of eachCue is pitch_bend then
                            set currentValue to (byte combo of eachCue) - 8192
                            set byte combo of eachCue to currentValue * theMultiplicand + 8192
                        end if
                    else if theParameter is "end value" then
                        if command of eachCue is not pitch_bend then
                            set currentValue to end value of eachCue
                            set end value of eachCue to currentValue * theMultiplicand
                        else
                            set currentValue to ((end value of eachCue) - 8192)
                            set end value of eachCue to (currentValue * theMultiplicand) + 8192
                        end if
                    end if
                on error
                    set ohDear to true
                end try
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustScaleMIDI
 
on adjustAddSubractMIDI(theCues, theParameter, whichCues)
    tell application "QLab"
 
        set theAddend to my enterAnInteger("Enter the integer you wish to add to " & theParameter & " for the " & whichCues & ":", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- Skip over cues that don't take MIDI!
                get command of eachCue -- Check for MIDI
                try -- This try will throw a detectable error if the appropriate line doesn't work
                    if theParameter is "byte one" then
                        set currentValue to byte one of eachCue
                        set byte one of eachCue to currentValue + theAddend
                    else if theParameter is "byte two" then
                        set currentValue to byte two of eachCue
                        set byte two of eachCue to currentValue + theAddend
                    else if theParameter is "byte combo" then
                        set currentValue to byte combo of eachCue
                        set byte combo of eachCue to currentValue + theAddend
                    else if theParameter is "end value" then
                        set currentValue to end value of eachCue
                        set end value of eachCue to currentValue + theAddend
                    end if
                on error
                    set ohDear to true
                end try
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustAddSubractMIDI
 
on adjustSeriesMIDI(theCues, theParameter, whichCues)
    tell application "QLab"
 
        if theParameter is "byte combo" then
            set theMin to -8192
            set theMax to 8191
        else
            set theMin to 0
            set theMax to 127
        end if
 
        set startNumber to my enterAnIntegerWithRange("Enter the value to which you wish to set the " & theParameter & ¬
            " of the first of the " & whichCues & ":", "", theMin, theMax)
        set theIncrement to my enterAnInteger("Enter the increment for each step:", "")
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            set theCounter to (startNumber + (i - 1) * theIncrement) -- We're relying on QLab to hit a ceiling/floor for this
            try -- Skip over cues that don't take MIDI!
                get command of eachCue -- Check for MIDI
                try -- This try will throw a detectable error if the appropriate line doesn't work
                    if theParameter is "channel" then
                        set channel of eachCue to theCounter
                    else if theParameter is "byte one" then
                        if command of eachCue is not pitch_bend then
                            set byte one of eachCue to theCounter
                        end if
                    else if theParameter is "byte two" then
                        if command of eachCue is not pitch_bend then
                            set byte two of eachCue to theCounter
                        end if
                    else if theParameter is "byte combo" then
                        if command of eachCue is pitch_bend then
                            set byte combo of eachCue to theCounter + 8192 -- Pitch bend of 0 in the Inspector is reported to AppleScript as 8192
                        end if
                    else if theParameter is "end value" then
                        if command of eachCue is not pitch_bend then
                            set end value of eachCue to theCounter
                        else
                            set end value of eachCue to theCounter + 8192
                        end if
                    end if
                on error
                    set ohDear to true
                end try
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustSeriesMIDI
 
on adjustArmed(theCues, theParameter)
    tell application "QLab"
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the appropriate line doesn't work
                if theParameter is item 1 of subChoiceArmed then
                    set armed of eachCue to true
                else if theParameter is item 2 of subChoiceArmed then
                    set armed of eachCue to false
                end if
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustArmed
 
on adjustContinueMode(theCues, theParameter)
    tell application "QLab"
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- This try will throw a detectable error if the appropriate line doesn't work (hard to think of a reason why it wouldn't though!)
                if theParameter is item 1 of subChoiceContinueMode then
                    set continue mode of eachCue to do_not_continue
                else if theParameter is item 2 of subChoiceContinueMode then
                    set continue mode of eachCue to auto_continue
                else if theParameter is item 3 of subChoiceContinueMode then
                    set continue mode of eachCue to auto_follow
                end if
            on error
                set ohDear to true
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustContinueMode
 
on adjustGuaranteeSync(theCues, theParameter)
    tell application "QLab"
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- Skip over cues that don't have guarantee sync!
                get guarantee sync of eachCue -- Check for guarantee sync
                try -- This try will throw a detectable error if the appropriate line doesn't work
                    if theParameter is item 1 of subChoiceGuaranteeSync then
                        set guarantee sync of eachCue to true
                    else if theParameter is item 2 of subChoiceGuaranteeSync then
                        set guarantee sync of eachCue to false
                    end if
                on error
                    set ohDear to true
                end try
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustGuaranteeSync
 
on adjustMode(theCues, theParameter)
    tell application "QLab"
 
        my startTheClock()
 
        set countCues to count theCues
 
        repeat with i from 1 to countCues
            set eachCue to item i of theCues
            try -- Skip over cues that aren't Groups
                if mode of eachCue is not cue_list then -- Don't adjust cue lists!
                    try -- This try will throw a detectable error if the appropriate line doesn't work
                        if theParameter is item 1 of subChoiceMode then
                            set mode of eachCue to fire_first_enter_group
                        else if theParameter is item 2 of subChoiceMode then
                            set mode of eachCue to fire_first_go_to_next_cue
                        else if theParameter is item 3 of subChoiceMode then
                            set mode of eachCue to fire_all
                        else if theParameter is item 4 of subChoiceMode then
                            set mode of eachCue to fire_random
                        end if
                    on error
                        set ohDear to true
                    end try
                end if
            end try
            if i mod 20 is 0 and (countCues - i) > 10 then -- Countdown timer (and opportunity to escape)
                my countdownTimer(i, countCues, whichCues)
            end if
        end repeat
 
        my finishedDialog()
 
    end tell
end adjustMode
 
-- Subroutines: text wrangling
 
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
 
on makeNiceT(howLong)
    if howLong is 0 then
        return "less than a second"
    end if
    set howManyHours to howLong div 3600
    if howManyHours is 0 then
        set hourString to ""
    else if howManyHours is 1 then
        set hourString to "1 hour"
    else
        set hourString to (howManyHours as string) & " hours"
    end if
    set howManyMinutes to (howLong mod 3600) div 60
    if howManyMinutes is 0 then
        set minuteString to ""
    else if howManyMinutes is 1 then
        set minuteString to "1 minute"
    else
        set minuteString to (howManyMinutes as string) & " minutes"
    end if
    set howManySeconds to howLong mod 60 as integer
    if howManySeconds is 0 then
        set secondString to ""
    else if howManySeconds is 1 then
        set secondString to "1 second"
    else
        set secondString to (howManySeconds as string) & " seconds"
    end if
    if hourString is not "" then
        if minuteString is not "" and secondString is not "" then
            set theAmpersand to ", "
        else if minuteString is not "" or secondString is not "" then
            set theAmpersand to " and "
        else
            set theAmpersand to ""
        end if
    else
        set theAmpersand to ""
    end if
    if minuteString is not "" and secondString is not "" then
        set theOtherAmpersand to " and "
    else
        set theOtherAmpersand to ""
    end if
    return hourString & theAmpersand & minuteString & theOtherAmpersand & secondString
end makeNiceT
 
(* END: Batch adjust selected *)