From b74c54a02923516f4f687484484c79b0501f98b3 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Tue, 3 Nov 2015 04:41:33 +0100 Subject: allow Stream:play() to be interrupted by CTRL+C * more precisely, Stream:play() will now throw an error whenever the process receices SIGINT. * this allows us to interrupt long playbacks --- applause.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'applause.c') diff --git a/applause.c b/applause.c index 6b71bb1..32f1a54 100644 --- a/applause.c +++ b/applause.c @@ -28,6 +28,8 @@ static jack_ringbuffer_t *buffer = NULL; static int buffer_sem; static sig_atomic_t buffer_xrun = 0; +static sig_atomic_t interrupted = 0; + static int svsem_init(size_t value) { @@ -75,6 +77,21 @@ svsem_free(int id) return semctl(id, 0, IPC_RMID); } +/** + * Handler for SIGINT signals. + * + * This handler is invoked e.g. when the user presses + * CTRL+C. + * It sets `interrupted` which is polled in the Lua play() + * method which allows us to interrupt long (possibly infinite) + * sound playback. + */ +static void +sigint_handler(int signum) +{ + interrupted = 1; +} + /** * The process callback for this JACK application is called in a * special realtime thread once for each audio cycle. @@ -253,7 +270,9 @@ l_Stream_play(lua_State *L) lua_gc(L, LUA_GCCOLLECT, 0); lua_gc(L, LUA_GCSTOP, 0); - for (;;) { + interrupted = 0; + + while (!interrupted) { jack_default_audio_sample_t sample; /* @@ -303,6 +322,9 @@ l_Stream_play(lua_State *L) lua_gc(L, LUA_GCRESTART, 0); + if (interrupted) + return luaL_error(L, "SIGINT received"); + /* any remaining stack elements are automatically popped */ return 0; } @@ -311,6 +333,7 @@ int main(int argc, char **argv) { int buffer_size = DEFAULT_BUFFER_SIZE; + struct sigaction sigint_action; static const luaL_Reg stream_methods[] = { {"play", l_Stream_play}, @@ -325,6 +348,17 @@ main(int argc, char **argv) if (argc > 1) buffer_size = atoi(argv[1]); + /* + * Register sigint_handler() as the SIGINT handler. + * This sets `interrupted`. Currently this is only polled + * in the Lua play() method in order to interrupt long + * sound playing. + * Otherwise it is ignored. + */ + memset(&sigint_action, 0, sizeof(sigint_action)); + sigint_action.sa_handler = sigint_handler; + sigaction(SIGINT, &sigint_action, NULL); + L = luaL_newstate(); if (!L) { fprintf(stderr, "Error creating Lua state.\n"); -- cgit v1.2.3