diff --git a/bank.h b/bank.h index 7fa7821..d981745 100644 --- a/bank.h +++ b/bank.h @@ -4,6 +4,7 @@ typedef enum { Oevent_type_midi, Oevent_type_osc_ints, + Oevent_type_udp_string, } Oevent_types; typedef struct { @@ -28,10 +29,19 @@ typedef struct { U8 numbers[Oevent_osc_int_count]; } Oevent_osc_ints; +enum { Oevent_udp_string_count = 16 }; + +typedef struct { + U8 oevent_type; + U8 count; + char chars[Oevent_udp_string_count]; +} Oevent_udp_string; + typedef union { Oevent_any any; Oevent_midi midi; Oevent_osc_ints osc_ints; + Oevent_udp_string udp_string; } Oevent; typedef struct { diff --git a/osc_out.c b/osc_out.c index 9a93d6f..9ae44f4 100644 --- a/osc_out.c +++ b/osc_out.c @@ -91,7 +91,7 @@ void oosc_dev_destroy(Oosc_dev* dev) { free(dev); } -static 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, dev->chosen->ai_addrlen); if (res < 0) { diff --git a/osc_out.h b/osc_out.h index 552915c..5c2f3ca 100644 --- a/osc_out.h +++ b/osc_out.h @@ -12,9 +12,20 @@ Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev** out_ptr, char const* dest_addr, char const* dest_port); void oosc_dev_destroy(Oosc_dev* dev); + +// Send a raw UDP datagram. +void oosc_send_datagram(Oosc_dev* dev, char const* data, Usz size); + +// Send a list/array of 32-bit integers in OSC format to the specified "osc +// address" (a path like /foo) as a UDP datagram. void oosc_send_int32s(Oosc_dev* dev, char const* osc_address, I32 const* vals, Usz count); +// Susnote is for handling MIDI note sustains -- each MIDI on event should be +// matched with a MIDI note-off event. The duration/sustain length of a MIDI +// note is specified when it is first triggered, so the orca VM itself is not +// responsible for sending the note-off event. We keep a list of currently 'on' +// notes so that they can have a matching 'off' sent at the correct time. typedef struct { float remaining; U16 chan_note; diff --git a/sim.c b/sim.c index cb2e9ff..371ff5f 100644 --- a/sim.c +++ b/sim.c @@ -224,6 +224,7 @@ Usz usz_clamp(Usz val, Usz min, Usz max) { _('#', comment) \ _('*', bang) \ _(':', midi) \ + _(';', udp) \ _('=', osc) #define ALPHA_OPERATORS(_) \ @@ -369,6 +370,32 @@ BEGIN_OPERATOR(midi) oe->bar_divisor = (U8)(index_of(length_g) + 1); END_OPERATOR +BEGIN_OPERATOR(udp) + Usz n = width - x - 1; + if (n > 16) + n = 16; + Glyph const* restrict gline = gbuffer + y * width + x + 1; + Mark* restrict mline = mbuffer + y * width + x + 1; + Glyph cpy[Oevent_udp_string_count]; + Usz i; + for (i = 0; i < n; ++i) { + Glyph g = gline[i]; + if (g == '.') + break; + cpy[i] = g; + mline[i] |= Mark_flag_lock; + } + n = i; + STOP_IF_NOT_BANGED; + Oevent_udp_string* oe = + (Oevent_udp_string*)oevent_list_alloc_item(extra_params->oevent_list); + oe->oevent_type = (U8)Oevent_type_udp_string; + oe->count = (U8)n; + for (i = 0; i < n; ++i) { + oe->chars[i] = cpy[i]; + } +END_OPERATOR + BEGIN_OPERATOR(osc) PORT(0, 1, IN | PARAM); PORT(0, 2, IN | PARAM); diff --git a/tui_main.c b/tui_main.c index 3a98939..8d1d445 100644 --- a/tui_main.c +++ b/tui_main.c @@ -102,6 +102,7 @@ static Glyph_class glyph_class_of(Glyph glyph) { return Glyph_class_movement; case '!': case ':': + case ';': case '=': return Glyph_class_lowercase; case '*': @@ -587,6 +588,13 @@ void draw_oevent_list(WINDOW* win, Oevent_list const* oevent_list) { wprintw(win, " %d", eo->numbers[i]); } } break; + case Oevent_type_udp_string: { + Oevent_udp_string const* eo = &ev->udp_string; + wprintw(win, "UDP\tcount %d\t", (int)eo->count); + for (Usz j = 0; j < (Usz)eo->count; ++j) { + waddch(win, (chtype)eo->chars[j]); + } + } break; } } } @@ -968,6 +976,12 @@ void send_output_events(Oosc_dev* oosc_dev, Midi_mode const* midi_mode, Usz bpm, } oosc_send_int32s(oosc_dev, path_buff, ints, nnum); } break; + case Oevent_type_udp_string: { + if (!oosc_dev) + continue; + Oevent_udp_string const* eo = &e->udp_string; + oosc_send_datagram(oosc_dev, eo->chars, eo->count); + } break; } }