Contexts

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.

Moments

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.at(0):
    ...     score_group = score.add_group()
    ... 
    
  • Servers use real timestamps:

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

    >>> with server.at():  # do it ASAP
    ...     server.add_group()
    ... 
    Group(context=<Server ONLINE [/usr/local/bin/scsynth -R 0 -l 1 -u 57110]>, id_=1001, parallel=False)
    
  • Servers can also omit moments entirely:

    >>> server.add_group()
    Group(context=<Server ONLINE [/usr/local/bin/scsynth -R 0 -l 1 -u 57110]>, id_=1002, parallel=False)
    

Completions

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 score.at(0):
...     with score.add_synthdefs(supriya.default):
...         score.add_synth(supriya.default, target_node=score_group)
... 
Synth(context=<Score ONLINE [/usr/local/bin/scsynth -R 0 -l 1 -u 57110]>, id_=1001, synthdef=<SynthDef: default>)
>>> with server.at():
...     with server.add_synthdefs(supriya.default):
...         server.add_synth(supriya.default, target_node=server_group)
... 
Synth(context=<Server ONLINE [/usr/local/bin/scsynth -R 0 -l 1 -u 57110]>, 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=<Server ONLINE [/usr/local/bin/scsynth -R 0 -l 1 -u 57110]>, moment=Moment(context=<Server ONLINE [/usr/local/bin/scsynth -R 0 -l 1 -u 57110]>, 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 server.at():
...     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/entities.py", line 90, in __enter__
    return self.completion.__enter__()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/supriya/supriya/supriya/contexts/core.py", line 187, in __enter__
    raise MomentClosed
supriya.contexts.errors.MomentClosed