Put the result in the clipboard

Hello,

I desperately try to put the result of this script in the clipboard.
The goal is to get information about an mp3 file.

The script :

choose file without invisibles
set thisMovie to POSIX path of result

tell application “System Events”
tell movie file thisMovie
properties of tracks
end tell
end tell

The result is :

{{modification time:missing value, audio sample size:0, data format:missing value, kind:missing value, audio sample rate:0.0, video depth:0, data rate:0, name:missing value, type class:missing value, class:track, dimensions:{0.0, 0.0}, start time:0, enabled:true, high quality:false, audio characteristic:false, visual characteristic:false, data size:3875696, href:missing value, creation time:missing value, audio channel count:0, duration:145355}}

I have tried without success:

set myVar to properties of tracks
set the clipboard to myVar

Thanks a lot for any help…

I think it’s because the properties are not ‘text’. However, you can coerce them into text with a couple of steps. I modified your posix path since I don’t see any shell script intent here.

Basically, after getting the properties of the file — which encompasses however many tracks the file may have — I grab the set for one of the tracks. Maybe your files have but a single track but you still have to do this because of how they’re structured (notice the {{…}} structure of propTracks).

Next, that set of properties is coerced into a list and then into the text of that list, separating the elements with ', '. You may want to reset the text item delimiters afterwards or not. Finally, it deposits the resulting text onto the clipboard.

set aMovie to (choose file without invisibles) as text
--> "MacHD:Users:username:Desktop:DSC_0123.mp3"

tell application "System Events"
	set thisMovie to movie file aMovie
	tell thisMovie
		
		set propTracks to properties of tracks
		
		set recProp to item 1 of propTracks
		set AppleScript's text item delimiters to ", "
		
		set textProp to recProp as list as text
		
	end tell
end tell

set the clipboard to textProp

Your script fails because by default, the type of data that the system clipboard requires is plain text. It means that each of properties of a singular track in your script should be coerced into plain text beforehand. Can you pull that off or do you need assistance?

Updated. And the downside of the script above is that the clipboard acquired only values without the related keys. To be able to tell one property from another you have to loop over every property by retrieving its value prepended with the textual form of the key written manually by yourself, such as

where TheList is the list of track’s properties in the original AppleScript-readable format.

Many thanks for your fast reactions and above all for your knowledge sharing.
Thanks to you the problems encountered are resolved and I am a little smarter!

The clipboard stores records fine. The clipboard knows what class is record data stored in it, when you set its contents to properties of some file inside tell application block. For file properties record you should ask for file of contents of the clipboard, and not for item 1 (a reference) or text or list or record:


set aFile to "HARD_DISK:Users:123:Desktop:Копировать Фильмы на USB .scpt alias"

tell application "System Events"
	set theRecord to properties of file aFile
	set the clipboard to theRecord -- remember the properties of the file
end tell

set newRecord to file of (get the clipboard) -- get the properties of the file back

--> {class:file, short version:"", container:folder "HARD_DISK:Users:123:Desktop:", path:"HARD_DISK:Users:123:Desktop:Копировать Фильмы на USB .scpt alias", file type:"alis", volume:"HARD_DISK", physical size:4096, URL:"file:///Users/123/Desktop/%D0%9A%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%A4%D0%B8%D0%BB%D1%8C%D0%BC%D1%8B%20%D0%BD%D0%B0%20USB%20.scpt%20alias", id:"Копировать Фильмы на USB .scpt alias,-100,12906994461", displayed name:"Копировать Фильмы на USB .scpt alias", busy status:false, kind:"Alias", creator type:"MACS", version:"", name extension:"", POSIX path:"/Users/123/Desktop/Копировать Фильмы на USB .scpt alias", name:"Копировать Фильмы на USB .scpt alias", modification date:date "Sunday, 21 March 2021 - 2:25:50 PM", size:920, type identifier:"com.apple.alias-file", default application:alias "HARD_DISK:System:Applications:Utilities:Terminal.app:", package folder:false, creation date:date "Sunday, 21 March 2021 - 2:25:50 PM", stationery:false, visible:true, product version:""}

When the clipboard can’t guess class of the record data, you can help it:


set theRecord to {Animal:"cat", |color|:12, theApp:current application}
set the clipboard to {text:theRecord}

set newRecord to record of (get the clipboard)
--> {Animal:"cat", |color|:12, theApp:current application}

FWIW, the original question seeks the ‘properties’ of ‘tracks’ of ‘movie file’, and thus requires a suitable file type (e.g. mp3 or mp4).

‘tracks’ generates a list — as some AV files have multiple tracks. Therefore, ‘properties of tracks of’ generates nested records. For an example mp3 file:


tell application "System Events" to properties of tracks of movie file aFile

--> {{visual characteristic:false, href:missing value, data size:10576718, duration:634603, modification time:date "Wednesday, April 14, 2021 at 20:22:45", high quality:false, kind:missing value, creation time:date "Wednesday, April 14, 2021 at 20:22:45", audio sample size:0, name:"Sound Track", type:missing value, data rate:0, audio characteristic:false, audio sample rate:0.0, enabled:true, class:track, video depth:0, dimensions:{0.0, 0.0}, start time:0, audio channel count:0, type class:missing value, data format:missing value}, {visual characteristic:false, href:missing value, data size:1, duration:905142, modification time:date "Wednesday, April 14, 2021 at 20:22:45", high quality:false, kind:missing value, creation time:date "Wednesday, April 14, 2021 at 20:22:45", audio sample size:0, name:"Base Track", type:missing value, data rate:0, audio characteristic:false, audio sample rate:0.0, enabled:true, class:track, video depth:0, dimensions:{0.0, 0.0}, start time:0, audio channel count:0, type class:missing value, data format:missing value}}

Notice that there are two records within the property result… one for each track (‘Sound Track’ and ‘Base Track’ in this example), and typically, but not always, ‘Sound Track’ is the name of the audio. Therefore, at least one extra step is required to get the relevant record.

Now, with that all said — based on your example, when I attempt to paste the clipboard into anything (even Script Editor), it fails with a beep. I don’t think that any applications understand this specialized pasteboard type (excepting the getting and setting of it in a script editor). So to use it in any other manner requires that it first be coerced into something intelligible (e.g. Record > List > Text). At least, I am unaware of how else to approach this.

Hi, again.

In my post above, I just showed that the clipboard can store records in the desired form. But this, as I now understand, is not what the OP is interested in.

To manually paste the content of the clipboard anywhere, I would write a script that uses a wonderful record handler from bmose:


set aFile to "HARD_DISK:Users:123:Desktop:Копировать Фильмы на USB .scpt alias"

tell application "System Events" to set theRecord to properties of file aFile

set {recordLabels:recordLabels, recordLabelsPiped:recordLabelsPiped, recordValuesAsText:recordValuesAsText, recordValues:recordValues} to my recordLabelsAndValues(theRecord)

set textProp to "{"
repeat with i from 1 to count recordLabels
	set textProp to textProp & item i of recordLabels & ":" & item i of recordValuesAsText & ","
end repeat
set textProp to textProp & "}"

set the clipboard to textProp


-- handler, written by bmose
on recordLabelsAndValues(theRecord)
	-- Returns the unpiped and piped forms of a record's labels and the text and value forms of a record's values
	-- Utility handler
	script util
		property recordLabels : {}
		property recordLabelsPiped : {}
		property recordValuesAsText : {}
		property recordValues : theRecord as list
		on representValueAsText(theValue)
			-- Parse a forced error message for the text representation of the input value
			try
				|| of {theValue}
			on error m
				set tid to AppleScript's text item delimiters
				try
					set AppleScript's text item delimiters to "{"
					set m to m's text items 2 thru -1 as text
					set AppleScript's text item delimiters to "}"
					set valueAsText to m's text items 1 thru -2 as text
				on error
					try
						-- Try an alternative method of generating a text representation from a forced error message if the first method fails
						{||:{theValue}} as null
					on error m
						try
							set AppleScript's text item delimiters to "{"
							set m to m's text items 3 thru -1 as text
							set AppleScript's text item delimiters to "}"
							set valueAsText to m's text items 1 thru -3 as text
						on error
							error "Could not get a text representation of the input value."
						end try
					end try
				end try
				set AppleScript's text item delimiters to tid
			end try
			return valueAsText
		end representValueAsText
	end script
	-- Perform the handler's actions inside a try block to capture any errors
	try
		set tid to AppleScript's text item delimiters
		-- Get the text representation of the input record
		set serializedRecord to util's representValueAsText(theRecord)
		-- Validate the text representation
		tell serializedRecord
			-- This test does not flag an input argument in the form of an Applescript list; however, a list will result in a parsing error in the code below
			if (it does not start with "{") or (it does not end with "}") then error "The input value is not a record."
			-- Handle the special case of an empty record
			if it = "{}" then return {recordLabels:{}, recordLabelsPiped:{}, recordValuesAsText:{}, recordValues:{}}
		end tell
		-- Remove the leading and trailing curly braces, and add a trailing ", " to the last record property to mimic the text pattern of the remaining properties
		set currSerializedRecord to (serializedRecord's text 2 thru -2) & ", "
		-- Parse the input record properties individually from first to last, using the text representation of the individual record values as text item delimiters
		repeat with currValue in util's recordValues
			-- Get the text representation of the current record property value
			set currSerializedValue to util's representValueAsText(currValue's contents)
			-- Consider the current record property label to be piped if the first character is a pipe
			set isPipedLabel to (currSerializedRecord starts with "|")
			-- Set the text item delimiter string to a colon (i.e., label-value separator), followed by the text representation of the record property value, followed by comma-space (i.e., property separator), optionally prefixing the entire string with a pipe if the label is piped
			if isPipedLabel then
				set currDelimiter to "|:" & currSerializedValue & ", "
				set invalidLabelChar to "|"
				set currSerializedRecord to currSerializedRecord's text 2 thru -1 -- "...text 2..." removes the leading pipe character
			else
				set currDelimiter to ":" & currSerializedValue & ", "
				set invalidLabelChar to ":"
			end if
			-- Extract the unpiped and piped versions of the current record property label
			set AppleScript's text item delimiters to currDelimiter
			tell (get currSerializedRecord's text items)
				-- Flag the input item as a non-record if (1) the text item delimiter string isn't found, (2) the property "label" contains an invalid character, or (3) the "label" is missing
				if (length = 1) or (item 1 contains invalidLabelChar) or (not isPipedLabel and (item 1 = "")) then error "The input argument theRecord does not appear to be a valid AppleScript record."
				-- Set the current record property label to the first text item, and the remaining record (still to be parsed) to the text beginning with the second text item (this will be the empty string if the current record property is the last property)
				set {currLabel, currLabelPiped} to {item 1, item 1}
				if isPipedLabel then set currLabelPiped to "|" & currLabelPiped & "|"
				set currSerializedRecord to rest as text
			end tell
			-- Save the results for the current record property
			set {end of util's recordLabels, end of util's recordLabelsPiped, end of util's recordValuesAsText} to {currLabel, currLabelPiped, currSerializedValue}
		end repeat
		if currSerializedRecord ≠ "" then error "The input argument theRecord does not appear to be a valid AppleScript record."
		-- Restore AppleScript's text item delimiters to their baseline value
		set AppleScript's text item delimiters to tid
		-- Return the results
		return {recordLabels:util's recordLabels as list, recordLabelsPiped:util's recordLabelsPiped as list, recordValuesAsText:util's recordValuesAsText as list, recordValues:util's recordValues as list}
	on error m number n
		set AppleScript's text item delimiters to tid
		if n = -128 then error number -128
		if n ≠ -2700 then set m to "(" & n & ") " & m -- -2700 = purposely thrown error
		error "Handler recordLabelsAndValues error:" & return & return & m
	end try
end recordLabelsAndValues