[SOLVED] dynamically loading an encapsulated file into an external, in a M4L frozen device


    Sep 16 2021 | 9:36 am
    Hi there,
    I’ve been banging my head against this problem for a while now, so I thought maybe someone would have some insight here. First, a description of the problem’s context: I am working on the development of a Max4Live device, for which I have developed a dedicated external (using min). This external uses a dynamic library (namely, PyTorch), and requires that a file (the .pt model) be loaded at runtime.
    So far, for development and testing, I have been solving this by placing this .pt file in a folder next to where the .amxd sits, and using the latter’s path (from [thispatcher]) to locate my .pt file. This worked well. So far.
    The constraint is that I now need to distribute this M4L device, which implies having just one .amxd file, and no environing folders. I also need users to be able to "collect and save" their Live sets without everything getting broken.
    So far, I have tried 2 different strategies, but none of them showed up successful: 1) Placing the .pt file in the .mxo, and calling it with a relative path (via https://pytorch.org/docs/stable/generated/torch.jit.load.html). The problem seems to be that when a relative path is called, it seems to be relative to the executable (i.e. Max itself ? And what when running within Live ?), and not to the external itself. Hence my question: Is there a way to get the path to the external’s executable (or to the .mxo) ? I have seen this has been discussed before in the forum, but I couldn’t find an actionable answer (or at least one I could act upon).
    2) Including my .pt file in the .amxd’s project and consolidating it. However, when doing so, I don’t know how to retrieve the file’s path after freezing the device. I have tried using [absolutepath] with the file’s name and passing the resulting path to my external (and forward to `torch.jit.load()`). But as soon as the device is frozen, [absolutepath] only returns (notfound) as a result). Hence, my alternative question: Is there a way to get the path to an arbitrary file in a frozen device’s project file structure ? I would be so grateful is anyone has any hint to help me moving forward this, because I’m feeling a little stuck right now (and unfortunately, for a while).
    Thanks in advance,
    Pia

    • Sep 17 2021 | 2:06 pm
      Hey list!
      I managed to solve this through option 1), and here it goes in case somebody has the same problem: - first one needs to set the `CFBundleIdentifier` key, let's say to: `your.identifier.here` in the .mxo's info.plist - then you need to include this code into your external, and it will give you the absolute path to the Resources folder of your .mxo bundle (which you might need to mkdir):
      #ifdef __APPLE__ #include "CoreFoundation/CoreFoundation.h" #define MY_PLUGIN_BUNDLE_IDENTIFIER your.identifier.here #endif //(...) std::string getExternalBundleResourcesPath() { #ifdef __APPLE__ #define QUOTE(str) #str #define EXPAND_AND_QUOTE(str) QUOTE(str) #define MY_PLUGIN_BUNDLE_IDENTIFIER_STRING EXPAND_AND_QUOTE(MY_PLUGIN_BUNDLE_IDENTIFIER) CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(CFSTR(MY_PLUGIN_BUNDLE_IDENTIFIER_STRING)); CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); char path[PATH_MAX]; if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX)) { // error! } CFRelease(resourcesURL); return path; #endif };
      Hope this helps others along the way...