alda-lang / alda-server-clj

A Clojure implementation of an Alda server
Other
2 stars 2 forks source link

Return STDOUT output for client consumption #1

Closed daveyarwood closed 5 years ago

daveyarwood commented 7 years ago

Moved from https://github.com/alda-lang/alda/issues/280.

So way back in the day, Alda was just a single process. When you ran alda play -f myfile.alda, you were running what is now the client, the server, and the worker, all in one process.

We eventually broke it out into separate, specialized processes so that now, when you run alda play -f myfile.alda, you're only running the client, which is a lot faster. This is nice because you get an immediate response -- you don't have to wait for the server and worker machinery to start up every time you want to play something.

One of the obscure downsides to this is that you can't see printed output anymore, because the output is getting printed by a worker process in the background, and your TTY is not attached to that worker process, so you can't see its STDOUT. You can only see output printed by the client.

You can observe the difference by running an Alda REPL (currently also a single process, closer to the way Alda used to be) and printing something:

$ alda repl
Oct 12, 2016 11:19:49 AM com.jsyn.engine.SynthesisEngine start
INFO: Pure Java JSyn from www.softsynth.com, rate = 44100, RT, V16.7.3 (build 457, 2014-12-25)
Preparing MIDI system... done.

 █████╗ ██╗     ██████╗  █████╗
██╔══██╗██║     ██╔══██╗██╔══██╗
███████║██║     ██║  ██║███████║
██╔══██║██║     ██║  ██║██╔══██║
██║  ██║███████╗██████╔╝██║  ██║
╚═╝  ╚═╝╚══════╝╚═════╝ ╚═╝  ╚═╝

           v1.0.0-rc44
        repl session

Type :help for a list of available commands.

> (println "hello world")
hello world

> (println "1 + 1 =" (+ 1 1))
1 + 1 = 2

>

But if you have a worker process play the same "score" (i.e. input containing inline Clojure code that prints something), you won't see any printed output:

$ alda play -c '(println "1 + 1 =" (+ 1 1))'
[27713] Parsing/evaluating...
[27713] Playing...

$

One nice thing that we do have in place is that if an error occurs at any point during the evaluation of a score, the worker will report it back to the client, and the client will print it:

$ alda play -c '(println "1 / 0 =" (/ 1 0))'
[27713] Parsing/evaluating...
[27713] ERROR Divide by zero

$

I just had a thought -- maybe the worker's response when it indicates to the client that it's playing a score could include a (potentially multiline) string of its STDOUT captured while parsing/evaluating the score? Then the client could look for the "stdout" key or whatever in the worker status responses and print whatever it may get.

This still wouldn't be ideal, though, because it wouldn't capture STDOUT that occurs while playing the score, e.g. when scheduling functions that print things to occur while playing the score.

Maybe a good approach there would be to include an options flag like --show-worker-stdout when playing a score. Then the client could continue making worker status requests as long as the score is playing (and the user doesn't press Ctrl-C), and the program would not exit until the score is done playing. Whenever a worker included some STDOUT with its status response, the client would print it.

For better timing, might need to explore PUB/SUB. A worker could publish both its status and stdout on the same PUB/SUB channel, each time either of those is updated.

daveyarwood commented 6 years ago

NB: We're removing the scheduled functions feature soon, but you can still print stuff at parse/eval time, so it would still behoove us to think about how we can access the STDOUT from the client-side.

daveyarwood commented 5 years ago

I've been doing a lot of planning and design for Alda 2.0, and part of the design is that we'll be doing a lot of the work that the server and worker are currently doing in the client. That will make this a non-issue.