Generate List of All Media Files in Project

97 views
Skip to first unread message

Jumpcut Jeff

unread,
Jun 26, 2024, 6:53:06 PM (8 days ago) Jun 26
to QLab
Hi,

I realize v5 has the log feature, which is great! I'm curious if there's some script that will produce a list of all files used in a project? File name and path would be awesome, BUT I'd settle for just file name.

Thanks much!
Jeff

Chris Ashworth

unread,
Jun 26, 2024, 8:46:47 PM (8 days ago) Jun 26
to Jumpcut Jeff, ql...@googlegroups.com
Hi Jeff,

One approach:

- Click on cue list
- Press > to expand all groups
- Command-A to select all
- Copy
- Paste into a spreadsheet
- Sort by column that contains file paths and delete any other rows for cues that don’t have files
- Repeat for each cue list

Rich Walsh

unread,
Jun 27, 2024, 3:53:10 AM (8 days ago) Jun 27
to ql...@googlegroups.com
I posted the first version of this so long ago I can’t find it any more: https://wiki.allthatyouhear.com/doku.php#make_a_list_of_media_files.

Needed a bit of a tweak for v5:

-- Best run as a separate process so it can be happening in the background


-- Explanations


set theExplanation to "This script creates a text file on the Desktop with a list of all the media files used as targets in the current workspace, " & ¬

"removing duplicates and sorting alphabetically. It then opens the file in TextEdit."


-- Declarations


global dialogTitle, startTime

set dialogTitle to "Make a list of media files"


-- Preamble


tell application id "com.figure53.QLab.5"

display dialog theExplanation & return & return & "It may take a little while to run; are you sure you wish to proceed?" with title dialogTitle with icon 1 ¬

buttons {"Cancel", "OK"} default button "OK" cancel button "Cancel"

-- Prepare variables for filename

set fileTime to my grabTimeForFilename()

set workspaceName to q number of front workspace -- This actually gets the name of the workspace

my startTheClock()

-- Extract array of File Targets from QLab, skipping duplicates

set mediaFiles to {}

set mediaFilesRef to a reference to mediaFiles

tell front workspace

-- First, the easy ones

set validTargets to file target of cues whose broken is false and (q type is "Audio" or q type is "Video" or q type is "MIDI File")

set countValidTargets to count validTargets

repeat with i from 1 to countValidTargets

set eachTarget to item i of validTargets

set targetFile to POSIX path of eachTarget -- Convert to POSIX

if targetFile is not in mediaFilesRef then

set end of mediaFilesRef to targetFile

end if

if i mod 100 is 0 and (countValidTargets - i) > 50 then -- Countdown timer (and opportunity to escape)

my countdownTimer(i, countValidTargets, "valid Audio, Video or MIDI File Cues")

end if

end repeat

-- Now, broken cues

set brokenCues to cues whose broken is true and (q type is "Audio" or q type is "Video" or q type is "MIDI File")

set countBrokenCues to count brokenCues

repeat with i from 1 to countBrokenCues

set eachCue to item i of brokenCues

set eachTarget to file target of eachCue

if eachTarget is missing value then -- This will be returned by cues whose targets have become invalid

set eachName to q display name of eachCue

set targetFile to "**** Missing file target for cue named \"" & eachName & "\" ****"

else

set targetFile to POSIX path of eachTarget & " [BROKEN]"

end if

if targetFile is not in mediaFilesRef then

set end of mediaFilesRef to targetFile

end if

if i mod 100 is 0 and (countBrokenCues - i) > 50 then -- Countdown timer (and opportunity to escape)

my countdownTimer(i, countBrokenCues, "broken Audio, Video or MIDI File Cues")

end if

end repeat

end tell

-- Check there are some files

if (count mediaFilesRef) is 0 then

activate

display dialog "No media files were found!" with title dialogTitle with icon 0 ¬

buttons {"OK"} default button "OK" giving up after 60

return

end if

end tell


-- Convert the list to text and sort it


set currentTIDs to AppleScript's text item delimiters

set AppleScript's text item delimiters to linefeed

set theText to mediaFilesRef as text

set AppleScript's text item delimiters to currentTIDs


set sortedText to sortTextIgnoringCase(theText)


-- Create a string of the full path of the text file to be created


set newFile to "" & (path to desktop) & "QLab | " & workspaceName & " | Media files in use | " & fileTime & ".txt"


-- Make the file


makeFileFromText(newFile, sortedText)


-- Open it in TextEdit


tell application "TextEdit"

activate

open file newFile

set zoomed of front window to true

end tell


finishedDialogBespoke()


-- Subroutines


(* === OUTPUT === *)


on startTheClock() -- [Shared subroutine]

tell application id "com.figure53.QLab.5"

display dialog "One moment caller…" with title dialogTitle with icon 1 buttons {"OK"} default button "OK" giving up after 1

end tell

set startTime to current date

end startTheClock


on countdownTimer(thisStep, totalSteps, whichCuesString) -- [Shared subroutine]

set timeTaken to round (current date) - startTime rounding as taught in school

set timeString to my makeMSS(timeTaken)

tell application id "com.figure53.QLab.5"

if frontmost then

display dialog "Time elapsed: " & timeString & " – " & thisStep & " of " & totalSteps & " " & whichCuesString & ¬

" 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 finishedDialogBespoke()

set timeTaken to round (current date) - startTime rounding as taught in school

set timeString to my makeNiceT(timeTaken)

tell application "TextEdit"

activate

display dialog "Done." & return & return & "(That took " & timeString & ".)" with title dialogTitle with icon 1 ¬

buttons {"OK"} default button "OK" giving up after 60

end tell

end finishedDialogBespoke


(* === TIME === *)


on makeMSS(howLong) -- [Shared subroutine]

set howManyMinutes to howLong div 60

set howManySeconds to howLong mod 60 div 1

return (howManyMinutes as text) & ":" & my padNumber(howManySeconds, 2)

end makeMSS


on makeNiceT(howLong) -- [Shared subroutine]

if howLong < 1 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 text) & " 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 text) & " minutes"

end if

set howManySeconds to howLong mod 60 div 1

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 text) & " seconds"

end if

set theAmpersand to ""

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 "

end if

end if

set theOtherAmpersand to ""

if minuteString is not "" and secondString is not "" then

set theOtherAmpersand to " and "

end if

return hourString & theAmpersand & minuteString & theOtherAmpersand & secondString

end makeNiceT


(* === TEXT WRANGLING === *)


on padNumber(theNumber, minimumDigits) -- [Shared subroutine]

set paddedNumber to theNumber as text

repeat while (count paddedNumber) < minimumDigits

set paddedNumber to "0" & paddedNumber

end repeat

return paddedNumber

end padNumber


on sortTextIgnoringCase(theText) -- [Shared subroutine]

return do shell script "echo " & quoted form of theText & " | sort -f "

end sortTextIgnoringCase


(* === FILES === *)


on grabTimeForFilename() -- [Shared subroutine]

return do shell script "date '+%y-%m-%d %H%M%S'"

end grabTimeForFilename


on makeFileFromText(newFilePath, fileContents) -- [Shared subroutine]

copy (open for access newFilePath with write permission) to theOpenFile

set eof theOpenFile to 0 -- Clear it out first (just in case it already existed)

write fileContents to theOpenFile

close access theOpenFile

end makeFileFromText


I haven’t tested it thoroughly since 2019, but a quick test in v5 just now shows it works in principle. Most of it is user interaction; the actual business part is very short.

Rich

micpool

unread,
Jun 27, 2024, 9:08:12 AM (8 days ago) Jun 27
to QLab

Here's my somewhat shorter version, which is designed to run in a script cue in QLab and puts the list in the notes field of the script cue. (You can copy and paste from there if needed)


It lacks some of the  refinements of Rich's script,  but should process all the file targets in typical large workspaces in around 10 seconds (on an M1 Mac)


--set the notes of this script cue to a sorted list of files used in this workspace with no duplicates

set fileList to {}

set mytext to ""

tell application id "com.figure53.QLab.5" to tell front workspace --change id to "com.figure53.QLab.4"  for QLab 4

set myCue to last item of (active cues as list)

set theCues to cues

set cuesRef to a reference to theCues

repeat with eachCue in cuesRef

if the q type of eachCue is in {"audio", "video"} then

try

set the end of fileList to (file target of eachCue as alias as text)

on error

set the end of fileList to ("BROKEN FILE TARGET: " & q default name of eachCue)

end try

end if

end repeat

set noDups to {}

repeat with eachItem in fileList

if eachItem is not in noDups then set end of noDups to eachItem as text

end repeat

set AppleScript's text item delimiters to {ASCII character 10}

set myString to (noDups as text)

set newString to do shell script "echo " & quoted form of myString & " | sort -f -V"

set notes of myCue to ""

repeat with eachParagraph in paragraphs of newString

set notes of myCue to notes of myCue & eachParagraph & return

end repeat

set AppleScript's text item delimiters to ""

end tell


Mic

Jumpcut Jeff

unread,
Jun 27, 2024, 2:17:10 PM (8 days ago) Jun 27
to QLab
There is NO greater software-focused online group! Everyone is incredibly helpful and positive. I really appreciate the assistance! Jeff

Rich Walsh

unread,
Jun 28, 2024, 7:47:22 AM (7 days ago) Jun 28
to ql...@googlegroups.com
If you want fast without any user interaction or an escape hatch, and don’t need POSIX paths then this is significantly faster:

tell application id "com.figure53.QLab.5" to tell front workspace

set thisCue to last item of (active cues as list)

set mediaFiles to {}

set mediaFilesRef to a reference to mediaFiles

set mediaFilesRef to file target of cues whose broken is false and (q type is "Audio" or q type is "Video" or q type is "MIDI File")

repeat with eachCue in (cues whose broken is true and (q type is "Audio" or q type is "Video" or q type is "MIDI File"))

set eachTarget to file target of eachCue

if eachTarget is missing value then

set eachName to q default name of eachCue

if eachName is "" then set eachName to q display name of eachCue

set targetFile to "**** Missing file target for cue named \"" & eachName & "\" ****"

else

set targetFile to (eachTarget as text) & " [BROKEN]"

end if

set end of mediaFilesRef to targetFile

end repeat

set currentTIDs to AppleScript's text item delimiters

set AppleScript's text item delimiters to linefeed

set theText to mediaFilesRef as text

set AppleScript's text item delimiters to currentTIDs

tell me to set sortedText to do shell script "echo " & quoted form of theText & " | sort -f -V | uniq"

set notes of thisCue to sortedText

end tell


This little tweak to Mic’s version also speeds things up – as it avoids setting and getting the notes of a cue in a loop (although you actually don’t need to replace the linefeeds the shell tool requires with carriage returns for QLab to treat them as new lines):

set fileList to {}

set mytext to ""

tell application id "com.figure53.QLab.5" to tell front workspace --change id to "com.figure53.QLab.4"  for QLab 4

set myCue to last item of (active cues as list)

set theCues to cues

set cuesRef to a reference to theCues

repeat with eachCue in cuesRef

if the q type of eachCue is in {"audio", "video"} then

try

set the end of fileList to (file target of eachCue as alias as text)

on error

set the end of fileList to ("BROKEN FILE TARGET: " & q default name of eachCue)

end try

end if

end repeat

set noDups to {}

repeat with eachItem in fileList

if eachItem is not in noDups then set end of noDups to eachItem as text

end repeat

set AppleScript's text item delimiters to {ASCII character 10}

set myString to (noDups as text)

set newString to do shell script "echo " & quoted form of myString & " | sort -f -V"

(*set notes of myCue to ""

repeat with eachParagraph in paragraphs of newString

set notes of myCue to notes of myCue & eachParagraph & return

end repeat*)

set AppleScript's text item delimiters to return -- Speed tweak

set notes of myCue to paragraphs of newString as text -- Speed tweak

set AppleScript's text item delimiters to ""

end tell


(I dropped ~6.5k of audio files into QLab – which took ages – and ran the three versions… Mic’s original was still going after five minutes, my tweak of that got it down to 90s, my simplification of my verbose version – with some Mic enhancements like using q default name – took 19s. On a couple of old shows of ~200 files, it's near instantaneous.)

Rich
Reply all
Reply to author
Forward
0 new messages