diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | src/jack.c | 94 | ||||
-rw-r--r-- | wscript | 10 |
3 files changed, 101 insertions, 6 deletions
@@ -3,6 +3,7 @@ jalv (1.6.1) unstable; * Fix compilation with recent Gtkmm versions that require C++11 * Add jalv -i option to ignore stdin for background use * Add several commands to console interface + * Add support for running as an internal Jack client (thanks Timo Wischer) * Make Suil dependency optional * Remove support for deprecated event and uri-map extensions * Fix Jack deactivation @@ -11,7 +12,7 @@ jalv (1.6.1) unstable; * Add support for underscore in port names on command line (thanks Jośe Fernando Moyano) - -- David Robillard <d@drobilla.net> Sun, 23 Sep 2018 15:49:05 +0200 + -- David Robillard <d@drobilla.net> Sat, 29 Sep 2018 14:16:07 +0200 jalv (1.6.0) stable; @@ -14,6 +14,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <ctype.h> + #include <jack/jack.h> #include <jack/midiport.h> #ifdef JALV_JACK_SESSION @@ -27,9 +29,16 @@ #include "worker.h" struct JalvBackend { - jack_client_t* client; ///< Jack client + jack_client_t* client; ///< Jack client + bool is_internal_client; ///< Running inside jackd }; +/** Internal Jack client initialization entry point */ +int jack_initialize(jack_client_t* client, const char* load_init); + +/** Internal Jack client finalization entry point */ +void jack_finish(void* arg); + /** Jack buffer size callback. */ static int jack_buffer_size_cb(jack_nframes_t nframes, void* data) @@ -390,9 +399,16 @@ jalv_backend_init(Jalv* jalv) jack_set_session_callback(client, &jack_session_cb, arg); #endif - /* Allocate and return opaque backend */ + if (jalv->backend) { + /* Internal JACK client, jalv->backend->is_internal_client was already + set in jack_initialize() when allocating the backend */ + return jalv->backend; + } + + /* External JACK client, allocate and return opaque backend */ JalvBackend* backend = (JalvBackend*)calloc(1, sizeof(JalvBackend)); - backend->client = client; + backend->client = client; + backend->is_internal_client = false; return backend; } @@ -400,7 +416,10 @@ void jalv_backend_close(Jalv* jalv) { if (jalv->backend) { - jack_client_close(jalv->backend->client); + if (!jalv->backend->is_internal_client) { + jack_client_close(jalv->backend->client); + } + free(jalv->backend); jalv->backend = NULL; } @@ -415,7 +434,7 @@ jalv_backend_activate(Jalv* jalv) void jalv_backend_deactivate(Jalv* jalv) { - if (jalv->backend) { + if (jalv->backend && !jalv->backend->is_internal_client) { jack_deactivate(jalv->backend->client); } } @@ -491,3 +510,68 @@ jalv_backend_activate_port(Jalv* jalv, uint32_t port_index) } #endif } + +int +jack_initialize(jack_client_t* const client, const char* const load_init) +{ + const size_t args_len = strlen(load_init); + if (args_len > JACK_LOAD_INIT_LIMIT) { + fprintf(stderr, "error: Too many arguments given\n"); + return -1; + } + + Jalv* const jalv = (Jalv*)calloc(1, sizeof(Jalv)); + if (!jalv) { + return -1; + } + + if (!(jalv->backend = (JalvBackend*)calloc(1, sizeof(JalvBackend)))) { + free(jalv); + return -1; + } + + jalv->backend->client = client; + jalv->backend->is_internal_client = true; + + /* Build full command line with "program" name for building argv */ + const size_t cmd_len = strlen("jalv ") + args_len; + char* const cmd = (char*)calloc(cmd_len + 1, 1); + strcat(cmd, "jalv "); + strcat(cmd, load_init); + + /* Build argv */ + int argc = 0; + char** argv = NULL; + char* tok = cmd; + for (size_t i = 0; i <= cmd_len; ++i) { + if (isspace(cmd[i]) || !cmd[i]) { + argv = (char**)realloc(argv, sizeof(char*) * ++argc); + cmd[i] = '\0'; + argv[argc - 1] = tok; + tok = cmd + i + 1; + } + } + + const int err = jalv_open(jalv, argc, argv); + if (err) { + jalv_backend_close(jalv); + free(jalv); + } + + free(argv); + free(cmd); + return err; +} + +void +jack_finish(void* const arg) +{ + Jalv* const jalv = (Jalv*)arg; + if (jalv) { + if (jalv_close(jalv)) { + fprintf(stderr, "Failed to close Jalv\n"); + } + + free(jalv); + } +} @@ -166,6 +166,16 @@ def build(bld): if bld.env.HAVE_JACK: source += 'src/jack.c' + + # Non-GUI internal JACK client library + obj = bld(features = 'c cshlib', + source = source + ' src/jalv_console.c', + target = 'jalv', + includes = ['.', 'src'], + lib = ['pthread'], + install_path = '${LIBDIR}/jack') + autowaf.use_lib(bld, obj, libs) + obj.env.cshlib_PATTERN = '%s.so' elif bld.env.HAVE_PORTAUDIO: source += 'src/portaudio.c' |