MartinusMagneson's picture

Magneson (@MartinusMagneson)

Compositions

MartinusMagneson's picture

I'm thinking way simpler in terms of parallelisation! As the "Build/Process List" are highly serial in the way they work, I'm assuming that being able to apply different image filters for instance would mean splitting each transition into its own thread and then have a timer/sync function in the collecting/output node to sync up the processes. I think there is some parallell action going on in Vuo already, but this could mean having greater control over it - which again could mean a possible greater efficiency (or a lot worse as well I guess..).

A struct in C is a collection of items, or a collection of a collection of items. A real number in Vuo for instance is a struct called VuoReal containing a float. Similarly a 3d point, VuoPoint3d, is also a struct - but one containing three floats with the identifiers x, y, z. The way Vuo works internally when it comes to generic types, is that when you write a node you specify the kinds of inputs a node can receive through a generic port by a placeholder. For instance, if you want to specify a variable to be a real number, the code would be VuoReal number;. If you want it to act on different types (2/3/4D) in addition to this, instead of creating 4 different nodes, you just specify what a generic type can be used as in the metadata of the node. Then the code would be VuoGenericType1 number;. At runtime, as far as I understand, the code then swaps VuoGenericType into whatever type you have attached to the composition input port.

If you look through the code examples and tutorials at api.vuo.org, You'll for instance see that there are functions to add reals/2/3/4d points. This is so that you can use the same code with the generic placeholder. Instead of using VuoReal sum = number1 + number2;, you can use VuoGenericType1 sum = VuoGenericType1_add(number1, number2); and have the same node calculate a lot of different structs.

The question then is, can you have functions as structs? Then you could type VuoGenericType1 whatJustHappened = VuoGenericFunction1(VuoGenericType2, VuoGenericType3);

On a different tangent, the Vuo API is really easy to work with. It looks like it works a lot like how you describe Haskell, although I guess it's more of an abstraction in terms of what and how it achieves it. Personally, I think it is one of Vuo's strongest features, and I hope more people get interested in that aspect as well, as it cuts out a lot of limitations you get with other software, and also makes it achievable to use once you have a decent result.

I think it could be a good idea in theory though. As an example, having an "Apply to 3d Object" node with an Object input port, and a generic input port could simplify a lot of tasks. Then you could add transforms, shaders, blending modes etc. through a single node - but I don't know how difficult or work intensive it would get for team Vuo to change something that seems to be very fundamental to how it works in the first place.

MartinusMagneson's picture
Magneson commented on Magneson's Discussion, “Memory leak

Thank you Jaymie, I think I might have stumbled onto something else though, causing this kind of behaviour.

I just made a new average list items node to smooth audio ranges a bit, and it just explodes wildly really fast. This node however is a stateless node, and it only gets triggered on start, so although I could be the culprit, I don't see how.

Here is an image of the Activity Monitor after running the composition for about a minute: The render scene to image node is there only to get the comp in the dock, as it otherwise wouldn't even show up. By removing the average list items node, it has a more expected memory usage.

The code for the node:

#include "node.h"
#include "math.h"
 
VuoModuleMetadata({
                      "title" : "Average List Items",
                      "keywords" : [ "magnitude", "bigger", "smaller", "some", "small", "most", ">", "<", "upper", "range" ],
                      "version" : "2.1.0",
                      "node": {
                          "exampleCompositions" : [ ]
                      }
                  });
 
void nodeEvent
(
        VuoInputData(VuoList_VuoReal) list,
        VuoInputData(VuoInteger) averageOfItems,
        VuoOutputData(VuoList_VuoReal) averageList
)
{
    unsigned long listCount = VuoListGetCount_VuoReal(list);
    *averageList = VuoListCreate_VuoReal();
 
    VuoInteger averageCount = averageOfItems;
 
    VuoList_VuoReal tempList = VuoListCreateWithCount_VuoReal(averageCount, 0.0);
 
    for(int i = 1; i <= listCount; i = (i + averageCount)){
        for(int j = 1; j <= VuoListGetCount_VuoReal(tempList); ++j){
            VuoListSetValue_VuoReal(tempList, VuoListGetValue_VuoReal(list, i+ (j - 1)), j, false);
        }
        VuoListAppendValue_VuoReal(*averageList, VuoReal_average(tempList));
    }
 
}

The original-problem node takes a relatively long time to reach any significant memory usage, but it still slowly grows out of its expected range, and into problem territory. That would be kind of worse if I hadn't noticed after running the node for a long time. Still work in progress it lacks defaults and proper naming, but here is the code if there is something glaringly obvious:

#include "node.h"
#include <math.h>
 
VuoModuleMetadata({
                     "title" : "Grow Real",
                     "description" : "Grows a list of VuoReals from a starting point to an end point.",
                     "keywords" : [ ],
                     "version" : "1.0.0",
                     "dependencies" : [ ],
                     "node": {
                         "isInterface" : false
                     }
                 });
 
struct nodeInstanceData
{
    VuoList_VuoPoint2d instanceTime;
    VuoReal previousTime;
    VuoInteger count;
};
 
struct nodeInstanceData * nodeInstanceInit
(
        VuoInputData(VuoInteger) points
)
{
    struct nodeInstanceData * instance = (struct nodeInstanceData *)malloc(sizeof(struct nodeInstanceData));
    VuoRegister(instance, free);
 
    instance->instanceTime = VuoListCreateWithCount_VuoPoint2d(points, VuoPoint2d_make(0.0, 0.0));
    instance->count = 0;
    VuoRetain(instance->instanceTime);
    instance->previousTime = 0.0;
 
    return instance;
}
 
void nodeInstanceEvent
(
        VuoInstanceData(struct nodeInstanceData *) instance,
        VuoInputEvent({"eventBlocking":"wall"}) trigger,
        VuoInputData(VuoReal) time,
        VuoInputData(VuoInteger, {"default":100, "suggestedMin":1, "suggestedMax":10000}) points,
        VuoInputData(VuoReal) startPosition,
        VuoInputData(VuoReal) endPosition,
        VuoInputData(VuoReal) duration,
        VuoInputData(VuoCurve) curve,
        VuoInputData(VuoCurveEasing) easing,
        VuoInputData(VuoLoopType) loop,
        VuoOutputData(VuoList_VuoReal) timeList
)
{
    //Make the output list
 
    *timeList = VuoListCreateWithCount_VuoReal(points, 0.0);
 
    //Make a copy of the info list
 
    VuoList_VuoPoint2d workList = VuoListCopy_VuoPoint2d((*instance)->instanceTime);
    VuoRelease((*instance)->instanceTime);
 
    //Get current count of active items
 
    VuoInteger activeCount = (*instance)->count;
    VuoRelease((*instance)->count);
 
    //Calculate time interval
    VuoReal pTime = (*instance)->previousTime;
    VuoReal frameTime = time - pTime;
 
    //Trigger durations
 
    if(trigger){
        activeCount += 1;
        if(activeCount > points){
            activeCount = 1;
        }
        VuoListSetValue_VuoPoint2d(workList, VuoPoint2d_make(time,duration), activeCount, false);
    }
 
    //VuoPoint3d stores curve data as: x = start time, y = duration. Duration decides if it is active or not (switch between durationTime / 0 for off)
    //Calculating the individual point/scale times
 
    for(unsigned int i = 0; i < points; ++i){
        VuoInteger index = i + 1;
 
        VuoPoint2d instanceInfo = VuoListGetValue_VuoPoint2d(workList, index);
 
        VuoReal currentTime = (time - instanceInfo.x) + frameTime;
 
        VuoReal pointTime = VuoReal_curve(
                        currentTime,
                        startPosition,
                        endPosition,
                        instanceInfo.y,
                        curve,
                        easing,
                        loop);
 
        if(pointTime == endPosition){
            instanceInfo = VuoPoint2d_make(0,0);
            pointTime = 0.0;
        }
 
 
        VuoListSetValue_VuoReal(
                    *timeList,
                    pointTime,
                    index,
                    false
                    );
 
        VuoListSetValue_VuoReal(*timeList, pointTime, index, false);
        VuoListSetValue_VuoPoint2d(workList, instanceInfo, index, false);
    }
 
    (*instance)->previousTime = time;
    (*instance)->count = activeCount;
    (*instance)->instanceTime = workList;
}
 
void nodeInstanceFini
(
        VuoInstanceData(struct nodeInstanceData *) instance
)
{
}

Both nodes are attached.

MartinusMagneson's picture

What I find intriguing about this is the implied parallell processing of the items. Am I right in this assumption? It would be huge in terms of the recent trends in processors, shifting to a large amount of cores/threads.

Could perhaps a multiplexing solution also fit into this some way? If you create a struct of input types from generic ports, could the function itself be a port type (wildly speculating)?

MartinusMagneson's picture
Magneson commented on Paul's Discussion, “rtsp

Have no idea about this, but it seems the URL in Vuo is different than the one at the top of the VLC window. Try setting it to the same? (rtsp://10.10.0.229:554/cam/realmonitor)

MartinusMagneson's picture
Magneson commented on jersmi's Discussion, “Force Image Generator to size?

If you're running it as a plugin in CoGe or VDMX I think you'd have to use the w/h inputs to get the canvas size from the application. You can also use a vuo.window.* node to set window properties. Resizing an image before outputting (either through the comp or Syphon) using the "resize image" node could also produce the desired result.

Pages