OSC / OSC Query Hierarchy of namespaces (Take 1 - OLD)

This is now superseded by what is described in this post of a second iteration for a solution.. I’ve left this old iteration for reference only, and might later delete it.

In several OSC enabled applications, the namespace is very dense, and can comprise a tree-structure hierarchy with obvious repetition. Below is an example from Resolume Arena:

  • /composition
  • /composition/columns
  • /composition/columns/n (1 – 9)
  • /composition/layers
  • /composition/layers/n (1 – 3)
  • /composition/layers/n/clips
  • /composition/layers/n/clips/n (1 – 9)
  • /composition/layers/n/video
  • /composition/selectedclip
  • /composition/selectedlayer
  • Etc.

Currently in OSC Query and other discovery protocols, there is some provision for describing such hierarchies.

In the Ossia library there is a mechanism where a node communicates the bounds of the sub-instances it can contain: “Instance Bounds”.

If min==max, it has no sub-instances. Otherwise, any sub-node can be treated as an instance. For example, columns, layers, and clips in Resolume. Or fixtures in the MadMapper namespace.

This is quite imperfect, just as is the analogous .1-.n notation of libossia’s OSC Query implementation, in that the node can only hold sub-instances, not a mixed sub-hierarchy. e.g., /shapes/cicle1, shapes/circle2, shapes/square1, shapes/square2, for instance.
It also doesn’t cover the use case of instances of the same sub-class also elsewhere in the hierarchy – e.g. that /someothershapes/othercircle1, is of the same type as /shapes/circle1.
Moreover, namespaces of complex applications grow very-very large, where often the size is due to repetition, e.g. when for each MadMapper fixture, all of its sub-namespace is repeated, per instance.

The TWO software implements a solution to these points, but one which doesn’t currently have any automatic discovery support, but requires manual setup by the end-user.

Instead of treating an application as having one big namespace, in TWO the big namespace can be split into several sub-namespaces. These can then be assembled into a separate tree-structure of “Addresses” in TWO - where a “Root Address” is a combination of a Namespace and IP/Port “Location”, and which can then have several sub-addresses, each of which can have its own OSC “Address Part”, and an optional Namespace.

So for example, the above Resolume hierarchy, becomes the separate namespaces of:

  • Layer
  • Clip
  • Column
  • Resolume

To represent the full namespace of Resolume through this model, the following “Address” hierarchy is created:

  • Resolume {Resolume}
    • Composition {null}
      • Layers {null}
        • Layer1 {Layer}
          • Clips {null}
            • Clip1- Clip9 {Clip}
            • Temp {Clip}
        • Layer2 (>>>)
      • Columns {null}
        • Column1 – Column9 {Column}
    • selectedClip {Clip}
    • selectedLayer {Layer}

The Root Address “Resolume” should have Namespace Resolume. “Layer1” etc and “selectedLayer” should have Namespace Layer. Clip1 through Clip9, and selectedClip, should be of namespace Clip. Column1 through Column9, namespace Column. “Composition”,” Layers”, “Clips”, “Columns”, should all not have a Namespace assigned at all, only an OSC Address Part, as they only serve for grouping.

SInce the purpose of this text isn’t to explain how TWO works in detail I’ll leave that part out. If you want to try the above, the creation and use of such a structure with Resolume, along with example .two files, is available here.

Finally, just to illustrate the above in TWO screenshots:

Before: One Big Namespace

After: Many Separate Namespaces…

And an address hierarchy linking them together.

Now to the interesting part - how can the above be made compatible with Discovery?

Discovery of Namespace & Address Hierarchies

Address as a name can stay as a placeholder, but I’d be more than happy for suggestions, and would then gladly change it also in TWO.

The solution can be separated into two sub-tasks - receiving separate namespaces instead of current functionality, and receiving an Address hierarchy of such namespaces.

Receiving separate namespaces

For each namespace, OSC Query is sufficient as-is, just that there is a need for a mechanism to transmit several.

At its simplest form, since all namespaces are defined at the same hierarchy level, would be a container node/”osc address part”, distinguished by a flag stating that all sub-namespaces are to be treated as separate. This is different to “Instance Bounds” only in that there is no hierarchy between them.

To receive these there can be a boolean Attribute to the OSC Query request sent, to distinguish between asking for several split namespaces, or the default current functionality.

NAMESPACE_HIERARCHY for example.

Receiving Hierarchy of Namespaces (Addresses)

This is analogous to extensions proposed a few years ago to OSC, of having OSC nodes that are “meta” nodes - the name eludes me. What I propose is I believe an improvement, in that the standard OSC specification is untouched and still fully compatible, in the spirit also of OSC Query.

This can be a separate OSC Query request Attribute, or the last Namespace received from a NAMESPACE_HIERARCHY request.

It can reuse the OSC Query format, but doing away with most of the attributes, down to only these:

DESCRIPTION

FULL_PATH

CONTENTS

NAMESPACE

NAMESPACE is the only new attribute proposed, and will be the name of the namespace from those returned with the NAMESPACE_HIERARCHY request. It can either be a string, or use the json null type to indicate that it is only a “container” of sub-addresses, and doesn’t reference any namespace itself.

{
“DESCRIPTION”: “root node”,
“FULL_PATH”: “/”,
“CONTENTS”: {
“resolume”: {
“DESCRIPTION”: “…”,
“FULL_PATH”: “/resolume”,
“NAMESPACE”: “Resolume”,
“CONTENTS”: {
“composition”: {
“DESCRIPTION”: “…”,
“FULL_PATH”: “/resolume/composition”,
“NAMESPACE”: Composition,
“CONTENTS”: {
“layers”: {
“DESCRIPTION”: “…”,
“FULL_PATH”: “/resolume/composition/layers”,
“NAMESPACE”: null,
“CONTENTS”: {
“layer1”: {
“DESCRIPTION”: “…”,
“FULL_PATH”: “/resolume/composition/layers/layer1”,
“NAMESPACE”: Layer
},
“layer2”: {
“DESCRIPTION”: “…”,
“FULL_PATH”: “/resolume/composition/layers/layer1”,
“NAMESPACE”: Layer
}
}
}
}
}
}
}
}
}

Discussion

I find this proposal solves many of the problems with large OSC namespaces with little overhead, and maintaining compatibility both with the original OSC spec, and OSC Query.

As it is, my above proposal only details requesting the full namespaces, but that is only for the sake of brevity. It seems straightforward for it to easily be extended so that only a single sub-namespace can be extended for example, or so that sub-addresses are created and deleted, essentially using the already defined optional Attributes of OSC Query for dynamic namespace manipulation and querying.

Let me know what you think in the thread below!

what do you mean by “mixed sub-hierarchy” ?

as I think I already mentioned in a previous discussion on the ossia chat, there’s the // syntax that helps dealing with this. It’s described in section 3.4 of the OSC 1.1 specifications

Good point!

I meant, for example, a set of different sub-nodes, that do not all follow the same namespace.

But my main point with these two different notations is the point on repetition across different levels of the tree.

Sorry to have missed the “//” notation - I’ll look into it now!

I might be wrong, but I couldn’t find any mention of instance management in the OSCQuery specs. There is one issue by @jcelerier about instances but that’s all.
Are you sure this is not ossia-specific, instead ? (and then related to the dot instance syntax)

I looked into “//” notation, I remember it now. But how would that be used to specify, not reference separate instances of the same Namespace/class?

E.g., define that there are several “Fixtures” at different points in the namespace: all of namespace Fixture, but with address paths leading to them of different levels?

Edit: then, if you wish to reach all with a message, certainly, // applies!

to me, instances allow for similar sub-namespaces, i.e. with the same structure, but possible sub-instance variations, e.g.:
• instance.1
• sub.1
• sub.2
• instance.2
• sub.1

to me, that what instances mean - but there has been no strict definition anywhere, to my knowledge… so we could contribute to making one

yes, but then I think we should try and see what we could do with the existing tools (i.e. // and then create something new if this is blocking somehow)

You are right, my mistake, it is indeed NOT part of OSC Query, but from ossia - I had seen it here: https://ossia.github.io/ossia-docs/?cpp--98#instance-bounds

1 Like

isn’t the specification implicit in the namespace itself ?

of course, if you have several, similarly-named nodes or leaves (such as, e.g. “x”) used for different things, then this might become a problem.

also we should look into tags for these kinds of thing, at least to make some kind of consensus emerge before we get into adding anything to actual specifications… like prototyping this with tags, and then figuring out how it can be systematized…

I’m a little confused, because you write:

and then selectedLayer doesn’t show up in the Layer namespace
did I miss something ? (because, if I understand things well, this is where you demonstrate the need for cross-hierarchy)

I might have missed something, but I don’t fully grasp what you mean here, since the JSON sample you give here doesn’t seem to be illustrating this… or does it ?

I don’t see how returning a json with a complete namespace, that has .1 notation, and/or “instance bound” notation, can explicitly specify that, in this example:

/left/fixtures/fixture.1/…

/left/fixtures/fixture.n/…

and

/right/fixtures/fixture.1/…

/right/fixtures/fixture.n/…

/selected/fixture/…

are all of the same “Type”, and their sub-namespaces(if that is a good term) are all identical, of, in my proposal, Namespace “Fixture”?

You are right, I used a generic example, and actually forgot to add the one new thing I proposed. I will edit it to show what I meant right away!

then, if that’s just that, what about adding those as “types”, maybe ?
like, using EXTENDED_TYPE ?
or maybe with tags, like TYPE:fixture
?

or it could be solved by adding e.g. categories in tags.
this could even mix with types, something like:
TAGS {CATEGORY:light, TYPE:fixture}
maybe ?

anyhow, it seems to me really overkill to duplicate a whole tree structure when you’re actually just trying to sort things inside of a client software… but maybe there’s more to this than that and missed it ?

It’s edited enough to I hope illustrate, though in the process there might be a bracket too many/too few, I’ll fix it later!

The way I apply the term instances here is actually no sub-variations, they are exact duplicates, hence their specification being replaceable with a single name, e.g. “Fixture”.

There are however indeed situations where this may be too inflexible, you are right.

For example if there are two different types of fixture, nearly identical but each with additional sub methods. Sub-classes to the same parent class, which add public methods - “inheritance” in object oriented terms.