Getting vst~ info from pattrstorage

Leigh Marble's icon

Hello,

I started playing with the vst~ object in Max 7.2 today. I hadn't re-visited that object in a while, and I'm trying to understand how it works with pattrstorage and the new (to me) snapshot system. (In Max 6, a named vst~ object didn't even show up in the pattr system.)

My patcher has autopattr and pattrstorage objects, and I gave the vst~ object a "scripting name", so it appears inside pattrstorage.

However, the "data" column in the pattrstorage view just lists "dictionary" as the data contents for the vst~ client object.

Is there a way to extract information from that dictionary inside pattrstorage? Trying getstoredvalue messages to pattrstorage has not yielded anything. And trying to access the data directly through various dictionary objects isn't getting anywhere either.

Thank you,
Leigh

Leigh Marble's icon

For reference/edification, here's the contents of the JSON file created by sending a write message to the pattrstorage object. To help you read it, I'll explain that the patcher I'm working with has a total of three named objects being tracked by the pattr system: midi_input_device_a, midi_input_device_b, and vst_a.

{
    "pattrstorage" :     {
        "name" : "uglytwin_setup",
        "slots" :         {
            "1" :             {
                "id" : 1,
                "data" :                 {
                    "midi_input_device_a" : [ "nanoKEY2 KEYBOARD" ],
                    "midi_input_device_b" : [ "Alesis Micron" ],
                    "vst_a" : [                         {
                            "filetype" : "C74Snapshot",
                            "version" : 2,
                            "minorversion" : 0,
                            "name" : "Cheese Machine",
                            "origin" : "CheezeMachine.vst",
                            "type" : "VST",
                            "subtype" : "Instrument",
                            "embed" : 1,
                            "snapshot" :                             {
                                "pluginname" : "CheezeMachine.vst",
                                "plugindisplayname" : "Cheese Machine",
                                "pluginsavedname" : "/Library/Audio/Plug-Ins/VST/CheezeMachine.vst",
                                "pluginsaveduniqueid" : 0,
                                "version" : 1,
                                "isbank" : 0,
                                "isbase64" : 1,
                                "blob" : "148.CMlaKA....fQPMDZ....ALDRIoE...P.....HLDZkUldkABSkEFY...........................VZkDRCE....vPnUVY5UFHLUVXjAfXrUF.Wc0UWc0UWcE....f...f+...........T35Y+fqGE7yiBWyOjBWO+.....f8nv0O...f+3tNl6SgqGkOu2689.�"
                            }

                        }
 ]
                }

            }

        }

    }

}

Leigh Marble's icon

Oh, and one more bit of pertinent info. If I send the pattrstorage object this message:

getstoredvalue vst_a 1

The output from pattrstorage, as printed to the Max window by a print object, is:

vst_a dictionary

Now, whether it is simply sending out the string "dictionary", or whether that is a placeholder being used by the print object because it cannot parse or display the contents of any dictionary, I do not know.

Leigh Marble's icon

I have hacked at this problem further, and remain confused. Could a Cycling '74 tech person chime in, please?

As mentioned previously, when sending a getstoredvalue vst_a 1 message to a pattrstorage object, the output is vst_a dictionary. (This is in a patch with a vst~ object given the scripting name of "vst_a", as well as an autopattr object.)

If the output of the pattrstorage is sent to a zl len object, it reports a message length of 2.

If that same output is sent to a route vst_a object, however, nothing prints out either outlet. OK, maybe the route object can't handle dictionaries?

Similarly, perhaps, an iter object prints only "vst_a". And the right outlet of a zl slice 1 produces no printable output either.

If, instead of sending these outputs straight to print objects, I send them to a dict.iter first, they still produce nothing.

In short –– how is it possible to access the contents of a dictionary that is stored in a pattrstorage??

Thank you, I am so lost here!

Leigh Marble's icon

For anyone following this thread, and/or posterity: I sent my questions to Cycling '74 support, and the short answer is that pattrstorage is not designed to output usable info about a vst~ object.

Since pattrstorage keeps data about vst~s in a standard dictionary format (as viewable in that JSON file copied above), I am unclear as to why it cannot simply output that dictionary. If I get any further clarification from support, I'll be happy to pass that on here.

adudek's icon

Leigh, I came across this thread while researching a similar problem I'm having. Namely, can I find a way to "save" snapshots inside of a standalone that can be recalled beyond the current session. If the data is already being written somewhere by the app in a format accessible to the developer, I could transfer it to a "writable" file format and have the user save it manually. However, your experience and information suggests that the info is not exposed in any way.

I have concocted a method for extracting all parameters from all VST~ objects into dictionaries and colls, then saving them through a dictionary file dialog, but that is a pretty burdonsome task, given the number and variety of VSTs I'm dealing with. My method is a brute force way of doing exactly what I think a Snapshot should do, but I would rather use a bona fide object or method if it is available . The saving and recalling of Snapshots works fine using the JS API commands inside of MAX, but there is no way I can find to "save" the information in a standalone past the current session. Have you or anyone else found a good way to really integrate the pattrstorage object with the Snaphot data?

Leigh Marble's icon

hi Adudek - thanks for weighing in on the subject. I wanted to clarify a couple things about what's possible with the pattrstorage object. (For this discussion, I am not integrating patch "Snapshot" data at all.)

It is already currently possible to save and recall the contents of the pattrstorage object, by sending it read and write messages. Max will save an JSON (or XML) file with those contents to whatever filepath you ask it to. (NB: pattrstorage also has a savemode attribute, which allows you to control its autosave behavior, further easing the administrative overhead.)

If you are designing a standalone app for Mac OS X, one of the necessary tricks is to save your pattrstorage data to a location that the filesystem will be happy about. You are technically not supposed to save anything "inside of a standalone", since that would require the app to have write permissions inside the "Applications" directory. Instead, if you had an app named, say, "RadSynth", you would write your data file inside the user directory, specifically to:

~/Library/Application Support/RadSynth

Last I checked, the best (only?) way to get that filepath is with using the "getpaths" object from JASCH. (One caveat there: It seems when built as a standalone app, Max patches will write new subdirectory into Application Support. However, when running as a patch within Max, it will only write to an EXISTING directory! So you would have to manually create the "RadSynth" subdirectory in the Finder, while you're getting this working from within Max. Then when you build it as a standalone app, test it by erasing the "RadSynth" subdir from Application Support, and make sure the standalone is able to create the missing directory itself.)

So, when all that is done – what you've got then is perfect recall of vst plug-in parameters, via the pattrstorage object.

However, my complaint here in my original post is that the communciation between pattrstorage and vst~ is a "closed channel". I cannot have my patch query pattrstorage for those stored vst plug-in parameters, so I cannot do anything creative with that data – for example, I can't provide my own display for a vst's parameters, or provide an "Assignable X-Y Control" like in Ableton Live (see attached image). (Well, you could do an "Assignable X-Y Control", but it would not have the correct initial values showing for the parameters!)

Hope that helps understand the issue at hand, and that it also helps you give pattrstorage another try!

Screen-Shot-2017-01-04-at-11.50.58-AM.png
png
Jean-Francois Charles's icon

It looks like [pattrstorage] uses the Snapshot system to memorize the states of [vst~].
One way to investigate further is with [dict.view] or [dict.print]:

Max Patch
Copy patch and select New From Clipboard in Max.

I guess we are supposed to use the "Snapshot" system when playing with vst~, something I don't have experience with (for the moment, I use the Factory & User presets system for Audio Units on Mac).
J-F

Leigh Marble's icon

hi J-F,

Thanks for your ideas on this. Your example patch actually helped me out, in an unexpected way. When the dump message is sent to a pattrstorage, it outputs different information about the vst~ than if you send pattrstorage a getstoredvalue message!

When I send getstoredvalue, it outputs: "vst_a (dictionary)"

When I send dump, it outputs: "vst_a dictionary u215001147_vst_a"

The latter will display nicely if passed to a dict.view object. The former, however, displays nothing at all in a dict.view.

That might be a bug or a feature, I'm unclear. Investigating further...

Leigh