diff options
Diffstat (limited to 'src/jalv_console.c')
-rw-r--r-- | src/jalv_console.c | 494 |
1 files changed, 271 insertions, 223 deletions
diff --git a/src/jalv_console.c b/src/jalv_console.c index 2d4a197..635b668 100644 --- a/src/jalv_console.c +++ b/src/jalv_console.c @@ -1,53 +1,69 @@ -/* - Copyright 2007-2016 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _POSIX_C_SOURCE 200809L -#define _XOPEN_SOURCE 600 -#define _BSD_SOURCE 1 -#define _DEFAULT_SOURCE 1 +// Copyright 2007-2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: ISC +#include "control.h" +#include "frontend.h" #include "jalv_config.h" #include "jalv_internal.h" +#include "log.h" +#include "options.h" +#include "port.h" +#include "state.h" +#include "types.h" +#include "lilv/lilv.h" #include "lv2/ui/ui.h" +#include "zix/attributes.h" +#include "zix/sem.h" + +#if USE_SUIL +# include "suil/suil.h" +#endif + +#ifdef _WIN32 +# include <synchapi.h> +#else +# include <unistd.h> +#endif #include <stdbool.h> +#include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <unistd.h> static int print_usage(const char* name, bool error) { - FILE* const os = error ? stderr : stdout; - fprintf(os, "Usage: %s [OPTION...] PLUGIN_URI\n", name); - fprintf(os, "Run an LV2 plugin as a Jack application.\n"); - fprintf(os, " -b SIZE Buffer size for plugin <=> UI communication\n"); - fprintf(os, " -c SYM=VAL Set control value (e.g. \"vol=1.4\")\n"); - fprintf(os, " -d Dump plugin <=> UI communication\n"); - fprintf(os, " -U URI Load the UI with the given URI\n"); - fprintf(os, " -h Display this help and exit\n"); - fprintf(os, " -l DIR Load state from save directory\n"); - fprintf(os, " -n NAME JACK client name\n"); - fprintf(os, " -p Print control output changes to stdout\n"); - fprintf(os, " -s Show plugin UI if possible\n"); - fprintf(os, " -t Print trace messages from plugin\n"); - fprintf(os, " -u UUID UUID for Jack session restoration\n"); - fprintf(os, " -x Exact JACK client name (exit if taken)\n"); - return error ? 1 : 0; + FILE* const os = error ? stderr : stdout; + fprintf(os, "Usage: %s [OPTION...] PLUGIN_URI\n", name); + fprintf(os, + "Run an LV2 plugin as a Jack application.\n" + " -b SIZE Buffer size for plugin <=> UI communication\n" + " -c SYM=VAL Set control value (e.g. \"vol=1.4\")\n" + " -d Dump plugin <=> UI communication\n" + " -h Display this help and exit\n" + " -i Ignore keyboard input, run non-interactively\n" + " -l DIR Load state from save directory\n" + " -n NAME JACK client name\n" + " -p Print control output changes to stdout\n" + " -s Show plugin UI if possible\n" + " -t Print trace messages from plugin\n" + " -U URI Load the UI with the given URI\n" + " -V Display version information and exit\n" + " -x Exit if the requested JACK client name is taken.\n"); + return error ? 1 : 0; +} + +static int +print_version(void) +{ + printf("jalv " JALV_VERSION " <http://drobilla.net/software/jalv>\n"); + printf("Copyright 2011-2022 David Robillard <d@drobilla.net>.\n" + "License ISC: <https://spdx.org/licenses/ISC>.\n" + "This is free software; you are free to change and redistribute it." + "\nThere is NO WARRANTY, to the extent permitted by law.\n"); + return 1; } void @@ -57,243 +73,275 @@ jalv_ui_port_event(Jalv* jalv, uint32_t protocol, const void* buffer) { - if (jalv->ui_instance) { - suil_instance_port_event(jalv->ui_instance, port_index, - buffer_size, protocol, buffer); - } +#if USE_SUIL + if (jalv->ui_instance) { + suil_instance_port_event( + jalv->ui_instance, port_index, buffer_size, protocol, buffer); + } +#else + (void)jalv; + (void)port_index; + (void)buffer_size; + (void)protocol; + (void)buffer; +#endif } int -jalv_init(int* argc, char*** argv, JalvOptions* opts) +jalv_frontend_init(int* argc, char*** argv, JalvOptions* opts) { - int n_controls = 0; - int a = 1; - for (; a < *argc && (*argv)[a][0] == '-'; ++a) { - if ((*argv)[a][1] == 'h') { - return print_usage((*argv)[0], true); - } else if ((*argv)[a][1] == 's') { - opts->show_ui = true; - } else if ((*argv)[a][1] == 'p') { - opts->print_controls = true; - } else if ((*argv)[a][1] == 'U') { - if (++a == *argc) { - fprintf(stderr, "Missing argument for -U\n"); - return 1; - } - opts->ui_uri = jalv_strdup((*argv)[a]); - } else if ((*argv)[a][1] == 'u') { - if (++a == *argc) { - fprintf(stderr, "Missing argument for -u\n"); - return 1; - } - opts->uuid = jalv_strdup((*argv)[a]); - } else if ((*argv)[a][1] == 'l') { - if (++a == *argc) { - fprintf(stderr, "Missing argument for -l\n"); - return 1; - } - opts->load = jalv_strdup((*argv)[a]); - } else if ((*argv)[a][1] == 'b') { - if (++a == *argc) { - fprintf(stderr, "Missing argument for -b\n"); - return 1; - } - opts->buffer_size = atoi((*argv)[a]); - } else if ((*argv)[a][1] == 'c') { - if (++a == *argc) { - fprintf(stderr, "Missing argument for -c\n"); - return 1; - } - opts->controls = (char**)realloc( - opts->controls, (++n_controls + 1) * sizeof(char*)); - opts->controls[n_controls - 1] = (*argv)[a]; - opts->controls[n_controls] = NULL; - } else if ((*argv)[a][1] == 'i') { - opts->non_interactive = true; - } else if ((*argv)[a][1] == 'd') { - opts->dump = true; - } else if ((*argv)[a][1] == 't') { - opts->trace = true; - } else if ((*argv)[a][1] == 'n') { - if (++a == *argc) { - fprintf(stderr, "Missing argument for -n\n"); - return 1; - } - free(opts->name); - opts->name = jalv_strdup((*argv)[a]); - } else if ((*argv)[a][1] == 'x') { - opts->name_exact = 1; - } else { - fprintf(stderr, "Unknown option %s\n", (*argv)[a]); - return print_usage((*argv)[0], true); - } - } + int n_controls = 0; + int a = 1; + for (; a < *argc && (*argv)[a][0] == '-'; ++a) { + if ((*argv)[a][1] == 'h') { + return print_usage((*argv)[0], true); + } - return 0; + if ((*argv)[a][1] == 'V') { + return print_version(); + } + + if ((*argv)[a][1] == 's') { + opts->show_ui = true; + } else if ((*argv)[a][1] == 'p') { + opts->print_controls = true; + } else if ((*argv)[a][1] == 'U') { + if (++a == *argc) { + fprintf(stderr, "Missing argument for -U\n"); + return 1; + } + opts->ui_uri = jalv_strdup((*argv)[a]); + } else if ((*argv)[a][1] == 'l') { + if (++a == *argc) { + fprintf(stderr, "Missing argument for -l\n"); + return 1; + } + opts->load = jalv_strdup((*argv)[a]); + } else if ((*argv)[a][1] == 'b') { + if (++a == *argc) { + fprintf(stderr, "Missing argument for -b\n"); + return 1; + } + opts->buffer_size = atoi((*argv)[a]); + } else if ((*argv)[a][1] == 'c') { + if (++a == *argc) { + fprintf(stderr, "Missing argument for -c\n"); + return 1; + } + opts->controls = + (char**)realloc(opts->controls, (++n_controls + 1) * sizeof(char*)); + opts->controls[n_controls - 1] = (*argv)[a]; + opts->controls[n_controls] = NULL; + } else if ((*argv)[a][1] == 'i') { + opts->non_interactive = true; + } else if ((*argv)[a][1] == 'd') { + opts->dump = true; + } else if ((*argv)[a][1] == 't') { + opts->trace = true; + } else if ((*argv)[a][1] == 'n') { + if (++a == *argc) { + fprintf(stderr, "Missing argument for -n\n"); + return 1; + } + free(opts->name); + opts->name = jalv_strdup((*argv)[a]); + } else if ((*argv)[a][1] == 'x') { + opts->name_exact = 1; + } else { + fprintf(stderr, "Unknown option %s\n", (*argv)[a]); + return print_usage((*argv)[0], true); + } + } + + return 0; } const char* -jalv_native_ui_type(void) +jalv_frontend_ui_type(void) { - return NULL; + return NULL; } static void jalv_print_controls(Jalv* jalv, bool writable, bool readable) { - for (size_t i = 0; i < jalv->controls.n_controls; ++i) { - ControlID* const control = jalv->controls.controls[i]; - if ((control->is_writable && writable) || - (control->is_readable && readable)) { - struct Port* const port = &jalv->ports[control->index]; - printf("%s = %f\n", - lilv_node_as_string(control->symbol), - port->control); - } - } + for (size_t i = 0; i < jalv->controls.n_controls; ++i) { + ControlID* const control = jalv->controls.controls[i]; + if ((control->is_writable && writable) || + (control->is_readable && readable)) { + struct Port* const port = &jalv->ports[control->index]; + jalv_log(JALV_LOG_INFO, + "%s = %f\n", + lilv_node_as_string(control->symbol), + port->control); + } + } + + fflush(stdout); } static int -jalv_print_preset(Jalv* jalv, +jalv_print_preset(Jalv* ZIX_UNUSED(jalv), const LilvNode* node, const LilvNode* title, - void* data) + void* ZIX_UNUSED(data)) { - printf("%s (%s)\n", lilv_node_as_string(node), lilv_node_as_string(title)); - return 0; + printf("%s (%s)\n", lilv_node_as_string(node), lilv_node_as_string(title)); + return 0; } static void jalv_process_command(Jalv* jalv, const char* cmd) { - char sym[1024]; - uint32_t index; - float value; - if (!strncmp(cmd, "help", 4)) { - fprintf(stderr, - "Commands:\n" - " help Display this help message\n" - " controls Print settable control values\n" - " monitors Print output control values\n" - " presets Print available presets\n" - " preset URI Set preset\n" - " set INDEX VALUE Set control value by port index\n" - " set SYMBOL VALUE Set control value by symbol\n" - " SYMBOL = VALUE Set control value by symbol\n"); - } else if (strcmp(cmd, "presets\n") == 0) { - jalv_unload_presets(jalv); - jalv_load_presets(jalv, jalv_print_preset, NULL); - } else if (sscanf(cmd, "preset %1023[a-zA-Z0-9_:/-.#]\n", sym) == 1) { - LilvNode* preset = lilv_new_uri(jalv->world, sym); - jalv_apply_preset(jalv, preset); - lilv_node_free(preset); - jalv_print_controls(jalv, true, false); - } else if (strcmp(cmd, "controls\n") == 0) { - jalv_print_controls(jalv, true, false); - } else if (strcmp(cmd, "monitors\n") == 0) { - jalv_print_controls(jalv, false, true); - } else if (sscanf(cmd, "set %u %f", &index, &value) == 2) { - if (index < jalv->num_ports) { - jalv->ports[index].control = value; - jalv_print_control(jalv, &jalv->ports[index], value); - } else { - fprintf(stderr, "error: port index out of range\n"); - } - } else if (sscanf(cmd, "set %1023[a-zA-Z0-9_] %f", sym, &value) == 2 || - sscanf(cmd, "%1023[a-zA-Z0-9_] = %f", sym, &value) == 2) { - struct Port* port = NULL; - for (uint32_t i = 0; i < jalv->num_ports; ++i) { - struct Port* p = &jalv->ports[i]; - const LilvNode* s = lilv_port_get_symbol(jalv->plugin, p->lilv_port); - if (!strcmp(lilv_node_as_string(s), sym)) { - port = p; - break; - } - } - if (port) { - port->control = value; - jalv_print_control(jalv, port, value); - } else { - fprintf(stderr, "error: no control named `%s'\n", sym); - } - } else { - fprintf(stderr, "error: invalid command (try `help')\n"); - } + char sym[1024]; + uint32_t index = 0; + float value = 0.0f; + if (!strncmp(cmd, "help", 4)) { + fprintf(stderr, + "Commands:\n" + " help Display this help message\n" + " controls Print settable control values\n" + " monitors Print output control values\n" + " presets Print available presets\n" + " preset URI Set preset\n" + " set INDEX VALUE Set control value by port index\n" + " set SYMBOL VALUE Set control value by symbol\n" + " SYMBOL = VALUE Set control value by symbol\n"); + } else if (strcmp(cmd, "presets\n") == 0) { + jalv_unload_presets(jalv); + jalv_load_presets(jalv, jalv_print_preset, NULL); + } else if (sscanf(cmd, "preset %1023[a-zA-Z0-9_:/-.#]\n", sym) == 1) { + LilvNode* preset = lilv_new_uri(jalv->world, sym); + lilv_world_load_resource(jalv->world, preset); + jalv_apply_preset(jalv, preset); + lilv_node_free(preset); + jalv_print_controls(jalv, true, false); + } else if (strcmp(cmd, "controls\n") == 0) { + jalv_print_controls(jalv, true, false); + } else if (strcmp(cmd, "monitors\n") == 0) { + jalv_print_controls(jalv, false, true); + } else if (sscanf(cmd, "set %u %f", &index, &value) == 2) { + if (index < jalv->num_ports) { + jalv->ports[index].control = value; + jalv_print_control(jalv, &jalv->ports[index], value); + } else { + fprintf(stderr, "error: port index out of range\n"); + } + } else if (sscanf(cmd, "set %1023[a-zA-Z0-9_] %f", sym, &value) == 2 || + sscanf(cmd, "%1023[a-zA-Z0-9_] = %f", sym, &value) == 2) { + struct Port* port = NULL; + for (uint32_t i = 0; i < jalv->num_ports; ++i) { + struct Port* p = &jalv->ports[i]; + const LilvNode* s = lilv_port_get_symbol(jalv->plugin, p->lilv_port); + if (!strcmp(lilv_node_as_string(s), sym)) { + port = p; + break; + } + } + if (port) { + port->control = value; + jalv_print_control(jalv, port, value); + } else { + fprintf(stderr, "error: no control named `%s'\n", sym); + } + } else { + fprintf(stderr, "error: invalid command (try `help')\n"); + } } bool -jalv_discover_ui(Jalv* jalv) +jalv_frontend_discover(Jalv* jalv) { - return jalv->opts.show_ui; + return jalv->opts.show_ui; } static bool jalv_run_custom_ui(Jalv* jalv) { -#ifdef HAVE_SUIL - const LV2UI_Idle_Interface* idle_iface = NULL; - const LV2UI_Show_Interface* show_iface = NULL; - if (jalv->ui && jalv->opts.show_ui) { - jalv_ui_instantiate(jalv, jalv_native_ui_type(), NULL); - idle_iface = (const LV2UI_Idle_Interface*) - suil_instance_extension_data(jalv->ui_instance, LV2_UI__idleInterface); - show_iface = (const LV2UI_Show_Interface*) - suil_instance_extension_data(jalv->ui_instance, LV2_UI__showInterface); - } +#if USE_SUIL + const LV2UI_Idle_Interface* idle_iface = NULL; + const LV2UI_Show_Interface* show_iface = NULL; + if (jalv->ui && jalv->opts.show_ui) { + jalv_ui_instantiate(jalv, jalv_frontend_ui_type(), NULL); + idle_iface = (const LV2UI_Idle_Interface*)suil_instance_extension_data( + jalv->ui_instance, LV2_UI__idleInterface); + show_iface = (const LV2UI_Show_Interface*)suil_instance_extension_data( + jalv->ui_instance, LV2_UI__showInterface); + } - if (show_iface && idle_iface) { - show_iface->show(suil_instance_get_handle(jalv->ui_instance)); + if (show_iface && idle_iface) { + show_iface->show(suil_instance_get_handle(jalv->ui_instance)); - // Drive idle interface until interrupted - while (!zix_sem_try_wait(&jalv->done)) { - jalv_update(jalv); - if (idle_iface->idle(suil_instance_get_handle(jalv->ui_instance))) { - break; - } - usleep(33333); - } + // Drive idle interface until interrupted + while (zix_sem_try_wait(&jalv->done)) { + jalv_update(jalv); + if (idle_iface->idle(suil_instance_get_handle(jalv->ui_instance))) { + break; + } - show_iface->hide(suil_instance_get_handle(jalv->ui_instance)); - return true; - } +# ifdef _WIN32 + Sleep(33); +# else + usleep(33333); +# endif + } + + show_iface->hide(suil_instance_get_handle(jalv->ui_instance)); + return true; + } +#else + (void)jalv; #endif - return false; + return false; } float -jalv_ui_refresh_rate(Jalv* jalv) +jalv_frontend_refresh_rate(Jalv* ZIX_UNUSED(jalv)) +{ + return 30.0f; +} + +float +jalv_frontend_scale_factor(Jalv* ZIX_UNUSED(jalv)) +{ + return 1.0f; +} + +LilvNode* +jalv_frontend_select_plugin(Jalv* jalv) { - return 30.0f; + (void)jalv; + return NULL; } int -jalv_open_ui(Jalv* jalv) +jalv_frontend_open(Jalv* jalv) { - if (!jalv_run_custom_ui(jalv) && !jalv->opts.non_interactive) { - // Primitive command prompt for setting control values - while (!zix_sem_try_wait(&jalv->done)) { - char line[1024]; - printf("> "); - if (fgets(line, sizeof(line), stdin)) { - jalv_process_command(jalv, line); - } else { - break; - } - } - } else { - zix_sem_wait(&jalv->done); - } + if (!jalv_run_custom_ui(jalv) && !jalv->opts.non_interactive) { + // Primitive command prompt for setting control values + while (zix_sem_try_wait(&jalv->done)) { + char line[1024]; + printf("> "); + if (fgets(line, sizeof(line), stdin)) { + jalv_process_command(jalv, line); + } else { + break; + } + } + } else { + zix_sem_wait(&jalv->done); + } - // Caller waits on the done sem, so increment it again to exit - zix_sem_post(&jalv->done); + // Caller waits on the done sem, so increment it again to exit + zix_sem_post(&jalv->done); - return 0; + return 0; } int -jalv_close_ui(Jalv* jalv) +jalv_frontend_close(Jalv* jalv) { - zix_sem_post(&jalv->done); - return 0; + zix_sem_post(&jalv->done); + return 0; } |