Wondering if I could get some help creating a proper declare for an AVAsset. I’m looking to create a simple function that tells me the length of a music file in MacOS.
I pulled the relevant parts from MacOSLib…
declare function assetWithURL lib Framework selector "assetWithURL:" ( id As Ptr, URL As Ptr ) As Ptr
declare function duration lib Framework selector "duration" ( obj_id As Ptr ) As CMTime
Can I pass a Memoryblock to id and URL?
Doesn’t look like CMTime is an easy structure to replicate…
https://developer.apple.com/documentation/coremedia/cmtime
As you may see with AVAssetMBS class in our MBS Plugins, it is loading a synchronously.
You need to wait for it to load ans query it later.
For the URL, would I need to do something like this?
[code]Declare Function NSClassFromString Lib “Cocoa” (className As CFStringRef) As Ptr
Declare Function fileURLWithPath Lib “Foundation” selector “fileURLWithPath:” (ptrNSURLClass As Ptr, path As CFStringRef) As Ptr
Dim ptrNSURLClass As Ptr = NSClassFromString(“NSURL”)
Dim ptrAppURL As Ptr = fileURLWithPath(ptrNSURLClass, “Path/To/My/File”)[/code]
I see what you’re saying, Christian. Thank you. I’m sure creating your MBS functions was no simple task!
I am still looking to learn more about how to properly create these parameters for the MacOS declares.
Try using this API to create a file based NSURL. It’s what I use and touch wood it’s working today.
https://developer.apple.com/documentation/foundation/nsurl/1414650-fileurlwithpath?language=objc
I also recall (it’s been several years since I did AV) that I ended up having to read all the tracks within the file to get the actual length. Ah yes, sorry it was video, video from a GoPro has longer audio that video, so I needed to read both track lengths and use the shorter time frame, otherwise I’d get a couple of black frames at the end.
I’m using it, and I don’t recall having problems. I guess I’ll have to double-check my app and see if it still does what it used to do.
Sure. The plugin also makes sure exceptions are handled properly, callbacks are sent to main thread and data types are converted.
Whether you prefer declare or plugin, you can see how we do it with the plugin and recreate each step via declare if you like.
Thanks, everyone. Turns out for this endeavour (all I need is to get the length of a music track) it’s a lot easier to just use shell and the parse the output of afinfo. No asynchronous issues there.
I do use a declare for Windows, since there’s no equivalent command-line way that I know of for Windows.
- afinfo on Mac
- mciSendStringW on Windows.
Easy-peasy.
I’ll save my Mac Declares for a time when there’s no command line equivalent.
Merry Christmas, y’all!
@Andy Broughton: I added your suggested afinfo to my function to get audiovisual files’ duration.
From a quick test I see that using AVAsset (macOSLib 64bits) it takes under 300 ticks, while afinfo takes over 1200 ticks.
Thank you for digging out afinfo.
Public Function getduration(f as FolderItem) as double
dim asset as AVAsset = AVAsset.AssetWithURL( new NSURL( f ) )
dim dur as Double = asset.DurationInSeconds
if dur <= 0 then
dim sh as new Shell
sh.Execute "afinfo " + f.ShellPath
dur = val(trim(NthField(NthField(sh.Result, "duration: ", 2), " sec", 1)))
end if
Return dur
End Function
No problem. Thank you for introducing me to “NthField” - I hadn’t seen that function before!
I was doing:
[code]Dim sh as New Shell
Dim St, End As Integer
Dim Dur As Double
sh.Execute("afinfo -b " + f.ShellPath)
St = sh.Result.InStr(0, “----”) + 5
End = sh.Result.Mid(St).InStr(0, “sec”) - 1
Dur = Val(sh.Result.Mid(St, End))[/code]
Yours is a bit cleaner.