Python > SuperCollider interaction

Hi everyone!

I’ve created a Python library that talks to SuperCollider through OSC. So far so good. Everytime I start working with it, I need to start the sclang CLI, boot the server, etc… I’ve seen that there is quite a lot of modules made specifically to control SuperCollider from Python but they don’t seem to provide the type of interaction that I’m looking for.

I would like to setup something so that:

  1. an instance of SCLang starts whenever I import my lib in a Python interpreter.
  2. Random SCLang strings can be sent to the SCLang interpreter with stdout/stderr being reported in the Python console.

I guess that some of you might be working with Python already. Did you ever setup something like this? Were you able to achieve something similar?

Although it’s probably not what you’re thinking of, but you could always take a look at Ryan Kirkbride’s FoxDot: https://foxdot.org

I’m aware of FoxDot but I’m programming yet another live-coding tool for Python/SuperCollider. Not very original, but a very good exercise! I’m trying to do something slightly different. FoxDot Quark should be started from the SC Interpreter as well, just like mine, but I want to automate part of that process.

EDIT: oh and if I could send random inputs to the underlying SC Interpreter, that would be the dream basically!

There are two very nice looking libraries in Python that you can use to fully control the server, build synthdefs, etc., I know of.

https://github.com/josiah-wolf-oberholtzer/supriya
https://github.com/smrg-lm/sc3

The second is a translation of the sclang library I’ve made.

this hack seems to work in an interactive session:

import sys
import threading
import subprocess

sclang_proc = subprocess.Popen(
    ['sclang'],
    stdin=subprocess.PIPE,
    stdout=sys.stdout,
    stderr=subprocess.STDOUT,
    bufsize=1,
    universal_newlines=True,
    start_new_session=True)

# Needs to be running free. A problem is stdout blocking stdin.
threading.Thread(target=lambda: sclang_proc.wait(), daemon=True).start()

def sceval(string):
    if not string.endswith('\n'):
        string += '\n'
    sclang_proc.stdin.write(string)
    sclang_proc.stdin.flush()

# Test.
# sceval('2 + 2')
# sceval('"holi".postln;')
# for i in range(100):
# sceval(f'{i} * 2')

1 Like

That’s perfect. It’s exactly what I was looking for. Thanks a lot! I tried using Popen just like you did, but I was puzzled by the stdout blocking stdin part…