Hello, all! I've been experimentally building a Tidal editor (drawing inspiration from @polymorphic.engine's GSoC work) and thinking through how tidal (particularly the internal
Stream.hs logic) could better integrate with external tools.
Here's a sketch of some things I'm interested in. I'd be willing to work on the development, but wanted to see which ideas other folks like or have critiques of first. Since some of these involve breaking changes, it would be good to coordinate a nice release, etc. Particularly interested in @ndr_brt's thoughts in terms of the Atom plugin, and @yaxu's thoughts how this could be informed by his remake experiments. But, I'd also love to hear any other thoughts, comments, requests, wild dreams that anyone else has!
Right now, patterns can be named by any
Showable ID, which is very useful for numbering patterns, but gets weird for other things—for example, the ID of the pattern
p "bev" $ s "cp" is not
"bev", but rather
I've already implemented this, but then got distracted trying to figure out git rebase. Sorry about that. One cool result is that it would enable things like this:
-- Silence d1, d2 & d3 p [1..3] $ silence
Most fields of the
Stream object are already
MVars, so should be easy to change the
sCxs field to be an
MVar without disrupting too much. This way, one target can come from
BootTidal.hs, another can be added by an editor, others can be added/reconfigured during live performance, etc.
I think the tidiest interface would be something like this, resembling how patterns work:
startStream :: Config -> IO Stream -- Add target to context list, open UDP port, etc streamAddTarget :: Stream -> String id -> Target -> IO () -- Remove from context list and close UDP port, etc streamRemoveTarget :: Stream -> String id -> IO ()
startTidal stay the same for backwards compatibility, but this would be a breaking change for anyone who's used
MVars, one limitation is that there's not a good way to wait for an
MVar to change if, for example, you want the editor to display changes to
State fields can be written to and read from, like now, but also would allow some sort of subscription where the first read gets the current value, and then all subsequent reads block a thread until the value changes. I think the closest thing is the "skip channel" described in the concurrent Haskell paper, but would love to hear if others know of existing mechanisms for achieving this.