Supriya’s context interface exposes a set of common functions for interacting with scsynth-compatible execution contexts in both realtime and non-realtime.

>>> server = supriya.Server().boot()  # realtime
>>> score = supriya.Score()  # non-realtime

See the servers and scores pages for in-depth documentation on how each time of context works.


Contexts can bundle requests together via Moment context managers.

For non-realtime contexts, all requests must happen inside a moment, while for realtime contexts issuing requests outside of a moment - or inside a moment with no timestamp - simply means “do this as soon as possible”. Use at() to create a new moment.

  • Scores count time from zero:

    >>> with
    ...     score_group = score.add_group()
  • Servers use real timestamps:

    >>> import time
    >>> with + 0.1):  # 0.1 seconds from now
    ...     server_group = server.add_group()
  • Servers can use moments without timestamps:

    >>> with  # do it ASAP
    ...     server.add_group()
    Group(context=<supriya.contexts.realtime.Server object at 0x7f53acb1b0d0>, id_=1001, parallel=False)
  • Servers can also omit moments entirely:

    >>> server.add_group()
    Group(context=<supriya.contexts.realtime.Server object at 0x7f53acb1b0d0>, id_=1002, parallel=False)


Some commands to SuperCollider are “async” and may take multiple control blocks to complete, e.g. reading a file from disk into a buffer. These commands often accept a final “completion message”: an OSC message or bundle to be executed once the original command completes. A common use-case is to load a SynthDef and then allocate a synth using that definition in the completion message.

Like moments, Supriya exposes completions via Completion context managers. Some context methods return a completion, and all requests issued inside that completion’s context with be bundled together into the original request’s on_completion argument.

>>> with
...     with score.add_synthdefs(supriya.default):
...         score.add_synth(supriya.default, target_node=score_group)
Synth(context=<supriya.contexts.nonrealtime.Score object at 0x7f53acb12fe0>, id_=1001, synthdef=<SynthDef: default>)
>>> with
...     with server.add_synthdefs(supriya.default):
...         server.add_synth(supriya.default, target_node=server_group)
Synth(context=<supriya.contexts.realtime.Server object at 0x7f53acb1b0d0>, id_=1003, synthdef=<SynthDef: default>)

Because realtime contexts can issue requests outside of a moment context, all command methods that return completions also accept an on_completion argument: a callable taking the context as its only argument. This callable will be executed and any issued requests will be bundled as a completion message.

>>> server.add_synthdefs(
...     supriya.default,
...     on_completion=lambda context: context.add_synth(supriya.default),
... )
Completion(context=<supriya.contexts.realtime.Server object at 0x7f53acb1b0d0>, moment=Moment(context=<supriya.contexts.realtime.Server object at 0x7f53acb1b0d0>, seconds=None, closed=True, requests=[(ReceiveSynthDefs(synthdefs=(<SynthDef: default>,), on_completion=None), ...)]), requests=[(NewSynth(synthdef=<SynthDef: default>, synth_id=1004, add_action=AddAction.ADD_TO_HEAD, target_node_id=1, controls={}), None)])

If issuing commands inside a moment, the completion must be used before the moment closes, because the request to which the completion message will be added will have been sent once the moment closed.

>>> with
...     completion = server.add_buffer(channel_count=1, frame_count=512)
>>> with completion:
...     ...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/runner/work/supriya/supriya/supriya/contexts/", line 90, in __enter__
    return self.completion.__enter__()
  File "/home/runner/work/supriya/supriya/supriya/contexts/", line 186, in __enter__
    raise MomentClosed