Read application specific clipboard item as text

Unfortunately it’s telling us it’s just a blob of data. Try changing the NSLog statement to:

       current application's NSLog("Data is %@", theObj)

That gives me:

I think you’ve left the |class|() in there…

You should also try:

		current application's NSLog("Object is %@", current application's NSUnarchiver's unarchiveObjectWithData:theObj)

Alright, your second line of code:

current application's NSLog("Object is %@", current application's NSUnarchiver's unarchiveObjectWithData:theObj)

gives me:

But your first line of code…

current application's NSLog("Data is %@", theObj)

gives me something promising (I have to truncate it because it’s too long to post it all):


I’m afraid you’ve run into a dead-end.

The clipboard is stored as a property list. One of the limitations of property lists is that they can only store objects from a limited range of classes. But one of those classes is NSData, so programmers can get around the limitation by converting whatever they want to store to raw data. This can be done various ways – using NSArchiver and then getting it back with NSUnarchiver is common, but by no means the only way. Unfortunately it looks like they’re using something else, and I’m not sure where you’d begin trying to work it out beyond what we’ve done here.

Sorry I don’t have better news.

Even if not successful, I’ve learned a lot. Thanks for taking the time to work on this.

Is simply writing the data to a file a viable option?

It’s easy enough to do, if that’s what you mean:

theObj's writeToFile:"path/to/file" atomically:true

So I wrote it to a file and opened it in TextEdit. It’s the same half-jumbled file that CopyLess was giving me. A fair amount of it looks like a corrupted XML but it’s sill readable enough for me to get some key values. Maybe this is a little wonky, but I think it might work for my purposes.

Send me a copy via email. There might be something that can be done.

Alright, I emailed the file to you.

OK, so my guess was close – it’s actually a property lists archived with NSKeyedUnarchiver. And unfortunately trying to unarchive it fails because it uses a custom class. You could theoretically reverse engineer it, but you’d need a lot of time and patience, and you’d have to do it in Objective-C – with no guarantees that you’d get something usable.

You could try making a record of it like this:

set {theDict, theError} to current application's NSPropertyListSerialization's propertyListWithData:theObj options:0 |format|:(missing value) |error|:(reference)
if theDict = missing value then
	error (theError's localizedDescription() as text)
end if
return theDict as record

but I’m not sure that gets you far.

Reading the unarchived version would be great, but I think I can make do with this for now.

I could probably stop using CopyLess altogether if I could write the FCPX data to the clipboard. Is that pretty much the opposite of reading the clipboard?

Sort of, yes.

I have one more quick question. Say I want to modify an item in the plist “ffpasteboardobject” then write that back to the master plist “com.apple.flexo.proFFPasteboardUTI”. I’m trying to do this like so:

set theData to current application's NSPropertyListSerialization's dataWithPropertyList:theDict format:{"NSPropertyListBinaryFormat_v1_0"} options:0 |error|:(reference)

but am getting this


What is type Q? Is what I’m trying even possible?

You’re trying to pass a string where an enum is required. Try:

set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:theDict |format|:(current application's NSPropertyListBinaryFormat_v1_0) options:0 |error|:(reference)

I’m attempting to write the FCPX data back to the clipboard. But I’m stuck on setPropertyList:forType. Here’s what I have:

on writeClipboard:thePath
	set thePlist to current application's NSDictionary's dictionaryWithContentsOfFile:thePath
	set theObj to thePlist's objectForKey:"ffpasteboardobject"
	set {theDict, theError} to current application's NSPropertyListSerialization's propertyListWithData:theObj options:0 format:(missing value) |error|:(reference)
	if theDict = missing value then
		error (theError's localizedDescription() as text)
	end if
	set {theData, theError} to current application's NSPropertyListSerialization's dataWithPropertyList:theDict format:(current application's NSPropertyListBinaryFormat_v1_0) options:0 |error|:(reference)
	set newRecord to {ffpasteboardcopiedtypes:{pb_anchoredObject:{|count|:1}}} & {ffpasteboardobject:theData} & {kffmodelobjectIDs:{}}
	set OBJcDict to current application's NSDictionary's dictionaryWithDictionary:newRecord
	set newClipboardItem to current application's NSPasteboard's setPropertyList:OBJcDict forType:"com.apple.flexo.proFFPasteboardUTI"
	set theNSPasteboard to current application's NSPasteboard's generalPasteboard()
	theNSPasteboard's clearContents()
	theNSPasteboard's writeObjects:{newClipboardItem}
end writeClipboard:

It returns the error:

What am I missing?

You’re sending the message to the pasteboard class, not a pasteboard, and you’re trying two methods at once – -writeObjects is an alternative to -setPropertyList:forType:. Try changing to something like this:

    set theNSPasteboard to current application's NSPasteboard's generalPasteboard()
   theNSPasteboard's clearContents()
  theNSPasteboard's setPropertyList:OBJcDict forType:"com.apple.flexo.proFFPasteboardUTI"

Oh, I see. What I was trying to do was a bit like telling Finder to move the folder class instead of one particular folder.

Clearly I’m still working out the fundamentals of AppleScriptObjC.

I was able to finish the script for creating hotkeys for Final Cut Pro X using NSPasteboard and a number of other ObjC classes: http://macscripter.net/viewtopic.php?id=43895

Thanks for all the help!

The next step is creating an interface for it. I created a post relating to this problem here: http://macscripter.net/viewtopic.php?id=43871

Any ideas would be greatly appreciated.