External App - Pop Up Menu Testing API

I’ve been really wanting to get Pop Up Menu items to show up in VDMX.
I’ve thought and looked into creating custom classes, ports or a port editor but figured that all of the info is there already
and would be easier to just figure out how to help the VidVox guys out on their end.

I’ve used the example VuoPlugInApp and built from there. Changed a bunch of stuff around.
Aso in the VuoPlugIn.vuo comp edited it and added a few more things main a WAVE Node with a published WAVE port.
(see VuoPlugIn V02.vuo)

I needed to figure out how to:

  • Get a Runner Going, load an Composition … then

  • Get a list of input ports and get details about them a log

  • Then take the info from the WAVE port that has the menuItems key… (I added the check to see if it actually had the key)

  • I then pull out the keys: “name”, “value”… I know VDMX for ISF wants to see a array of “LABELS” and a matching array of “VALUES”.

  • I then built of NSMenuItems using the “name” IE Sine. and set it’s action selector to a function in my Class; waveTypeUpdatedFromUI:

  • then I built a separate NSDictionary to use for the associated object

    aMenuItemDict is:{
    Wave = triangle;
    }

  • I add each menuItem to a menu, then I set my App’s PopUp Button to the new Menu.

  • I then next test sending a new menu item selection back to the composition.

Here’s some screen shots and logs:

Here’s the first log query

2021-07-12 03:24:23.526225-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] inPorts is:(
    Wave,
    Amplitude,
    Periods,
    Which
)
2021-07-12 03:24:23.526315-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Wave
2021-07-12 03:24:23.526579-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    default = sine;
    menuItems =     (
                {
            name = Sine;
            value = sine;
        },
                {
            name = Triangle;
            value = triangle;
        },
                {
            name = Sawtooth;
            value = sawtooth;
        }
    );
    title = Wave;
    type = VuoWave;
}
2021-07-12 03:24:23.526629-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Amplitude
2021-07-12 03:24:23.526781-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    default = "0.1";
    title = Amplitude;
    type = VuoReal;
}
2021-07-12 03:24:23.526819-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Periods
2021-07-12 03:24:23.526885-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    title = Periods;
    type = "VuoList_VuoInteger";
}
2021-07-12 03:24:23.526921-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Which
2021-07-12 03:24:23.527017-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    default = 1;
    suggestedMin = 1;
    title = Which;
    type = VuoInteger;
}
2021-07-12 03:24:23.529229-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner testPropertyListFromInput] propListFromInput is:{
    Amplitude = "0.10000000000000001";
    Periods = null;
    Wave = "\"sine\"";
    Which = 1;
}
2021-07-12 03:24:23.529344-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner setUpPopUpButton] aWaveDict is:{
    default = sine;
    menuItems =     (
                {
            name = Sine;
            value = sine;
        },
                {
            name = Triangle;
            value = triangle;
        },
                {
            name = Sawtooth;
            value = sawtooth;
        }
    );
    title = Wave;
    type = VuoWave;
}
2021-07-12 03:24:23.529464-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner setUpPopUpButton] allKeys is:(
    menuItems,
    title,
    default,
    type
)
2021-07-12 03:24:23.529536-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner parseMenuItemsAndBuildPopUp:] vuoMenuItems is:(
        {
        name = Sine;
        value = sine;
    },
        {
        name = Triangle;
        value = triangle;
    },
        {
        name = Sawtooth;
        value = sawtooth;
    }
) 

And the LOGs after selecting a new Menu Item:

2021-07-12 03:28:40.871909-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner waveTypeUpdatedFromUI:] aMenuItemDict is:{
    Wave = triangle;
}
2021-07-12 03:28:40.874537-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner waveTypeUpdatedFromUI:] okUpdate is:1


----------------- AND THEN LOG PUBLISHED INPUTS AGAIN NEXT

2021-07-12 03:29:39.391621-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] inPorts is:(
    Wave,
    Amplitude,
    Periods,
    Which
)
2021-07-12 03:29:39.391705-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Wave
2021-07-12 03:29:39.391830-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    default = sine;
    menuItems =     (
                {
            name = Sine;
            value = sine;
        },
                {
            name = Triangle;
            value = triangle;
        },
                {
            name = Sawtooth;
            value = sawtooth;
        }
    );
    title = Wave;
    type = VuoWave;
}
2021-07-12 03:29:39.391900-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Amplitude
2021-07-12 03:29:39.391984-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    default = "0.1";
    title = Amplitude;
    type = VuoReal;
}
2021-07-12 03:29:39.392019-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Periods
2021-07-12 03:29:39.392125-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    title = Periods;
    type = "VuoList_VuoInteger";
}
2021-07-12 03:29:39.392159-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort is:Which
2021-07-12 03:29:39.392227-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner logInputPorts:] aPort details is:{
    default = 1;
    suggestedMin = 1;
    title = Which;
    type = VuoInteger;
}
2021-07-12 03:29:39.395958-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner testPropertyListFromInput] propListFromInput is:{
    Amplitude = "0.10000000000000001";
    Periods = null;
    Wave = "\"triangle\"";
    Which = 1;
}
2021-07-12 03:29:39.396070-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner setUpPopUpButton] aWaveDict is:{
    default = sine;
    menuItems =     (
                {
            name = Sine;
            value = sine;
        },
                {
            name = Triangle;
            value = triangle;
        },
                {
            name = Sawtooth;
            value = sawtooth;
        }
    );
    title = Wave;
    type = VuoWave;
}
2021-07-12 03:29:39.396120-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner setUpPopUpButton] allKeys is:(
    menuItems,
    title,
    default,
    type
)
2021-07-12 03:29:39.396180-0700 VuoPluginApp[69787:614861] -[TechnoVuoRunner parseMenuItemsAndBuildPopUp:] vuoMenuItems is:(
        {
        name = Sine;
        value = sine;
    },
        {
        name = Triangle;
        value = triangle;
    },
        {
        name = Sawtooth;
        value = sawtooth;
    }
) 

And here’s the ZIPPED Xcode project, Vuo comp and pics / logs

Vuo Working Menu Parsing.zip (1.36 MB)

thanks

Kerry

3 Likes

Excellent! It’s great that you were able to add the pop-up menu to the VuoPluginApp example without adding that much additional code.

A while ago I talked with David Lublin of Vidvox about this. There are a couple of things that I think they’d want to implement differently in VDMX than you have in your code. One is that (last I heard anyway) they’re using Vuo’s C++ API rather than the Cocoa API.

The other difference is that David had mentioned wanting to compile the composition and set up the UI in parallel, rather than waiting for the compilation to complete before getting the list of menu items. This means that you wouldn’t be able to use VuoRunner::Port::getDetails(). Intead, you could call VuoCompilerPublishedPort::getDetails(). I’ve attached some example code.

There’s one more complication. Currently Vuo returns the menuItems in one of two different formats, depending on how the menu items are defined in the node class. In the example code, the Wave and Attribute port have one format and the CoordinateSpace port has the other. Ideally we should standardize on one of those, but for now VDMX would need to support both.

To build and run the example code:

  • Download and unzip.
  • In Terminal:
    • cd ~/Downloads/ListPublishedPortDetails
    • mkdir build
    • cd build
    • cmake ..
    • make
    • ./ListPublishedPorts

ListPublishedPortDetails.zip (3.9 KB)

1 Like

Yes can totally see the need for speed for getting info a compile tile.
And I know VDMX is using a cache based system in their VuoCache folder to pre-build the executables.
I also know they’ve build their own Cocoa Framework that extends the Vuo Framework and from my observations
in the log they are using the C++API with VuoRunner rather than the CocoaRunner which I understand has it’s limitations
(which I think I was running into, I’ve come from straight Objective-C programming and not too familiar with using C++
and mixing it. I think a few times I was trying to do some bridging stuff but was probably doing it all wrong! haha)

I will experiment with the

VuoCompilerPublishedPort::getDetails()

and start trying to learn the C++ API

I know it can also be gathered straight from the GraphViz text info in the comp.
Which I’m realizing isn’t necessary straight JSON. (also realizing I need to learn more about json_object

label="PublishedInputs|<time>time\r|<image>image\r|<Wave>Wave\r|<Amplitude>Amplitude\r|<Periods>Periods\r|<Which>Which\r" _time_type="VuoReal" _time="0.000000" _time_suggestedMin="0" _time_suggestedMax="1" _image_type="VuoImage" _Wave_type="VuoWave" _Wave_menuItems="[\{\"value\":\"sine\",\"name\":\"Sine\"\},\{\"value\":\"triangle\",\"name\":\"Triangle\"\},\{\"value\":\"sawtooth\",\"name\":\"Sawtooth\"\}]" _Wave="\"sine\"" _Amplitude_type="VuoReal" _Amplitude="0.1" _Periods_type="VuoList_VuoInteger" _Which_type="VuoInteger" _Which_suggestedMin="1" _Which="1"];

or just the WAVE

_Wave_type="VuoWave"
 _Wave_menuItems="[
    \{\"value\":\"sine\",\"name\":\"Sine\"\},
    \{\"value\":\"triangle\",\"name\":\"Triangle\"\},
    \{\"value\":\"sawtooth\",\"name\":\"Sawtooth\"\}
    ]"
 _Wave="\"sine\"" 

Could easily load and parse the Text from the Above and search for “menuItems” key.

I will experiment more.
Thanks for your tips and the cod

1 Like

Also is there anywhere you can direct me to as how I can use that code in an Xcode Project?

I would rather that be able to be a separate function that I can pass a composition to as a variable.
Rather than a main() function call.

From the other Xcode project I see that there is some action that happen in the main.mm that sets up a context object and a VuoRunnerCocoa object.
would I need to include some code in there? Or can I do it in the AppDelegate

For the most part all of my Xcode Projects in the main.m file it’s usually always just the standard.
Template, except for when I’ve created AscOBJC AppleScript projects.

thanks

Kerry

The AppDelegate would be a good place, specifically the init or applicationDidFinishLaunching method.