Browse Source

Move OSC configuration to menus and conf file

master
cancel 5 years ago
parent
commit
fcababf01b
  1. 8
      osc_out.c
  2. 12
      sysmisc.c
  3. 11
      term_util.c
  4. 1
      term_util.h
  5. 4
      thirdparty/oso.c
  6. 2
      thirdparty/oso.h
  7. 357
      tui_main.c

8
osc_out.c

@ -27,7 +27,9 @@ Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr,
struct addrinfo *head = NULL; struct addrinfo *head = NULL;
int err = getaddrinfo(dest_addr, dest_port, &hints, &head); int err = getaddrinfo(dest_addr, dest_port, &hints, &head);
if (err != 0) { if (err != 0) {
#if 0
fprintf(stderr, "Failed to get address info, error: %d\n", errno); fprintf(stderr, "Failed to get address info, error: %d\n", errno);
#endif
return Oosc_udp_create_error_getaddrinfo_failed; return Oosc_udp_create_error_getaddrinfo_failed;
} }
// Special behavior: if no hostname was provided, we'll get loopback(s) from // Special behavior: if no hostname was provided, we'll get loopback(s) from
@ -72,7 +74,9 @@ Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr,
int udpfd = int udpfd =
socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol); socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol);
if (udpfd < 0) { if (udpfd < 0) {
#if 0
fprintf(stderr, "Failed to open UDP socket, error number: %d\n", errno); fprintf(stderr, "Failed to open UDP socket, error number: %d\n", errno);
#endif
freeaddrinfo(head); freeaddrinfo(head);
return Oosc_udp_create_error_couldnt_open_socket; return Oosc_udp_create_error_couldnt_open_socket;
} }
@ -93,10 +97,14 @@ void oosc_dev_destroy(Oosc_dev *dev) {
void oosc_send_datagram(Oosc_dev *dev, char const *data, Usz size) { 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, ssize_t res = sendto(dev->fd, data, size, 0, dev->chosen->ai_addr,
dev->chosen->ai_addrlen); dev->chosen->ai_addrlen);
(void)res;
// TODO handle this in UI somehow
#if 0
if (res < 0) { if (res < 0) {
fprintf(stderr, "UDP message send failed\n"); fprintf(stderr, "UDP message send failed\n");
exit(1); exit(1);
} }
#endif
} }
static bool oosc_write_strn(char *restrict buffer, Usz buffer_size, static bool oosc_write_strn(char *restrict buffer, Usz buffer_size,

12
sysmisc.c

@ -127,8 +127,10 @@ Conf_read_result conf_read_line(FILE *file, char *buf, Usz bufsize,
} }
for (;;) { // scan for first non-whitespace after '=' for (;;) { // scan for first non-whitespace after '='
b0++; b0++;
if (b0 == len) if (b0 == len) { // empty right side, but still valid pair
goto ignore; b1 = b0;
goto ok;
}
char c = s[b0]; char c = s[b0];
if (!isspace(c)) if (!isspace(c))
break; break;
@ -161,14 +163,14 @@ ioerror:
fail: fail:
*out_left = NULL; *out_left = NULL;
*out_leftsize = 0; *out_leftsize = 0;
goto no_right; goto null_right;
ignore: ignore:
s[len - 1] = '\0'; s[len - 1] = '\0';
*out_left = s; *out_left = s;
*out_leftsize = len; *out_leftsize = len;
err = Conf_read_irrelevant; err = Conf_read_irrelevant;
goto no_right; goto null_right;
no_right: null_right:
*out_right = NULL; *out_right = NULL;
*out_rightsize = 0; *out_rightsize = 0;
return err; return err;

11
term_util.c

@ -450,6 +450,17 @@ void qmenu_set_current_item(Qmenu *qm, int id) {
qm->initial_item = found; 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) { void qmenu_set_displayed_active(Qmenu *qm, bool active) {
// Could add a flag in the Qmenu to avoid redundantly changing this stuff. // Could add a flag in the Qmenu to avoid redundantly changing this stuff.
set_menu_fore(qm->ncurses_menu, active ? A_BOLD : A_DIM); set_menu_fore(qm->ncurses_menu, active ? A_BOLD : A_DIM);

1
term_util.h

@ -148,6 +148,7 @@ void qmenu_add_spacer(Qmenu *qm);
void qmenu_set_current_item(Qmenu *qm, int id); void qmenu_set_current_item(Qmenu *qm, int id);
void qmenu_set_displayed_active(Qmenu *qm, bool active); void qmenu_set_displayed_active(Qmenu *qm, bool active);
void qmenu_push_to_nav(Qmenu *qm); void qmenu_push_to_nav(Qmenu *qm);
int qmenu_current_item(Qmenu *qm);
bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action); bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action);
Qmenu *qmenu_of(Qblock *qb); Qmenu *qmenu_of(Qblock *qb);
bool qmenu_top_is_menu(int id); bool qmenu_top_is_menu(int id);

4
thirdparty/oso.c

@ -184,8 +184,8 @@ void osowipe(oso **p) {
osofree(*p); osofree(*p);
*p = NULL; *p = NULL;
} }
void ososwap(oso const **a, oso const **b) { void ososwap(oso **a, oso **b) {
oso const *tmp = *a; oso *tmp = *a;
*a = *b; *a = *b;
*b = tmp; *b = tmp;
} }

2
thirdparty/oso.h

@ -158,7 +158,7 @@ void osofree(oso *s);
void osowipe(oso **p) OSO_NONNULL(); void osowipe(oso **p) OSO_NONNULL();
// ^- It's like `osofree()`, except you give it a ptr-to-ptr, and it also sets // ^- 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. // `*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 // ^- Swaps the two pointers. Yeah, that's all it does. Why? Because it's
// common when dealing memory management for individually allocated strings // common when dealing memory management for individually allocated strings
// and changing between old and new string values. // and changing between old and new string values.

357
tui_main.c

@ -45,15 +45,6 @@ static void usage(void) {
" Reduce the timing jitter of outgoing MIDI and OSC messages.\n" " Reduce the timing jitter of outgoing MIDI and OSC messages.\n"
" Uses more CPU time.\n" " Uses more CPU time.\n"
"\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" " --osc-midi-bidule <path>\n"
" Set MIDI to be sent via OSC formatted for Plogue Bidule.\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" " The path argument is the path of the Plogue OSC MIDI device.\n"
@ -971,21 +962,6 @@ bool ged_is_draw_dirty(Ged *a) {
return a->is_draw_dirty || a->needs_remarking; 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) { void ged_set_midi_mode(Ged *a, Midi_mode const *midi_mode) {
a->midi_mode = midi_mode; a->midi_mode = midi_mode;
} }
@ -1012,7 +988,7 @@ send_midi_chan_msg(Oosc_dev *oosc_dev, Midi_mode const *midi_mode,
break; break;
case Midi_mode_type_osc_bidule: { case Midi_mode_type_osc_bidule: {
if (!oosc_dev) if (!oosc_dev)
break; // not sure if needed break;
oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path, oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path,
(int[]){type << 4 | chan, byte1, byte2}, 3); (int[]){type << 4 | chan, byte1, byte2}, 3);
break; break;
@ -1232,6 +1208,28 @@ do_note_ons:
} }
} }
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; } static double ms_to_sec(double ms) { return ms / 1000.0; }
double ged_secs_to_deadline(Ged const *a) { double ged_secs_to_deadline(Ged const *a) {
@ -1950,6 +1948,9 @@ enum {
Autofit_menu_id, Autofit_menu_id,
Confirm_new_file_menu_id, Confirm_new_file_menu_id,
Cosmetics_menu_id, Cosmetics_menu_id,
Osc_menu_id,
Osc_output_address_form_id,
Osc_output_port_form_id,
Set_soft_margins_form_id, Set_soft_margins_form_id,
Set_fancy_grid_dots_menu_id, Set_fancy_grid_dots_menu_id,
Set_fancy_grid_rulers_menu_id, Set_fancy_grid_rulers_menu_id,
@ -1981,6 +1982,7 @@ enum {
Main_menu_autofit_grid, Main_menu_autofit_grid,
Main_menu_about, Main_menu_about,
Main_menu_cosmetics, Main_menu_cosmetics,
Main_menu_osc,
#ifdef FEAT_PORTMIDI #ifdef FEAT_PORTMIDI
Main_menu_choose_portmidi_output, Main_menu_choose_portmidi_output,
#endif #endif
@ -1998,10 +2000,11 @@ void push_main_menu(void) {
qmenu_add_choice(qm, Main_menu_set_grid_dims, "Set Grid Size..."); 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_choice(qm, Main_menu_autofit_grid, "Auto-fit Grid");
qmenu_add_spacer(qm); qmenu_add_spacer(qm);
qmenu_add_choice(qm, Main_menu_osc, "OSC Output...");
#ifdef FEAT_PORTMIDI #ifdef FEAT_PORTMIDI
qmenu_add_choice(qm, Main_menu_choose_portmidi_output, "MIDI Output..."); qmenu_add_choice(qm, Main_menu_choose_portmidi_output, "MIDI Output...");
qmenu_add_spacer(qm);
#endif #endif
qmenu_add_spacer(qm);
qmenu_add_choice(qm, Main_menu_cosmetics, "Appearance..."); qmenu_add_choice(qm, Main_menu_cosmetics, "Appearance...");
qmenu_add_choice(qm, Main_menu_controls, "Controls..."); qmenu_add_choice(qm, Main_menu_controls, "Controls...");
qmenu_add_choice(qm, Main_menu_opers_guide, "Operators..."); qmenu_add_choice(qm, Main_menu_opers_guide, "Operators...");
@ -2039,9 +2042,6 @@ enum {
Cosmetics_grid_dots_id, Cosmetics_grid_dots_id,
Cosmetics_grid_rulers_id, Cosmetics_grid_rulers_id,
}; };
enum {
Soft_margins_text_line_id = 1,
};
void push_cosmetics_menu(void) { void push_cosmetics_menu(void) {
Qmenu *qm = qmenu_create(Cosmetics_menu_id); Qmenu *qm = qmenu_create(Cosmetics_menu_id);
qmenu_set_title(qm, "Appearance"); qmenu_set_title(qm, "Appearance");
@ -2056,7 +2056,7 @@ void push_soft_margins_form(int init_y, int init_x) {
int snres = snprintf(buff, sizeof buff, "%dx%d", init_x, init_y); int snres = snprintf(buff, sizeof buff, "%dx%d", init_x, init_y);
char const *inistr = snres > 0 && (Usz)snres < sizeof buff ? buff : "2x1"; char const *inistr = snres > 0 && (Usz)snres < sizeof buff ? buff : "2x1";
qform_set_title(qf, "Set Margins"); 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); qform_push_to_nav(qf);
} }
void push_plainorfancy_menu(int menu_id, char const *title, void push_plainorfancy_menu(int menu_id, char const *title,
@ -2070,6 +2070,34 @@ void push_plainorfancy_menu(int menu_id, char const *title,
qmenu_push_to_nav(qm); 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) { void push_about_msg(void) {
// clang-format off // clang-format off
static char const* logo[] = { static char const* logo[] = {
@ -2445,13 +2473,19 @@ void try_send_to_gui_clipboard(Ged const *a, bool *io_use_gui_clipboard) {
typedef struct { typedef struct {
oso *portmidi_output_device; oso *portmidi_output_device;
oso *osc_output_address;
oso *osc_output_port;
int softmargin_y, softmargin_x; 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; U32 touched;
} Prefs; } Prefs;
void prefs_init(Prefs *p) { *p = (Prefs){0}; } 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 { typedef enum {
Prefs_load_ok = 0, Prefs_load_ok = 0,
@ -2459,6 +2493,9 @@ typedef enum {
char const *const confopts[] = { char const *const confopts[] = {
"portmidi_output_device", "portmidi_output_device",
"osc_output_address",
"osc_output_port",
"osc_output_enabled",
"margins", "margins",
"grid_dot_type", "grid_dot_type",
"grid_ruler_type", "grid_ruler_type",
@ -2466,16 +2503,20 @@ char const *const confopts[] = {
enum { Confoptslen = ORCA_ARRAY_COUNTOF(confopts) }; enum { Confoptslen = ORCA_ARRAY_COUNTOF(confopts) };
enum { enum {
Confopt_portmidi_output_device = 0, Confopt_portmidi_output_device = 0,
Confopt_osc_output_address,
Confopt_osc_output_port,
Confopt_osc_output_enabled,
Confopt_margins, Confopt_margins,
Confopt_grid_dot_type, Confopt_grid_dot_type,
Confopt_grid_ruler_type, Confopt_grid_ruler_type,
}; };
enum { // Use this to create a bitflag out of a Confopt_. These flags are used to
Preftouch_softmargins = 1 << 0, // indicate that a setting has been touched by the user. In other words, these
Preftouch_griddotstype = 1 << 1, // flags are used to check whether or not a particular setting should be
Preftouch_gridrulerstype = 1 << 2, // 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_plain = "plain";
char const *const prefval_fancy = "fancy"; char const *const prefval_fancy = "fancy";
@ -2492,6 +2533,25 @@ bool plainorfancy(char const *val, bool *out) {
return false; return false;
} }
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 ORCA_FORCE_NO_INLINE
Prefs_load_error prefs_load_from_conf_file(Prefs *p) { Prefs_load_error prefs_load_from_conf_file(Prefs *p) {
Ezconf_r ez; Ezconf_r ez;
@ -2500,13 +2560,34 @@ Prefs_load_error prefs_load_from_conf_file(Prefs *p) {
case Confopt_portmidi_output_device: case Confopt_portmidi_output_device:
osoput(&p->portmidi_output_device, ez.value); osoput(&p->portmidi_output_device, ez.value);
break; 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: { case Confopt_margins: {
int softmargin_y, softmargin_x; int softmargin_y, softmargin_x;
if (read_nxn_or_n(ez.value, &softmargin_x, &softmargin_y) && if (read_nxn_or_n(ez.value, &softmargin_x, &softmargin_y) &&
softmargin_y >= 0 && softmargin_x >= 0) { softmargin_y >= 0 && softmargin_x >= 0) {
p->softmargin_y = softmargin_y; p->softmargin_y = softmargin_y;
p->softmargin_x = softmargin_x; p->softmargin_x = softmargin_x;
p->touched |= Preftouch_softmargins; p->touched |= TOUCHFLAG(Confopt_margins);
} }
break; break;
} }
@ -2514,7 +2595,7 @@ Prefs_load_error prefs_load_from_conf_file(Prefs *p) {
bool fancy; bool fancy;
if (plainorfancy(ez.value, &fancy)) { if (plainorfancy(ez.value, &fancy)) {
p->fancy_grid_dots = fancy; p->fancy_grid_dots = fancy;
p->touched |= Preftouch_griddotstype; p->touched |= TOUCHFLAG(Confopt_grid_dot_type);
} }
break; break;
} }
@ -2522,7 +2603,7 @@ Prefs_load_error prefs_load_from_conf_file(Prefs *p) {
bool fancy; bool fancy;
if (plainorfancy(ez.value, &fancy)) { if (plainorfancy(ez.value, &fancy)) {
p->fancy_grid_rulers = fancy; p->fancy_grid_rulers = fancy;
p->touched |= Preftouch_gridrulerstype; p->touched |= TOUCHFLAG(Confopt_grid_ruler_type);
} }
break; break;
} }
@ -2548,13 +2629,14 @@ void print_loading_message(char const *s) {
typedef struct { typedef struct {
Ged ged; Ged ged;
oso *file_name; oso *file_name;
oso *osc_hostname, *osc_port; oso *osc_address, *osc_port;
int undo_history_limit; int undo_history_limit;
int softmargin_y, softmargin_x; int softmargin_y, softmargin_x;
int hardmargin_y, hardmargin_x; int hardmargin_y, hardmargin_x;
U32 prefs_touched; U32 prefs_touched;
bool use_gui_cboard; bool use_gui_cboard;
bool strict_timing; bool strict_timing;
bool osc_output_enabled;
bool fancy_grid_dots; bool fancy_grid_dots;
bool fancy_grid_rulers; bool fancy_grid_rulers;
Midi_mode midi_mode; Midi_mode midi_mode;
@ -2586,16 +2668,38 @@ void tui_save_prefs(Tui *t) {
} }
#endif #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); 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], ezconf_w_addopt(&ez, confopts[Confopt_grid_dot_type],
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], ezconf_w_addopt(&ez, confopts[Confopt_grid_ruler_type],
Confopt_grid_ruler_type); Confopt_grid_ruler_type);
while (ezconf_w_step(&ez)) { while (ezconf_w_step(&ez)) {
switch (ez.optid) { 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 #ifdef FEAT_PORTMIDI
case Confopt_portmidi_output_device: case Confopt_portmidi_output_device:
fputs(osoc(midi_output_device_name), ez.file); fputs(osoc(midi_output_device_name), ez.file);
@ -2674,6 +2778,37 @@ void plainorfancy_menu_was_picked(Tui *t, int picked_id, bool *p_is_fancy,
t->ged.is_draw_dirty = true; 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 // main
// //
@ -2683,13 +2818,12 @@ enum {
Argopt_hardmargins, Argopt_hardmargins,
Argopt_undo_limit, Argopt_undo_limit,
Argopt_init_grid_size, Argopt_init_grid_size,
Argopt_osc_server,
Argopt_osc_port,
Argopt_osc_midi_bidule, Argopt_osc_midi_bidule,
Argopt_strict_timing, Argopt_strict_timing,
Argopt_bpm, Argopt_bpm,
Argopt_seed, Argopt_seed,
Argopt_portmidi_deprecated, Argopt_portmidi_deprecated,
Argopt_osc_deprecated,
}; };
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -2699,8 +2833,6 @@ int main(int argc, char **argv) {
{"undo-limit", required_argument, 0, Argopt_undo_limit}, {"undo-limit", required_argument, 0, Argopt_undo_limit},
{"initial-size", required_argument, 0, Argopt_init_grid_size}, {"initial-size", required_argument, 0, Argopt_init_grid_size},
{"help", no_argument, 0, 'h'}, {"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}, {"osc-midi-bidule", required_argument, 0, Argopt_osc_midi_bidule},
{"strict-timing", no_argument, 0, Argopt_strict_timing}, {"strict-timing", no_argument, 0, Argopt_strict_timing},
{"bpm", required_argument, 0, Argopt_bpm}, {"bpm", required_argument, 0, Argopt_bpm},
@ -2708,6 +2840,8 @@ int main(int argc, char **argv) {
{"portmidi-list-devices", no_argument, 0, Argopt_portmidi_deprecated}, {"portmidi-list-devices", no_argument, 0, Argopt_portmidi_deprecated},
{"portmidi-output-device", required_argument, 0, {"portmidi-output-device", required_argument, 0,
Argopt_portmidi_deprecated}, Argopt_portmidi_deprecated},
{"osc-server", required_argument, 0, Argopt_osc_deprecated},
{"osc-port", required_argument, 0, Argopt_osc_deprecated},
{NULL, 0, NULL, 0}}; {NULL, 0, NULL, 0}};
int init_bpm = 120; int init_bpm = 120;
int init_seed = 1; int init_seed = 1;
@ -2815,12 +2949,6 @@ int main(int argc, char **argv) {
} }
break; 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: case Argopt_osc_midi_bidule:
midi_mode_deinit(&t.midi_mode); midi_mode_deinit(&t.midi_mode);
midi_mode_init_osc_bidule(&t.midi_mode, optarg); midi_mode_init_osc_bidule(&t.midi_mode, optarg);
@ -2828,7 +2956,7 @@ int main(int argc, char **argv) {
case Argopt_strict_timing: case Argopt_strict_timing:
t.strict_timing = true; t.strict_timing = true;
break; break;
case Argopt_portmidi_deprecated: { case Argopt_portmidi_deprecated:
fprintf(stderr, fprintf(stderr,
"Option \"--%s\" has been removed.\nInstead, choose " "Option \"--%s\" has been removed.\nInstead, choose "
"your MIDI output device from within the ORCA menu.\n" "your MIDI output device from within the ORCA menu.\n"
@ -2837,7 +2965,13 @@ int main(int argc, char **argv) {
tui_options[longindex].name); tui_options[longindex].name);
exit(1); exit(1);
break; 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;
} }
} }
@ -2852,30 +2986,6 @@ int main(int argc, char **argv) {
qnav_init(); qnav_init();
ged_init(&t.ged, (Usz)t.undo_history_limit, (Usz)init_bpm, (Usz)init_seed); 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)) { if (osolen(t.file_name)) {
Field_load_error fle = field_load_file(osoc(t.file_name), &t.ged.field); Field_load_error fle = field_load_file(osoc(t.file_name), &t.ged.field);
if (fle != Field_load_error_ok) { if (fle != Field_load_error_ok) {
@ -2953,14 +3063,27 @@ int main(int argc, char **argv) {
Prefs_load_error prefserr = prefs_load_from_conf_file(&prefs); Prefs_load_error prefserr = prefs_load_from_conf_file(&prefs);
if (prefserr == Prefs_load_ok) { if (prefserr == Prefs_load_ok) {
t.prefs_touched |= prefs.touched; 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_y = prefs.softmargin_y;
t.softmargin_x = prefs.softmargin_x; 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; 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; t.fancy_grid_rulers = prefs.fancy_grid_rulers;
} }
#ifdef FEAT_PORTMIDI #ifdef FEAT_PORTMIDI
@ -2988,6 +3111,8 @@ int main(int argc, char **argv) {
} }
prefs_deinit(&prefs); prefs_deinit(&prefs);
tui_restart_osc_udp_if_enabled(&t);
WINDOW *cont_window = NULL; WINDOW *cont_window = NULL;
int key = KEY_RESIZE; int key = KEY_RESIZE;
@ -3248,6 +3373,9 @@ int main(int argc, char **argv) {
case Main_menu_cosmetics: case Main_menu_cosmetics:
push_cosmetics_menu(); push_cosmetics_menu();
break; break;
case Main_menu_osc:
push_osc_menu(ged_is_using_osc_udp(&t.ged));
break;
case Main_menu_controls: case Main_menu_controls:
push_controls_msg(); push_controls_msg();
break; break;
@ -3361,12 +3489,36 @@ int main(int argc, char **argv) {
break; break;
case Set_fancy_grid_dots_menu_id: case Set_fancy_grid_dots_menu_id:
plainorfancy_menu_was_picked(&t, act.picked.id, &t.fancy_grid_dots, plainorfancy_menu_was_picked(&t, act.picked.id, &t.fancy_grid_dots,
Preftouch_griddotstype); TOUCHFLAG(Confopt_grid_dot_type));
break; break;
case Set_fancy_grid_rulers_menu_id: case Set_fancy_grid_rulers_menu_id:
plainorfancy_menu_was_picked(&t, act.picked.id, plainorfancy_menu_was_picked(&t, act.picked.id,
&t.fancy_grid_rulers, &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; break;
#ifdef FEAT_PORTMIDI #ifdef FEAT_PORTMIDI
case Portmidi_output_device_menu_id: { case Portmidi_output_device_menu_id: {
@ -3452,6 +3604,35 @@ int main(int argc, char **argv) {
osofree(tmpstr); osofree(tmpstr);
break; 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: { case Set_grid_dims_form_id: {
oso *tmpstr = get_nonempty_singular_form_text(qf); oso *tmpstr = get_nonempty_singular_form_text(qf);
if (!tmpstr) if (!tmpstr)
@ -3485,7 +3666,7 @@ int main(int argc, char **argv) {
if (read_nxn_or_n(osoc(tmpstr), &newx, &newy) && newy >= 0 && if (read_nxn_or_n(osoc(tmpstr), &newx, &newy) && newy >= 0 &&
newx >= 0 && newx >= 0 &&
(newy != t.softmargin_y || newx != t.softmargin_x)) { (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_y = newy;
t.softmargin_x = newx; t.softmargin_x = newx;
ungetch(KEY_RESIZE); // kinda lame but whatever ungetch(KEY_RESIZE); // kinda lame but whatever
@ -3828,7 +4009,7 @@ quit:
endwin(); endwin();
ged_deinit(&t.ged); ged_deinit(&t.ged);
osofree(t.file_name); osofree(t.file_name);
osofree(t.osc_hostname); osofree(t.osc_address);
osofree(t.osc_port); osofree(t.osc_port);
midi_mode_deinit(&t.midi_mode); midi_mode_deinit(&t.midi_mode);
#ifdef FEAT_PORTMIDI #ifdef FEAT_PORTMIDI
@ -3837,3 +4018,5 @@ quit:
#endif #endif
return 0; return 0;
} }
#undef TOUCHFLAG

Loading…
Cancel
Save