Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pattern control of OSC paths #557

Closed
yaxu opened this issue Oct 18, 2019 · 14 comments
Closed

Pattern control of OSC paths #557

yaxu opened this issue Oct 18, 2019 · 14 comments

Comments

@yaxu
Copy link
Member

yaxu commented Oct 18, 2019

A lot of systems put patternable information in the OSC path, for example I think /ch/1/mix/1/level would set levels on channel 1 bus 1 on Behringer's X-AIR protocol, and Bitwig does similar things. It'd be good to be able to pattern these parameters.

One approach would be supporting substitution in OscShape's, e.g. with the above example:
oPath = "/ch/${channel}/mix/${bus}/level

@jarmitage
Copy link

Reference for Bitwig OSC paths: https://github.com/git-moss/DrivenByMoss/wiki/Open-Sound-Control-(OSC)

@yaxu
Copy link
Member Author

yaxu commented Oct 20, 2019

I jmplemented it without the dollar so oPath = "/ch/{channel}/mix/{bus}/level should work. Braces aren't allowed in paths according to the osc spec so this shouldnt conflict with anything

@yaxu yaxu closed this as completed in 472d5f7 Oct 20, 2019
@jarmitage
Copy link

Some further reflections on this issue:

  • OSCTarget can only use one message spec (oPath, oShape, etc), but most OSC speaking systems have a range of message specs
  • This currently means multiple OSCTargets have to be created to have a complete protocol, which in turn means multiple streams are created (along with their schedulers and network connections)

Ideally OSCTarget would be able to encapsulate a complete OSC protocol for a given target. One possibility would be to have multiple message specs per target, but then an extra parameter is needed to lookup which one to use:

customTarget = OSCTarget {
	[...],
	oPaths = [
		"/track/{track}/{action}" ,
		"/track/{track}/clip/{clip}/{action}",
		"/master/{action}/{value}"
	],
	oShapes = [
		Just [("raw", Just $ VF 0)],
		Just [],
		Just [],
	],
	[...]
}

@jarmitage jarmitage reopened this Nov 11, 2019
@yaxu
Copy link
Member Author

yaxu commented Nov 11, 2019

Maybe it would be best for the path to become part of the shape, with each shape given a name, e.g.:

customTarget = OSCTarget {
	[...],
	oShapes = [
		("track",
                 ("/track/{track}/{action}", Just [("raw", Just $ VF 0)])),
		("clip",
                 ("/track/{track}/clip/{clip}/{action}", Just [])),
                ("master",
		("/master/{action}/{value}", Just [])),
	],
	[...]
}

@yaxu
Copy link
Member Author

yaxu commented Nov 11, 2019

In practice the shape name could then be used like:

d1 $ action "thing thing2" # raw sine # track 2 # shape "track"

I think there would be a better name for this parameter than shape though. Maybe _shape or _type with the _ making clear that it's metadata.

@yaxu
Copy link
Member Author

yaxu commented Nov 11, 2019

I'd probably make a datatype for this, so a shape would be made with e.g. Shape {sName = "track", sPath = "/track/{track}/{action}", sParams = Just []}}

@jarmitage
Copy link

This looks good.

I think there would be a better name for this parameter than shape though.

I do agree. To me path or even url would be clear as that is part of OSC / network terminology.

Another option would be to make it a parameter of the pattern:

d1 "track" $ ...
d 1 "track" $ ...

There's something quite logical about this, but I'm not sure if there would be other consequences.

@jarmitage
Copy link

Here's a more complete example of current workaround: https://gist.github.com/jarmitage/100ec087997100b448f173a0258d1885

@yaxu
Copy link
Member Author

yaxu commented Nov 13, 2019

Here's the current datatype

data OSCTarget = OSCTarget {oName :: String,
                            oAddress :: String,
                            oPort :: Int,
                            oPath :: String,
                            oShape :: Maybe [(String, Maybe Value)],
                            oLatency :: Double,
                            oPreamble :: [O.Datum],
                            oTimestamp :: TimeStamp
                           }
                 deriving Show

It mixes properties of the network connection with properties of the messages that are sent.

Here's a disentangled version:


data OSCTarget = OSCTarget {oName :: String,
                            oAddress :: String,
                            oPort :: Int,
                            oPath :: String,
                            oShape :: Maybe [(String, Maybe Value)],
                            oLatency :: Double,
                            oPreamble :: [O.Datum],
                            oTimestamp :: TimeStamp
                           }
                 deriving Show


data Shape = Shape {sTimestamp :: TimeStamp,
                    sPreamble :: [O.Datum],
                    sPath :: String,
                    sParams :: Maybe [(String, Maybe Value)]
                   }
           deriving Show

The interface could look something like this:


-- Connect
cx <- connectTarget superdirtTarget defaultConfig
-- Start scheduling + sending patterns
sd <- stream cx superdirtShape

streamReplace sd "gabbazero" $ s "gabba(3,8)" # crush 3
streamHush sd

@yaxu
Copy link
Member Author

yaxu commented Nov 13, 2019

I think we'll probably always want a separate scheduler for each 'shape'. So in terms of efficiency this doesn't buy us anything so far, apart from saving on network connections.

@yaxu
Copy link
Member Author

yaxu commented Nov 13, 2019

Well I guess this sort of thing would also be possible:

cx <- connectTarget superdirtTarget defaultConfig

streamReplace cx superdirtShape "gabbazero" $ s "gabba(3,8)" # crush 3
-- or in practice:
p = streamReplace cx superdirtShape 
d1 = p 1
d1 $ s "gabba(3,8)" # crush 3

Currently all the patterns get combined into one 'stack', and while that's convenient in terms of the code, it probably isn't more efficient.

@jarmitage
Copy link

jarmitage commented Nov 13, 2019

Ok this is really interesting! I will try to rewrite my example from above using this and see what comes up.

Edit: couldn't find time for this. If it's possible to get a prototype running I can try it out.

@yaxu
Copy link
Member Author

yaxu commented May 1, 2020

Moved to #638

@yaxu yaxu closed this as completed May 1, 2020
@yaxu yaxu reopened this May 3, 2020
@jarmitage
Copy link

(in case anyone is reading this and is confused; conversation is continuing over at #638, but both issues are remaining open for now)

@yaxu yaxu closed this as completed May 22, 2020
jamagin pushed a commit to jamagin/Tidal that referenced this issue Apr 4, 2024
jamagin pushed a commit to jamagin/Tidal that referenced this issue Apr 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants