SendReply and OSC formatting

Hi all,

While converting some old code from using OSCresponder to using OSCFunc I was scratching my head for a long time when OSC messages from a SendReply.kr could be received with an OSCresponder but not with an OSCFunc. Turns out that OSCresponder address names that it responds to can be any symbol or even a string while OSCFunc address names need to be specifically formatted '/symbol'.

This is safeguarded when sending messages with NetAddr.sendMsg as it prepends a '/' if it’s not present in the address name. Should this maybe be implemented to SendReply as well or maybe there is a reason that it is the way it is?

Anyways thought I would post this if it maybe saves someone else who is troubleshooting the same issue some headache in the future.

Privet @blindmanonacid

There is a point there, but it’s more about design than what’s “right”.

The OSC specification defines an OSC Address Pattern as “an OSC-string beginning with the character ‘/’ (forward slash).” That’s it

Through its examples and pattern-matching rules, the specification implicitly implies a hierarchical structure analogous to URLs or file system paths, separating levels with forward slashes. This is also well understood.

Sometimes overlooked in brief guides, the specification details precise rules for pattern matching in OSC addresses. These are outlined in the section “OSC Message Dispatching and Pattern Matching” of the official specification.

** Disclaimer:** My opinion on language design (not necessarily a consensus ): From a standards compliance perspective, all OSC-related functionality in SuperCollider should adhere strictly to the official specification.

Implementing automatic slash prepending as syntactic sugar could be considered an oversight. It does not even qualify as syntactic sugar. What to see proper syntax sugar? Observe what happens when an expressive language is translated to an intermediate form, much more verbose, still readable by humans, but with a more structural syntax. That’s the real deal. Those tiny details, in this particular case, are too trivial.

In the case of SuperCollider, the immediate consequence of this erratic design is that it encourages confusion, Which is what happened here! A very slow deprecation (with an entire release cycle or even more with warnings) of non-compliant OSC address formats in favor of strict adherence to the specification could be a good idea.

Makes sense??? See https://opensoundcontrol.stanford.edu/spec-1_0.html

What do you think?

If I understand the OSC standard correctly, there should only be OSC addersses with a prepended /, quoting from OSC spec 1_0

The OSC Address of an OSC Method is a symbolic name giving the full path to the OSC Method in the OSC Address Space, starting from the root of the tree. An OSC Method’s OSC Address begins with the character ‘/’ (forward slash), followed by the names of all the containers, in order, along the path from the root of the tree to the OSC Method, separated by forward slash characters, followed by the name of the OSC Method. The syntax of OSC Addresses was chosen to match the syntax of URLs.

IMO using OSC addresses without a prepended / should be checked during runtime and print a log or error message to give a hint that something is not how it should be.

I think we should not start to support deviations from the standard.

1 Like

Too late. Now we have to fix that. :sweat_smile:

1 Like

That depends - if the old interface manages to make this work it is fine, but we should not continue with this deviation from the standard in a new interface, especially since this would break our current OSCFunc implementation, quoting from OSCFunc.new arg of path:

A Symbol indicating the path of the OSC address of this object. Note that OSCFunc demands OSC compliant addresses. If the path does not begin with a / one will be added automatically.

Maybe the thing you discovered could be added to OSCresponder docs, as a reminder on how to make a transition between both interfaces?

Would be interesting when this should get removed after all, I think a grace period of 7 years could be long enough?

1 Like

@dscheiba, since we are at it, does SC implement the pattern-matching rules precisely according to the specification?

Partial quote, better to check the document itself:

  • ?’ in the OSC Address Pattern matches any single character
  • *’ in the OSC Address Pattern matches any sequence of zero or more characters
  • A string of characters in square brackets (e.g., “[string]”) in the OSC Address Pattern matches any character in the string. Inside square brackets, the minus sign (-) and exclamation point (!) have special meanings:
  • two characters separated by a minus sign indicate the range of characters between the given two in ASCII collating sequence. (A minus sign at the end of the string has no special meaning.)
  • An exclamation point at the beginning of a bracketed string negates the sense of the list, meaning that the list matches any character not in the list. (An exclamation point anywhere besides the first character after the open bracket has no special meaning.)
  • A comma-separated list of strings enclosed in curly braces (e.g., “{foo,bar}”) in the OSC Address Pattern matches any of the strings in the list.

@smoge Thanks for the elaborate answer. It makes total sense that I have not conformed to standards, the errors have accumulated and now I have to face the consequences :wink:

It does make me wonder, since NetAddr is effectively translating all addresses to be OSC compliant - I have a bunch of old code (further down my updating odyssey) that sends UDP messages to Arduinos. They are not OSC formatted, simply strings (to be as efficient as possible, I think was the thought). I just checked and in SC 3.6 NetAddr did not add a '/' to addresses. Is there a way to send non-OSC UDP messages with NetAddr or do I have to reprogram the Arduinos too?

1 Like

You need to check. It would be weird if SC did such a thing. How would SC generate this non-OSC code (probably implementing everything internally)? Who is the receiver, or are the receivers?

You can expand the OSC protocol. Some applications, such as non-mixer and non-timeline, have reached a limitation. They have their own extension of the OSC+ protocol when talking with each other and follow the strict specifications for everything else. Normal? Not at all! Is it possible for the developer to do this internally as a design option? Yes, it’s on the table. The world doesn’t have to know. And since there is no God, it’s not a concern to any holiness being. So, it’s all good!

A minor detail: You just can’t talk to other programs, which is the raison d’être of the protocol in the first place, haha

They probably do this because the entire project was based on OSC and JACK as a framework for all its applications/processes, and just when the mixer and the timeline needed to talk, the protocol had to be expanded.

It would make sense that SendReply behaves the same, if only to comfort non-comformists like me :wink:

Haha, alright, that’s way above my head though. My head stops and intermittently bangs itself at classes. I will now take the vow and solemnly swear to abide by the OSC protocol. It’s probably for the better with the Arduinos too.

Thanks a lot for your answers!

2 Likes

FWIW, sclang appends the leading slash for you when sending – I guess this happens in the primitive to encode the OSC message (asRawOSC I think, but haven’t checked). I examined the bytes received in Pd, and these two messages transmit identically:

  • ['/hello', 123]
  • ['hello', 123]

So SendReply is the outlier, I guess. Not sure it’s worth risking code breakage to fix it…?

hjh

That’s a design decision, all right; it’s done. What bothers me is the inconsistency in a protocol shared by all audio applications.

I’m not sure, but a simple warning would avoid confusion. I would never change this part of the language, only after a few years warning. It’s not a big deal as it is now, I think.

It’s just an opinion, of course

We could add a warning if this occurs?

SendReply was added later. Whoever added it probably just didn’t think about the slash – whereas sclang’s OSC encoding dates back to the beginning (JMc’s code).

Inconsistencies often stem from different people writing code at different times, possibly without awareness of all the considerations.

hjh

1 Like

OSC is already stressful because one sometimes codes in very different environments. It deserves special care. This thread is a direct offspring of those inconsistencies. The proof is that we are talking about that decision here and now.

Let’s fix it. A warning for 2 or 3 years is not absurd to me. Whatever time works for the community. It will not hurt and will be an enhancement.

1 Like

SendReply was added before OSCFunc, IIRC.

Unfortunately lots of OSC implementations play fast and loose with the spec. With OSCFunc we took the opportunity to be a little stricter. No implementation prevents compliance I’d think, so it should always be possible to make it work with a very minor change.

I think a fix to SendReply would be okay. I would suggest it possibly posts a warning if it appends a /, so that at least there’s some feedback that something happened. OSCresponder has been deprecated for years, so I don’t think we need to continue to support its technically incorrect behaviour. Nor do we need to support invalid paths in other OSC servers.

My 2 cents anyway…

1 Like

Note that SuperCollider uses integer addresses for its Server messages for efficiency. These are 100% non-standard :slight_smile: Of course, this doesn’t mean we shouldn’t adhere to the standard whenever possible.

2 Likes

How about the section on pattern matching? Projects, in general, adapted all of that? (Genuine question, I believe that’s the case, but I don’t know)

But that’s one point I tried to make. That’s fine when it is OSC, but communicating processes belong to the same project. Non-mixer and non-timeline have an alternative implementation of OSC to talk to each other and nothing more.
`
These cases are harmless, right? It’s written:

thou shalt create an OSC dialect for thy kin alone. Speak it not beyond thy hearth, nor share it with outsiders. Let it be a secret bond known only to those of thy blood and household. Speak not this language in the marketplace, nor in the fields, nor houses of other music systems worship. Keep it hidden from the eyes and ears.

1 Like

Probably best in the classlib (following the precedent of fixing floats in buffer messages by using .asInteger in Buffer methods).

SendReply : SendTrig {
	*checkPath { |cmdName|
		cmdName = cmdName.asString;
		if(cmdName.first != $/) {
			"SendReply cmdName '%' should have a leading slash; one has been added for you"
			.format(cmdName)
			.warn;
			cmdName = "/" ++ cmdName;
		};
		^cmdName
	}
	*kr { arg trig = 0.0, cmdName = '/reply', values, replyID = -1;
		if(values.containsSeqColl.not) { values = values.bubble };
		[trig, this.checkPath(cmdName), values, replyID].flop.do { |args|
			this.new1('control', *args);
		};
		^0.0		// SendReply has no output
	}

	*ar { arg trig = 0.0, cmdName = '/reply', values, replyID = -1;
		if(values.containsSeqColl.not) { values = values.bubble };
		[trig, this.checkPath(cmdName), values, replyID].flop.do { |args|
			this.new1('audio', *args);
		};
		^0.0		// SendReply has no output
	}
	...
}

hjh

4 Likes

There is a 2010 commit (9ab372e) introducing input with or without a preceding slash (simply a language design principle in practice—“the blame is always with the receiver”), also in the class library. Maybe all the history is in the class library. I didn’t find anything on the C++ side.

Since OSCresponder is deprecated, I don’t think we need to follow its example anymore.

hjh

2 Likes