Remote usage of audio-placed-player.rkt
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
racket/contract
|
||||
racket/place
|
||||
racket/async-channel
|
||||
uni-channel
|
||||
port-channel
|
||||
"../audio-placed-player.rkt"
|
||||
"../audio-player.rkt"))
|
||||
|
||||
@@ -30,9 +32,11 @@ The placed player is implemented as a command loop around a decoder, an
|
||||
asynchronous libao output handle, and a small amount of state that is reported
|
||||
back to the controlling side. In normal use it runs in a Racket place, so that
|
||||
the audio side has a separate Racket VM. The same function can also run in a
|
||||
normal Racket thread with async channels. That mode is useful for debugging,
|
||||
because the player then stays in the same process and can be inspected more
|
||||
easily.
|
||||
normal Racket thread with async channels. Both modes are mediated through
|
||||
@racketmodname[uni-channel]: each of the existing logical channels is wrapped as
|
||||
a uni-channel endpoint, so the worker no longer depends directly on
|
||||
@racket[place-channel-put], @racket[place-channel-get],
|
||||
@racket[async-channel-put], or @racket[async-channel-get].
|
||||
|
||||
It is normally run in a separate place so that audio decoding and feeding are
|
||||
isolated from scheduling delays in the main Racket VM, such as GUI activity,
|
||||
@@ -40,22 +44,58 @@ debugging, or interaction with DrRacket.
|
||||
|
||||
@section{Interface}
|
||||
|
||||
@defproc[(placed-player [ch-in (or/c place-channel? async-channel?)]) void?]{
|
||||
Runs the placed-player command loop on @racket[ch-in]. The channel may be a
|
||||
place channel or an async channel. The command loop receives list commands,
|
||||
@defproc[(placed-player
|
||||
[ch-in (or/c uni-channel? place-channel? async-channel? port-channel?)]
|
||||
[ch-out (or/c #f uni-channel? place-channel? async-channel? port-channel?) #f]
|
||||
[ch-evt (or/c #f uni-channel? place-channel? async-channel? port-channel?) #f])
|
||||
void?]{
|
||||
Runs the placed-player command loop on @racket[ch-in]. Each channel may already
|
||||
be a @racket[uni-channel?] or may be a supported raw channel that can be wrapped
|
||||
with @racket[make-uni-channel]. The command loop receives list commands,
|
||||
initializes its reply and event channels, and then processes playback commands
|
||||
until it receives @racket['quit].
|
||||
|
||||
The function is designed to be started either by @racket[dynamic-place] or by
|
||||
@racket[thread]. In place mode, all three channels are place channels. In
|
||||
thread mode, all three channels are async channels. The implementation detects
|
||||
the kind of channel and uses @racket[place-channel-put],
|
||||
@racket[place-channel-get], @racket[async-channel-put], or
|
||||
@racket[async-channel-get] as appropriate.}
|
||||
When @racket[ch-out] and @racket[ch-evt] are @racket[#f], the command loop
|
||||
expects an initial @racket['init] command containing the raw reply and event
|
||||
channels. This remains the normal path for @racket[dynamic-place], because a
|
||||
@racket[uni-channel] value contains procedures and must not be sent through a
|
||||
place channel. In that case the controlling side sends the raw place channels
|
||||
and the worker wraps them locally.
|
||||
|
||||
When all three channels are supplied, the worker starts initialized. This is
|
||||
used by the standard-port worker entry point and can also be used by custom
|
||||
launchers.}
|
||||
|
||||
@defproc[(placed-player/stdio [#:log-file log-file (or/c #f path-string?) (racket-sound-log-file 'placed-audio-player-stdio)])
|
||||
void?]{
|
||||
Runs @racket[placed-player] using the process standard streams as three logical
|
||||
channels: @racket[current-input-port] is the command channel,
|
||||
@racket[current-output-port] is the reply channel, and
|
||||
@racket[current-error-port] is the asynchronous event channel. The streams are
|
||||
wrapped through @racket[make-port-channel] and then through
|
||||
@racket[make-uni-channel].
|
||||
|
||||
Because stdout and stderr are protocol streams in this mode, ordinary display
|
||||
and log output is redirected while the worker is running. By default, output is
|
||||
appended to a log file under Racket's standard cache directory, for example
|
||||
@filepath{~/.cache/racket/racket-audio/placed-audio-player-stdio.log} on many
|
||||
Unix-like systems. Pass @racket[#f] explicitly to discard ordinary output, or
|
||||
pass a path to choose a different log file.
|
||||
|
||||
The module also has a command-line entry point. A remote or local subprocess
|
||||
worker can be started with:
|
||||
|
||||
@verbatim{
|
||||
racket -l racket-audio/audio-placed-player -- --stdio
|
||||
}
|
||||
|
||||
This is the command used by @racket[make-audio-player] when SSH remote playback
|
||||
is enabled, unless the caller supplies a custom remote command.}
|
||||
|
||||
The public wrapper in @racketmodname[racket-audio/audio-player] creates the channels,
|
||||
sends the initial @racket['init] command, starts an event thread, and exposes a
|
||||
contracted API. The placed player itself only exports @racket[placed-player].
|
||||
sends the initial @racket['init] command when needed, starts an event thread, and exposes a
|
||||
contracted API. The placed player exports @racket[placed-player] and the
|
||||
standard-port worker entry point @racket[placed-player/stdio].
|
||||
|
||||
@section{Overall state model}
|
||||
|
||||
@@ -91,7 +131,10 @@ installed.
|
||||
|
||||
The controlling side sends commands as lists on @racket[ch-in]. The result of
|
||||
an RPC-style command is sent on the reply channel installed by
|
||||
@racket['init]. Asynchronous events are sent on the event channel.
|
||||
@racket['init] or supplied directly to @racket[placed-player]. Asynchronous
|
||||
events are sent on the event channel. These are logical channels; the concrete
|
||||
transport may be place channels, async channels, or port channels wrapped as
|
||||
uni-channels.
|
||||
|
||||
@itemlist[#:style 'compact
|
||||
@item{@racket[(list 'init ch-out ch-evt)] installs @racket[ch-out] and
|
||||
@@ -252,7 +295,8 @@ place or thread then terminates.
|
||||
@section{Running in a place or in a thread}
|
||||
|
||||
The normal path in @racket[make-audio-player] uses @racket[dynamic-place] when
|
||||
places are enabled. This gives the audio side its own Racket VM and isolates
|
||||
places are enabled. The command, reply, and event channels are wrapped with
|
||||
@racket[make-uni-channel] on each side. This gives the audio side its own Racket VM and isolates
|
||||
it from the main controller, while the command and event protocol stays the
|
||||
same.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user