ref: fcababf01b6363d8aababfbd5d62a79f68ec867c
parent: 2ebfe03d0d57a4ff315fbd421284e4544fe85922
author: cancel <cancel@cancel.fm>
date: Wed Jan 22 22:32:58 EST 2020
Move OSC configuration to menus and conf file
--- a/osc_out.c
+++ b/osc_out.c
@@ -27,7 +27,9 @@
struct addrinfo *head = NULL;
int err = getaddrinfo(dest_addr, dest_port, &hints, &head);
if (err != 0) {
+#if 0
fprintf(stderr, "Failed to get address info, error: %d\n", errno);
+#endif
return Oosc_udp_create_error_getaddrinfo_failed;
}
// Special behavior: if no hostname was provided, we'll get loopback(s) from
@@ -72,7 +74,9 @@
int udpfd =
socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol);
if (udpfd < 0) {
+#if 0
fprintf(stderr, "Failed to open UDP socket, error number: %d\n", errno);
+#endif
freeaddrinfo(head);
return Oosc_udp_create_error_couldnt_open_socket;
}
@@ -93,10 +97,14 @@
void oosc_send_datagram(Oosc_dev *dev, char const *data, Usz size) {
ssize_t res = sendto(dev->fd, data, size, 0, dev->chosen->ai_addr,
dev->chosen->ai_addrlen);
+ (void)res;
+ // TODO handle this in UI somehow
+#if 0
if (res < 0) {
fprintf(stderr, "UDP message send failed\n");
exit(1);
}
+#endif
}
static bool oosc_write_strn(char *restrict buffer, Usz buffer_size,
--- a/sysmisc.c
+++ b/sysmisc.c
@@ -127,8 +127,10 @@
}
for (;;) { // scan for first non-whitespace after '='
b0++;
- if (b0 == len)
- goto ignore;
+ if (b0 == len) { // empty right side, but still valid pair
+ b1 = b0;
+ goto ok;
+ }
char c = s[b0];
if (!isspace(c))
break;
@@ -161,14 +163,14 @@
fail:
*out_left = NULL;
*out_leftsize = 0;
- goto no_right;
+ goto null_right;
ignore:
s[len - 1] = '\0';
*out_left = s;
*out_leftsize = len;
err = Conf_read_irrelevant;
- goto no_right;
-no_right:
+ goto null_right;
+null_right:
*out_right = NULL;
*out_rightsize = 0;
return err;
--- a/term_util.c
+++ b/term_util.c
@@ -450,6 +450,17 @@
qm->initial_item = found;
}
}
+int qmenu_current_item(Qmenu *qm) {
+ ITEM *item = NULL;
+ if (qm->ncurses_menu)
+ item = current_item(qm->ncurses_menu);
+ if (!item)
+ item = qm->initial_item;
+ if (!item)
+ return 0;
+ struct Qmenu_item_extra *extras = qmenu_item_extras_ptr(qm);
+ return qmenu_itemextra(extras, item)->user_id;
+}
void qmenu_set_displayed_active(Qmenu *qm, bool active) {
// Could add a flag in the Qmenu to avoid redundantly changing this stuff.
set_menu_fore(qm->ncurses_menu, active ? A_BOLD : A_DIM);
--- a/term_util.h
+++ b/term_util.h
@@ -148,6 +148,7 @@
void qmenu_set_current_item(Qmenu *qm, int id);
void qmenu_set_displayed_active(Qmenu *qm, bool active);
void qmenu_push_to_nav(Qmenu *qm);
+int qmenu_current_item(Qmenu *qm);
bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action);
Qmenu *qmenu_of(Qblock *qb);
bool qmenu_top_is_menu(int id);
--- a/thirdparty/oso.c
+++ b/thirdparty/oso.c
@@ -184,8 +184,8 @@
osofree(*p);
*p = NULL;
}
-void ososwap(oso const **a, oso const **b) {
- oso const *tmp = *a;
+void ososwap(oso **a, oso **b) {
+ oso *tmp = *a;
*a = *b;
*b = tmp;
}
--- a/thirdparty/oso.h
+++ b/thirdparty/oso.h
@@ -36,7 +36,7 @@
// `oso **` -> Must not be null, but the `oso *` pointed to
// can be null. The pointed-to `oso *` may be
// modified during the call.
-//
+//
// 3. `oso *` and `char const *` as arguments to the functions here must not
// overlap in memory. During the call, the buffer pointed to by a `oso *`
// might need to be reallocated in memory to make room for the `char const
@@ -158,7 +158,7 @@
void osowipe(oso **p) OSO_NONNULL();
// ^- It's like `osofree()`, except you give it a ptr-to-ptr, and it also sets
// `*p` to null for you when it's done freeing the memory.
-void ososwap(oso const **a, oso const **b) OSO_NONNULL();
+void ososwap(oso **a, oso **b) OSO_NONNULL();
// ^- Swaps the two pointers. Yeah, that's all it does. Why? Because it's
// common when dealing memory management for individually allocated strings
// and changing between old and new string values.
--- a/tui_main.c
+++ b/tui_main.c
@@ -45,15 +45,6 @@
" Reduce the timing jitter of outgoing MIDI and OSC messages.\n"
" Uses more CPU time.\n"
"\n"
-" --osc-server <address>\n"
-" Hostname or IP address to send OSC messages to.\n"
-" Default: loopback (this machine)\n"
-"\n"
-" --osc-port <number or service name>\n"
-" UDP port (or service name) to send OSC messages to.\n"
-" This option must be set for OSC output to be enabled.\n"
-" Default: none\n"
-"\n"
" --osc-midi-bidule <path>\n"
" Set MIDI to be sent via OSC formatted for Plogue Bidule.\n"
" The path argument is the path of the Plogue OSC MIDI device.\n"
@@ -971,21 +962,6 @@
return a->is_draw_dirty || a->needs_remarking;
}
-bool ged_set_osc_udp(Ged *a, char const *dest_addr, char const *dest_port) {
- if (a->oosc_dev) {
- oosc_dev_destroy(a->oosc_dev);
- a->oosc_dev = NULL;
- }
- if (dest_port) {
- Oosc_udp_create_error err =
- oosc_dev_create_udp(&a->oosc_dev, dest_addr, dest_port);
- if (err) {
- return false;
- }
- }
- return true;
-}
-
void ged_set_midi_mode(Ged *a, Midi_mode const *midi_mode) {
a->midi_mode = midi_mode;
}
@@ -1012,7 +988,7 @@
break;
case Midi_mode_type_osc_bidule: {
if (!oosc_dev)
- break; // not sure if needed
+ break;
oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path,
(int[]){type << 4 | chan, byte1, byte2}, 3);
break;
@@ -1232,6 +1208,28 @@
}
}
+void ged_clear_osc_udp(Ged *a) {
+ if (a->oosc_dev) {
+ if (a->midi_mode && a->midi_mode->any.type == Midi_mode_type_osc_bidule) {
+ ged_stop_all_sustained_notes(a);
+ }
+ oosc_dev_destroy(a->oosc_dev);
+ a->oosc_dev = NULL;
+ }
+}
+bool ged_is_using_osc_udp(Ged *a) { return (bool)a->oosc_dev; }
+bool ged_set_osc_udp(Ged *a, char const *dest_addr, char const *dest_port) {
+ ged_clear_osc_udp(a);
+ if (dest_port) {
+ Oosc_udp_create_error err =
+ oosc_dev_create_udp(&a->oosc_dev, dest_addr, dest_port);
+ if (err) {
+ return false;
+ }
+ }
+ return true;
+}
+
static double ms_to_sec(double ms) { return ms / 1000.0; }
double ged_secs_to_deadline(Ged const *a) {
@@ -1950,6 +1948,9 @@
Autofit_menu_id,
Confirm_new_file_menu_id,
Cosmetics_menu_id,
+ Osc_menu_id,
+ Osc_output_address_form_id,
+ Osc_output_port_form_id,
Set_soft_margins_form_id,
Set_fancy_grid_dots_menu_id,
Set_fancy_grid_rulers_menu_id,
@@ -1981,6 +1982,7 @@
Main_menu_autofit_grid,
Main_menu_about,
Main_menu_cosmetics,
+ Main_menu_osc,
#ifdef FEAT_PORTMIDI
Main_menu_choose_portmidi_output,
#endif
@@ -1998,10 +2000,11 @@
qmenu_add_choice(qm, Main_menu_set_grid_dims, "Set Grid Size...");
qmenu_add_choice(qm, Main_menu_autofit_grid, "Auto-fit Grid");
qmenu_add_spacer(qm);
+ qmenu_add_choice(qm, Main_menu_osc, "OSC Output...");
#ifdef FEAT_PORTMIDI
qmenu_add_choice(qm, Main_menu_choose_portmidi_output, "MIDI Output...");
- qmenu_add_spacer(qm);
#endif
+ qmenu_add_spacer(qm);
qmenu_add_choice(qm, Main_menu_cosmetics, "Appearance...");
qmenu_add_choice(qm, Main_menu_controls, "Controls...");
qmenu_add_choice(qm, Main_menu_opers_guide, "Operators...");
@@ -2039,9 +2042,6 @@
Cosmetics_grid_dots_id,
Cosmetics_grid_rulers_id,
};
-enum {
- Soft_margins_text_line_id = 1,
-};
void push_cosmetics_menu(void) {
Qmenu *qm = qmenu_create(Cosmetics_menu_id);
qmenu_set_title(qm, "Appearance");
@@ -2056,7 +2056,7 @@
int snres = snprintf(buff, sizeof buff, "%dx%d", init_x, init_y);
char const *inistr = snres > 0 && (Usz)snres < sizeof buff ? buff : "2x1";
qform_set_title(qf, "Set Margins");
- qform_add_text_line(qf, Soft_margins_text_line_id, inistr);
+ qform_add_text_line(qf, Single_form_item_id, inistr);
qform_push_to_nav(qf);
}
void push_plainorfancy_menu(int menu_id, char const *title,
@@ -2070,6 +2070,34 @@
qmenu_push_to_nav(qm);
}
+enum {
+ Osc_menu_output_enabledisable = 1,
+ Osc_menu_output_address,
+ Osc_menu_output_port,
+};
+
+void push_osc_menu(bool output_enabled) {
+ Qmenu *qm = qmenu_create(Osc_menu_id);
+ qmenu_set_title(qm, "OSC Output");
+ qmenu_add_printf(qm, Osc_menu_output_enabledisable, "[%c] OSC Output Enabled",
+ output_enabled ? '*' : ' ');
+ qmenu_add_choice(qm, Osc_menu_output_address, "OSC Output Address...");
+ qmenu_add_choice(qm, Osc_menu_output_port, "OSC Output Port...");
+ qmenu_push_to_nav(qm);
+}
+void push_osc_output_address_form(char const *initial) {
+ Qform *qf = qform_create(Osc_output_address_form_id);
+ qform_set_title(qf, "Set OSC Output Address");
+ qform_add_text_line(qf, Single_form_item_id, initial);
+ qform_push_to_nav(qf);
+}
+void push_osc_output_port_form(char const *initial) {
+ Qform *qf = qform_create(Osc_output_port_form_id);
+ qform_set_title(qf, "Set OSC Output Port");
+ qform_add_text_line(qf, Single_form_item_id, initial);
+ qform_push_to_nav(qf);
+}
+
void push_about_msg(void) {
// clang-format off
static char const* logo[] = {
@@ -2445,13 +2473,19 @@
typedef struct {
oso *portmidi_output_device;
+ oso *osc_output_address;
+ oso *osc_output_port;
int softmargin_y, softmargin_x;
- bool fancy_grid_dots : 1, fancy_grid_rulers : 1;
+ bool osc_output_enabled : 1, fancy_grid_dots : 1, fancy_grid_rulers : 1;
U32 touched;
} Prefs;
void prefs_init(Prefs *p) { *p = (Prefs){0}; }
-void prefs_deinit(Prefs *p) { osofree(p->portmidi_output_device); }
+void prefs_deinit(Prefs *p) {
+ osofree(p->portmidi_output_device);
+ osofree(p->osc_output_address);
+ osofree(p->osc_output_port);
+}
typedef enum {
Prefs_load_ok = 0,
@@ -2459,6 +2493,9 @@
char const *const confopts[] = {
"portmidi_output_device",
+ "osc_output_address",
+ "osc_output_port",
+ "osc_output_enabled",
"margins",
"grid_dot_type",
"grid_ruler_type",
@@ -2466,16 +2503,20 @@
enum { Confoptslen = ORCA_ARRAY_COUNTOF(confopts) };
enum {
Confopt_portmidi_output_device = 0,
+ Confopt_osc_output_address,
+ Confopt_osc_output_port,
+ Confopt_osc_output_enabled,
Confopt_margins,
Confopt_grid_dot_type,
Confopt_grid_ruler_type,
};
-enum {
- Preftouch_softmargins = 1 << 0,
- Preftouch_griddotstype = 1 << 1,
- Preftouch_gridrulerstype = 1 << 2,
-};
+// Use this to create a bitflag out of a Confopt_. These flags are used to
+// indicate that a setting has been touched by the user. In other words, these
+// flags are used to check whether or not a particular setting should be
+// written back to the conf file during a conf file save.
+#define TOUCHFLAG(_confopt) (1u << (Usz)_confopt)
+
char const *const prefval_plain = "plain";
char const *const prefval_fancy = "fancy";
@@ -2493,6 +2534,25 @@
}
ORCA_FORCE_NO_INLINE
+bool conf_read_boolish(char const *val, bool *out) {
+ static char const *const trues[] = {"1", "true", "yes"};
+ static char const *const falses[] = {"0", "false", "no"};
+ for (Usz i = 0; i < ORCA_ARRAY_COUNTOF(trues); i++) {
+ if (strcmp(val, trues[i]) != 0)
+ continue;
+ *out = true;
+ return true;
+ }
+ for (Usz i = 0; i < ORCA_ARRAY_COUNTOF(falses); i++) {
+ if (strcmp(val, falses[i]) != 0)
+ continue;
+ *out = false;
+ return true;
+ }
+ return false;
+}
+
+ORCA_FORCE_NO_INLINE
Prefs_load_error prefs_load_from_conf_file(Prefs *p) {
Ezconf_r ez;
for (ezconf_r_start(&ez); ezconf_r_step(&ez, confopts, Confoptslen);) {
@@ -2500,6 +2560,27 @@
case Confopt_portmidi_output_device:
osoput(&p->portmidi_output_device, ez.value);
break;
+ case Confopt_osc_output_address: {
+ // Don't actually allocate heap string if string is empty
+ Usz len = strlen(ez.value);
+ if (len > 0)
+ osoputlen(&p->osc_output_address, ez.value, len);
+ p->touched |= TOUCHFLAG(Confopt_osc_output_address);
+ break;
+ }
+ case Confopt_osc_output_port: {
+ osoput(&p->osc_output_port, ez.value);
+ p->touched |= TOUCHFLAG(Confopt_osc_output_port);
+ break;
+ }
+ case Confopt_osc_output_enabled: {
+ bool enabled;
+ if (conf_read_boolish(ez.value, &enabled)) {
+ p->osc_output_enabled = enabled;
+ p->touched |= TOUCHFLAG(Confopt_osc_output_enabled);
+ }
+ break;
+ }
case Confopt_margins: {
int softmargin_y, softmargin_x;
if (read_nxn_or_n(ez.value, &softmargin_x, &softmargin_y) &&
@@ -2506,7 +2587,7 @@
softmargin_y >= 0 && softmargin_x >= 0) {
p->softmargin_y = softmargin_y;
p->softmargin_x = softmargin_x;
- p->touched |= Preftouch_softmargins;
+ p->touched |= TOUCHFLAG(Confopt_margins);
}
break;
}
@@ -2514,7 +2595,7 @@
bool fancy;
if (plainorfancy(ez.value, &fancy)) {
p->fancy_grid_dots = fancy;
- p->touched |= Preftouch_griddotstype;
+ p->touched |= TOUCHFLAG(Confopt_grid_dot_type);
}
break;
}
@@ -2522,7 +2603,7 @@
bool fancy;
if (plainorfancy(ez.value, &fancy)) {
p->fancy_grid_rulers = fancy;
- p->touched |= Preftouch_gridrulerstype;
+ p->touched |= TOUCHFLAG(Confopt_grid_ruler_type);
}
break;
}
@@ -2548,7 +2629,7 @@
typedef struct {
Ged ged;
oso *file_name;
- oso *osc_hostname, *osc_port;
+ oso *osc_address, *osc_port;
int undo_history_limit;
int softmargin_y, softmargin_x;
int hardmargin_y, hardmargin_x;
@@ -2555,6 +2636,7 @@
U32 prefs_touched;
bool use_gui_cboard;
bool strict_timing;
+ bool osc_output_enabled;
bool fancy_grid_dots;
bool fancy_grid_rulers;
Midi_mode midi_mode;
@@ -2586,16 +2668,38 @@
}
#endif
}
- if (t->prefs_touched & Preftouch_softmargins)
+ // TODO ok, this is redundant now
+ if (t->prefs_touched & TOUCHFLAG(Confopt_osc_output_address))
+ ezconf_w_addopt(&ez, confopts[Confopt_osc_output_address],
+ Confopt_osc_output_address);
+ if (t->prefs_touched & TOUCHFLAG(Confopt_osc_output_port))
+ ezconf_w_addopt(&ez, confopts[Confopt_osc_output_port],
+ Confopt_osc_output_port);
+ if (t->prefs_touched & TOUCHFLAG(Confopt_osc_output_enabled))
+ ezconf_w_addopt(&ez, confopts[Confopt_osc_output_enabled],
+ Confopt_osc_output_enabled);
+ if (t->prefs_touched & TOUCHFLAG(Confopt_margins))
ezconf_w_addopt(&ez, confopts[Confopt_margins], Confopt_margins);
- if (t->prefs_touched & Preftouch_griddotstype)
+ if (t->prefs_touched & TOUCHFLAG(Confopt_grid_dot_type))
ezconf_w_addopt(&ez, confopts[Confopt_grid_dot_type],
Confopt_grid_dot_type);
- if (t->prefs_touched & Preftouch_gridrulerstype)
+ if (t->prefs_touched & TOUCHFLAG(Confopt_grid_ruler_type))
ezconf_w_addopt(&ez, confopts[Confopt_grid_ruler_type],
Confopt_grid_ruler_type);
while (ezconf_w_step(&ez)) {
switch (ez.optid) {
+ case Confopt_osc_output_address:
+ // Fine to not write anything here
+ if (osolen(t->osc_address))
+ fputs(osoc(t->osc_address), ez.file);
+ break;
+ case Confopt_osc_output_port:
+ if (osolen(t->osc_port))
+ fputs(osoc(t->osc_port), ez.file);
+ break;
+ case Confopt_osc_output_enabled:
+ fputc(t->osc_output_enabled ? '1' : '0', ez.file);
+ break;
#ifdef FEAT_PORTMIDI
case Confopt_portmidi_output_device:
fputs(osoc(midi_output_device_name), ez.file);
@@ -2674,6 +2778,37 @@
t->ged.is_draw_dirty = true;
}
+bool tui_restart_osc_udp_if_enabled_diderror(Tui *t) {
+ bool error = false;
+ if (t->osc_output_enabled && t->osc_port) {
+ error = !ged_set_osc_udp(&t->ged, osoc(t->osc_address) /* null ok here */,
+ osoc(t->osc_port));
+ } else {
+ ged_clear_osc_udp(&t->ged);
+ }
+ return error;
+}
+void tui_restart_osc_udp_showerror(void) {
+ qmsg_printf_push("OSC Networking Error", "Failed to set up OSC networking");
+}
+void tui_restart_osc_udp_if_enabled(Tui *t) {
+ bool old_inuse = ged_is_using_osc_udp(&t->ged);
+ bool did_error = tui_restart_osc_udp_if_enabled_diderror(t);
+ bool new_inuse = ged_is_using_osc_udp(&t->ged);
+ if (old_inuse != new_inuse) {
+ Qblock *qb = qnav_top_block();
+ if (qb && qb->tag == Qblock_type_qmenu &&
+ qmenu_id(qmenu_of(qb)) == Osc_menu_id) {
+ int itemid = qmenu_current_item(qmenu_of(qb));
+ qnav_stack_pop();
+ push_osc_menu(new_inuse);
+ qmenu_set_current_item(qmenu_of(qnav_top_block()), itemid);
+ }
+ }
+ if (did_error)
+ tui_restart_osc_udp_showerror();
+}
+
//
// main
//
@@ -2683,13 +2818,12 @@
Argopt_hardmargins,
Argopt_undo_limit,
Argopt_init_grid_size,
- Argopt_osc_server,
- Argopt_osc_port,
Argopt_osc_midi_bidule,
Argopt_strict_timing,
Argopt_bpm,
Argopt_seed,
Argopt_portmidi_deprecated,
+ Argopt_osc_deprecated,
};
int main(int argc, char **argv) {
@@ -2699,8 +2833,6 @@
{"undo-limit", required_argument, 0, Argopt_undo_limit},
{"initial-size", required_argument, 0, Argopt_init_grid_size},
{"help", no_argument, 0, 'h'},
- {"osc-server", required_argument, 0, Argopt_osc_server},
- {"osc-port", required_argument, 0, Argopt_osc_port},
{"osc-midi-bidule", required_argument, 0, Argopt_osc_midi_bidule},
{"strict-timing", no_argument, 0, Argopt_strict_timing},
{"bpm", required_argument, 0, Argopt_bpm},
@@ -2708,6 +2840,8 @@
{"portmidi-list-devices", no_argument, 0, Argopt_portmidi_deprecated},
{"portmidi-output-device", required_argument, 0,
Argopt_portmidi_deprecated},
+ {"osc-server", required_argument, 0, Argopt_osc_deprecated},
+ {"osc-port", required_argument, 0, Argopt_osc_deprecated},
{NULL, 0, NULL, 0}};
int init_bpm = 120;
int init_seed = 1;
@@ -2815,12 +2949,6 @@
}
break;
}
- case Argopt_osc_server:
- osoput(&t.osc_hostname, optarg);
- break;
- case Argopt_osc_port:
- osoput(&t.osc_port, optarg);
- break;
case Argopt_osc_midi_bidule:
midi_mode_deinit(&t.midi_mode);
midi_mode_init_osc_bidule(&t.midi_mode, optarg);
@@ -2828,7 +2956,7 @@
case Argopt_strict_timing:
t.strict_timing = true;
break;
- case Argopt_portmidi_deprecated: {
+ case Argopt_portmidi_deprecated:
fprintf(stderr,
"Option \"--%s\" has been removed.\nInstead, choose "
"your MIDI output device from within the ORCA menu.\n"
@@ -2837,8 +2965,14 @@
tui_options[longindex].name);
exit(1);
break;
+ case Argopt_osc_deprecated:
+ fprintf(
+ stderr,
+ "Options --osc-server and --osc-port have been removed.\n"
+ "Instead, set the OSC server and port from within the ORCA menu.\n");
+ exit(1);
+ break;
}
- }
}
if (optind == argc - 1) {
@@ -2852,30 +2986,6 @@
qnav_init();
ged_init(&t.ged, (Usz)t.undo_history_limit, (Usz)init_bpm, (Usz)init_seed);
- if (t.osc_hostname != NULL && t.osc_port == NULL) {
- fprintf(stderr,
- "An OSC server address was specified, but no OSC port was "
- "specified.\n"
- "OSC output is not possible without specifying an OSC port.\n");
- ged_deinit(&t.ged);
- exit(1);
- }
- if (t.midi_mode.any.type == Midi_mode_type_osc_bidule && t.osc_port == NULL) {
- fprintf(stderr,
- "MIDI was set to be sent via OSC formatted for Plogue Bidule,\n"
- "but no OSC port was specified.\n"
- "OSC output is not possible without specifying an OSC port.\n");
- ged_deinit(&t.ged);
- exit(1);
- }
- if (t.osc_port) {
- if (!ged_set_osc_udp(&t.ged, osoc(t.osc_hostname), osoc(t.osc_port))) {
- fprintf(stderr, "Failed to set up OSC networking\n");
- ged_deinit(&t.ged);
- exit(1);
- }
- }
-
if (osolen(t.file_name)) {
Field_load_error fle = field_load_file(osoc(t.file_name), &t.ged.field);
if (fle != Field_load_error_ok) {
@@ -2953,14 +3063,27 @@
Prefs_load_error prefserr = prefs_load_from_conf_file(&prefs);
if (prefserr == Prefs_load_ok) {
t.prefs_touched |= prefs.touched;
- if (prefs.touched & Preftouch_softmargins) {
+ if (prefs.touched & TOUCHFLAG(Confopt_osc_output_address)) {
+ ososwap(&t.osc_address, &prefs.osc_output_address);
+ } else {
+ // leave null
+ }
+ if (prefs.touched & TOUCHFLAG(Confopt_osc_output_port)) {
+ ososwap(&t.osc_port, &prefs.osc_output_port);
+ } else {
+ osoput(&t.osc_port, "49162");
+ }
+ if (prefs.touched & TOUCHFLAG(Confopt_osc_output_enabled)) {
+ t.osc_output_enabled = prefs.osc_output_enabled;
+ }
+ if (prefs.touched & TOUCHFLAG(Confopt_margins)) {
t.softmargin_y = prefs.softmargin_y;
t.softmargin_x = prefs.softmargin_x;
}
- if (prefs.touched & Preftouch_griddotstype) {
+ if (prefs.touched & TOUCHFLAG(Confopt_grid_dot_type)) {
t.fancy_grid_dots = prefs.fancy_grid_dots;
}
- if (prefs.touched & Preftouch_gridrulerstype) {
+ if (prefs.touched & TOUCHFLAG(Confopt_grid_ruler_type)) {
t.fancy_grid_rulers = prefs.fancy_grid_rulers;
}
#ifdef FEAT_PORTMIDI
@@ -2988,6 +3111,8 @@
}
prefs_deinit(&prefs);
+ tui_restart_osc_udp_if_enabled(&t);
+
WINDOW *cont_window = NULL;
int key = KEY_RESIZE;
@@ -3248,6 +3373,9 @@
case Main_menu_cosmetics:
push_cosmetics_menu();
break;
+ case Main_menu_osc:
+ push_osc_menu(ged_is_using_osc_udp(&t.ged));
+ break;
case Main_menu_controls:
push_controls_msg();
break;
@@ -3361,13 +3489,37 @@
break;
case Set_fancy_grid_dots_menu_id:
plainorfancy_menu_was_picked(&t, act.picked.id, &t.fancy_grid_dots,
- Preftouch_griddotstype);
+ TOUCHFLAG(Confopt_grid_dot_type));
break;
case Set_fancy_grid_rulers_menu_id:
plainorfancy_menu_was_picked(&t, act.picked.id,
&t.fancy_grid_rulers,
- Preftouch_gridrulerstype);
+ TOUCHFLAG(Confopt_grid_ruler_type));
break;
+ case Osc_menu_id:
+ switch (act.picked.id) {
+ case Osc_menu_output_enabledisable: {
+ qnav_stack_pop();
+ t.osc_output_enabled = !ged_is_using_osc_udp(&t.ged);
+ // Funny dance to keep the qnav stack in good order
+ bool diderror = tui_restart_osc_udp_if_enabled_diderror(&t);
+ push_osc_menu(ged_is_using_osc_udp(&t.ged));
+ if (diderror) {
+ t.osc_output_enabled = false;
+ tui_restart_osc_udp_showerror();
+ }
+ t.prefs_touched |= TOUCHFLAG(Confopt_osc_output_enabled);
+ tui_save_prefs(&t);
+ break;
+ }
+ case Osc_menu_output_address:
+ push_osc_output_address_form(osoc(t.osc_address) /* null ok */);
+ break;
+ case Osc_menu_output_port:
+ push_osc_output_port_form(osoc(t.osc_port) /* null ok */);
+ break;
+ }
+ break;
#ifdef FEAT_PORTMIDI
case Portmidi_output_device_menu_id: {
ged_stop_all_sustained_notes(&t.ged);
@@ -3452,6 +3604,35 @@
osofree(tmpstr);
break;
}
+ case Osc_output_address_form_id: {
+ oso *addr = NULL;
+ // Empty string is OK here
+ if (qform_get_text_line(qf, Single_form_item_id, &addr)) {
+ if (osolen(addr)) {
+ ososwap(&t.osc_address, &addr);
+ } else {
+ osowipe(&t.osc_address);
+ }
+ qnav_stack_pop();
+ tui_restart_osc_udp_if_enabled(&t);
+ t.prefs_touched |= TOUCHFLAG(Confopt_osc_output_address);
+ tui_save_prefs(&t);
+ }
+ osofree(addr);
+ break;
+ }
+ case Osc_output_port_form_id: {
+ oso *portstr = get_nonempty_singular_form_text(qf);
+ if (!portstr)
+ break;
+ qnav_stack_pop();
+ ososwap(&t.osc_port, &portstr);
+ tui_restart_osc_udp_if_enabled(&t);
+ osofree(portstr);
+ t.prefs_touched |= TOUCHFLAG(Confopt_osc_output_port);
+ tui_save_prefs(&t);
+ break;
+ }
case Set_grid_dims_form_id: {
oso *tmpstr = get_nonempty_singular_form_text(qf);
if (!tmpstr)
@@ -3485,7 +3666,7 @@
if (read_nxn_or_n(osoc(tmpstr), &newx, &newy) && newy >= 0 &&
newx >= 0 &&
(newy != t.softmargin_y || newx != t.softmargin_x)) {
- t.prefs_touched |= Preftouch_softmargins;
+ t.prefs_touched |= TOUCHFLAG(Confopt_margins);
t.softmargin_y = newy;
t.softmargin_x = newx;
ungetch(KEY_RESIZE); // kinda lame but whatever
@@ -3828,7 +4009,7 @@
endwin();
ged_deinit(&t.ged);
osofree(t.file_name);
- osofree(t.osc_hostname);
+ osofree(t.osc_address);
osofree(t.osc_port);
midi_mode_deinit(&t.midi_mode);
#ifdef FEAT_PORTMIDI
@@ -3837,3 +4018,5 @@
#endif
return 0;
}
+
+#undef TOUCHFLAG