diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2023-11-14 19:31:36 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2023-11-14 19:31:36 -0800 |
commit | a44c71ba3dcd57765b112c039b48513646c9e244 (patch) | |
tree | 03febc52aeed244f4f9a2085e91f8c7c6d662155 | |
parent | b7f773ae87ab037b94582005729fc15a22340f97 (diff) |
til_stream,rkt,main: add stream audio control
Until now everything interested in audio just used a plain getter
on the stream to get at the context.
But with how things work currently, audio is always left in a
paused state until explicitly unpaused. This works fine with
modules/rkt, which manages pause/unpause explicitly. When
there's nothing like modules/rkt in charge though, the audio just
sits stuck paused. Meaning if you do some simple thing like
--module=playit, it won't ever get unpaused.
With this commit, something like modules/rkt takes control of the
stream's audio context, in a way that prevents anything else from
taking control of the same context on the same stream. That
enables having main try take control of the audio context after
creating the module contexts, then in the rendering thread ensure
the audio is unpaused if main is in control of the audio context
and something's queueing audio frames.
For now there's no mechanism for releasing control of the audio
context. It doesn't seem appropriate to make this more elaborate
than necessary. There's basically just two use cases WRT audio:
1. Something like rkt, which takes control once for the process
and stays in control until process exit.
2. Something far simpler where nothing's taking control like
rkt, and main just needs to get things unpaused when
needed because something's generating audio frames.
-rw-r--r-- | src/main.c | 9 | ||||
-rw-r--r-- | src/modules/rkt/rkt.c | 5 | ||||
-rw-r--r-- | src/til_stream.c | 18 | ||||
-rw-r--r-- | src/til_stream.h | 1 |
4 files changed, 31 insertions, 2 deletions
@@ -73,7 +73,7 @@ typedef struct rototiller_t { til_fb_fragment_t *fragment; pthread_t thread; til_fb_t *fb; - til_audio_context_t *audio; + til_audio_context_t *audio, *audio_control; } rototiller_t; static rototiller_t rototiller; @@ -430,6 +430,10 @@ static void * rototiller_thread(void *_rt) til_fb_fragment_submit(rt->fragment); last_ticks = ticks; + /* if we're in audio control, ensure it's unpaused if something's queueing audio */ + if (rt->audio_control && til_audio_n_queued(rt->audio_control)) + til_audio_unpause(rt->audio_control); + if (rt->args.print_module_contexts || rt->args.print_pipes) { /* render threads are idle at this point */ printf("\x1b[2J\x1b[;H"); /* ANSI codes for clear screen and move cursor to top left */ @@ -502,6 +506,9 @@ int main(int argc, const char *argv[]) &rototiller.module_context)) < 0, "unable to create module context: %s", strerror(-r)); + /* this determines if we need to "control" the audio (unpause it, really) */ + rototiller.audio_control = til_stream_get_audio_context_control(rototiller.stream); + pexit_if(pthread_create(&rototiller.thread, NULL, rototiller_thread, &rototiller) != 0, "unable to create dispatch thread"); diff --git a/src/modules/rkt/rkt.c b/src/modules/rkt/rkt.c index 7460161..f5221f4 100644 --- a/src/modules/rkt/rkt.c +++ b/src/modules/rkt/rkt.c @@ -286,7 +286,10 @@ static til_module_context_t * rkt_create_context(const til_module_t *module, til if (!ctxt->scene_track) return til_module_context_free(&ctxt->til_module_context); - ctxt->audio_context = til_stream_get_audio_context(stream); + ctxt->audio_context = til_stream_get_audio_context_control(stream); + if (!ctxt->audio_context) + return til_module_context_free(&ctxt->til_module_context); + /* set the stream hooks early so context creates can establish taps early */ til_stream_set_hooks(stream, &rkt_stream_hooks, ctxt); diff --git a/src/til_stream.c b/src/til_stream.c index 72dedb6..8fd4b07 100644 --- a/src/til_stream.c +++ b/src/til_stream.c @@ -97,6 +97,7 @@ typedef struct til_stream_t { const til_stream_hooks_t *hooks; void *hooks_context; til_audio_context_t *audio_context; + unsigned audio_controlled:1; til_stream_pipe_t *pipe_buckets[TIL_STREAM_PIPE_BUCKETS_COUNT]; til_stream_module_context_t *module_context_buckets[TIL_STREAM_CTXT_BUCKETS_COUNT]; } til_stream_t; @@ -227,6 +228,23 @@ til_audio_context_t * til_stream_get_audio_context(til_stream_t *stream) return stream->audio_context; } + +/* identical to til_stream_get_audio_context() except taking control, + * returns NULL if control is already taken. + */ +til_audio_context_t * til_stream_get_audio_context_control(til_stream_t *stream) +{ + assert(stream); + + if (stream->audio_controlled) + return NULL; + + stream->audio_controlled = 1; + + return stream->audio_context; +} + + /* Taps the key-named type-typed pipe on the supplied stream. * If this is the first use of the pipe on this stream, new pipe will be created. * If the pipe exists on this stream, and the type/n_elems match, existing pipe will be used as-is. diff --git a/src/til_stream.h b/src/til_stream.h index d72b139..a0dde31 100644 --- a/src/til_stream.h +++ b/src/til_stream.h @@ -53,6 +53,7 @@ void til_stream_start_frame(til_stream_t *stream); int til_stream_set_hooks(til_stream_t *stream, const til_stream_hooks_t *hooks, void *context); int til_stream_unset_hooks(til_stream_t *stream, const til_stream_hooks_t *hooks); til_audio_context_t * til_stream_get_audio_context(til_stream_t *stream); +til_audio_context_t * til_stream_get_audio_context_control(til_stream_t *stream); /* bare interface for non-module-context owned taps */ int til_stream_tap(til_stream_t *stream, const void *owner, const void *owner_foo, const char *parent_path, uint32_t parent_hash, const til_tap_t *tap); |