|
@ -13,6 +13,10 @@ |
|
|
#include "sokol_time.h" |
|
|
#include "sokol_time.h" |
|
|
#undef SOKOL_IMPL |
|
|
#undef SOKOL_IMPL |
|
|
|
|
|
|
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
#include <portmidi.h> |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
#define TIME_DEBUG 0 |
|
|
#define TIME_DEBUG 0 |
|
|
#if TIME_DEBUG |
|
|
#if TIME_DEBUG |
|
|
static int spin_track_timeout = 0; |
|
|
static int spin_track_timeout = 0; |
|
@ -21,34 +25,46 @@ static int spin_track_timeout = 0; |
|
|
static void usage(void) { |
|
|
static void usage(void) { |
|
|
// clang-format off
|
|
|
// clang-format off
|
|
|
fprintf(stderr, |
|
|
fprintf(stderr, |
|
|
"Usage: orca [options] [file]\n\n" |
|
|
"Usage: orca [options] [file]\n\n" |
|
|
"General options:\n" |
|
|
"General options:\n" |
|
|
" --margins <number> Set cosmetic margins.\n" |
|
|
" --margins <number> Set cosmetic margins.\n" |
|
|
" Default: 2\n" |
|
|
" Default: 2\n" |
|
|
" --undo-limit <number> Set the maximum number of undo steps.\n" |
|
|
" --undo-limit <number> Set the maximum number of undo steps.\n" |
|
|
" If you plan to work with large files,\n" |
|
|
" If you plan to work with large files,\n" |
|
|
" set this to a low number.\n" |
|
|
" set this to a low number.\n" |
|
|
" Default: 100\n" |
|
|
" Default: 100\n" |
|
|
" -h or --help Print this message and exit.\n" |
|
|
" -h or --help Print this message and exit.\n" |
|
|
"\n" |
|
|
"\n" |
|
|
"OSC/MIDI options:\n" |
|
|
"OSC/MIDI options:\n" |
|
|
" --osc-server <address>\n" |
|
|
" --strict-timing\n" |
|
|
" Hostname or IP address to send OSC messages to.\n" |
|
|
" Reduce the timing jitter of outgoing MIDI and OSC messages.\n" |
|
|
" Default: loopback (this machine)\n" |
|
|
" Uses more CPU time.\n" |
|
|
"\n" |
|
|
"\n" |
|
|
" --osc-port <number or service name>\n" |
|
|
" --osc-server <address>\n" |
|
|
" UDP port (or service name) to send OSC messages to.\n" |
|
|
" Hostname or IP address to send OSC messages to.\n" |
|
|
" This option must be set for OSC output to be enabled.\n" |
|
|
" Default: loopback (this machine)\n" |
|
|
" Default: none\n" |
|
|
"\n" |
|
|
"\n" |
|
|
" --osc-port <number or service name>\n" |
|
|
" --osc-midi-bidule <path>\n" |
|
|
" UDP port (or service name) to send OSC messages to.\n" |
|
|
" Set MIDI to be sent via OSC formatted for Plogue Bidule.\n" |
|
|
" This option must be set for OSC output to be enabled.\n" |
|
|
" The path argument is the path of the Plogue OSC MIDI device.\n" |
|
|
" Default: none\n" |
|
|
" Example: /OSC_MIDI_0/MIDI\n" |
|
|
"\n" |
|
|
"\n" |
|
|
" --osc-midi-bidule <path>\n" |
|
|
" --strict-timing\n" |
|
|
" Set MIDI to be sent via OSC formatted for Plogue Bidule.\n" |
|
|
" Reduce the timing jitter of outgoing MIDI and OSC messages.\n" |
|
|
" The path argument is the path of the Plogue OSC MIDI device.\n" |
|
|
" Uses more CPU time.\n" |
|
|
" Example: /OSC_MIDI_0/MIDI\n" |
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
"\n" |
|
|
|
|
|
" --portmidi-list-devices\n" |
|
|
|
|
|
" List the MIDI output devices available through PortMIDI,\n" |
|
|
|
|
|
" along with each associated device ID number, and then exit.\n" |
|
|
|
|
|
" Do this to figure out which ID to use with\n" |
|
|
|
|
|
" --portmidi-output-device\n" |
|
|
|
|
|
"\n" |
|
|
|
|
|
" --portmidi-output-device <number>\n" |
|
|
|
|
|
" Set MIDI to be sent via PortMIDI on a specified device ID.\n" |
|
|
|
|
|
" Example: 1\n" |
|
|
|
|
|
#endif |
|
|
); |
|
|
); |
|
|
// clang-format on
|
|
|
// clang-format on
|
|
|
} |
|
|
} |
|
@ -633,6 +649,9 @@ bool ged_resize_grid_snap_ruler(Field* field, Markmap_reusable* markmap, |
|
|
typedef enum { |
|
|
typedef enum { |
|
|
Midi_mode_type_null, |
|
|
Midi_mode_type_null, |
|
|
Midi_mode_type_osc_bidule, |
|
|
Midi_mode_type_osc_bidule, |
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
Midi_mode_type_portmidi, |
|
|
|
|
|
#endif |
|
|
} Midi_mode_type; |
|
|
} Midi_mode_type; |
|
|
|
|
|
|
|
|
typedef struct { |
|
|
typedef struct { |
|
@ -644,12 +663,22 @@ typedef struct { |
|
|
char const* path; |
|
|
char const* path; |
|
|
} Midi_mode_osc_bidule; |
|
|
} Midi_mode_osc_bidule; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
typedef struct { |
|
|
|
|
|
Midi_mode_type type; |
|
|
|
|
|
PmDeviceID device_id; |
|
|
|
|
|
} Midi_mode_portmidi; |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
typedef union { |
|
|
typedef union { |
|
|
Midi_mode_any any; |
|
|
Midi_mode_any any; |
|
|
Midi_mode_osc_bidule osc_bidule; |
|
|
Midi_mode_osc_bidule osc_bidule; |
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
Midi_mode_portmidi portmidi; |
|
|
|
|
|
#endif |
|
|
} Midi_mode; |
|
|
} Midi_mode; |
|
|
|
|
|
|
|
|
void midi_mode_init(Midi_mode* mm) { mm->any.type = Midi_mode_type_null; } |
|
|
void midi_mode_init_null(Midi_mode* mm) { mm->any.type = Midi_mode_type_null; } |
|
|
void midi_mode_set_osc_bidule(Midi_mode* mm, char const* path) { |
|
|
void midi_mode_set_osc_bidule(Midi_mode* mm, char const* path) { |
|
|
mm->osc_bidule.type = Midi_mode_type_osc_bidule; |
|
|
mm->osc_bidule.type = Midi_mode_type_osc_bidule; |
|
|
mm->osc_bidule.path = path; |
|
|
mm->osc_bidule.path = path; |
|
@ -793,6 +822,10 @@ void send_midi_note_offs(Oosc_dev* oosc_dev, Midi_mode const* midi_mode, |
|
|
oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path, ints, |
|
|
oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path, ints, |
|
|
ORCA_ARRAY_COUNTOF(ints)); |
|
|
ORCA_ARRAY_COUNTOF(ints)); |
|
|
} break; |
|
|
} break; |
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
case Midi_mode_type_portmidi: { |
|
|
|
|
|
} break; |
|
|
|
|
|
#endif |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -904,6 +937,10 @@ void send_output_events(Oosc_dev* oosc_dev, Midi_mode const* midi_mode, Usz bpm, |
|
|
oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path, ints, |
|
|
oosc_send_int32s(oosc_dev, midi_mode->osc_bidule.path, ints, |
|
|
ORCA_ARRAY_COUNTOF(ints)); |
|
|
ORCA_ARRAY_COUNTOF(ints)); |
|
|
} break; |
|
|
} break; |
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
case Midi_mode_type_portmidi: { |
|
|
|
|
|
} break; |
|
|
|
|
|
#endif |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -1720,6 +1757,9 @@ enum { |
|
|
Argopt_osc_port, |
|
|
Argopt_osc_port, |
|
|
Argopt_osc_midi_bidule, |
|
|
Argopt_osc_midi_bidule, |
|
|
Argopt_strict_timing, |
|
|
Argopt_strict_timing, |
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
Argopt_portmidi_list_devices, |
|
|
|
|
|
#endif |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
int main(int argc, char** argv) { |
|
|
int main(int argc, char** argv) { |
|
@ -1731,6 +1771,9 @@ int main(int argc, char** argv) { |
|
|
{"osc-port", required_argument, 0, Argopt_osc_port}, |
|
|
{"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}, |
|
|
|
|
|
#ifdef FEAT_PORTMIDI |
|
|
|
|
|
{"portmidi-list-devices", no_argument, 0, Argopt_portmidi_list_devices}, |
|
|
|
|
|
#endif |
|
|
{NULL, 0, NULL, 0}}; |
|
|
{NULL, 0, NULL, 0}}; |
|
|
char* input_file = NULL; |
|
|
char* input_file = NULL; |
|
|
int margin_thickness = 2; |
|
|
int margin_thickness = 2; |
|
@ -1739,7 +1782,7 @@ int main(int argc, char** argv) { |
|
|
char const* osc_port = NULL; |
|
|
char const* osc_port = NULL; |
|
|
bool strict_timing = false; |
|
|
bool strict_timing = false; |
|
|
Midi_mode midi_mode; |
|
|
Midi_mode midi_mode; |
|
|
midi_mode_init(&midi_mode); |
|
|
midi_mode_init_null(&midi_mode); |
|
|
for (;;) { |
|
|
for (;;) { |
|
|
int c = getopt_long(argc, argv, "h", tui_options, NULL); |
|
|
int c = getopt_long(argc, argv, "h", tui_options, NULL); |
|
|
if (c == -1) |
|
|
if (c == -1) |
|
@ -1748,6 +1791,9 @@ int main(int argc, char** argv) { |
|
|
case 'h': |
|
|
case 'h': |
|
|
usage(); |
|
|
usage(); |
|
|
return 0; |
|
|
return 0; |
|
|
|
|
|
case '?': |
|
|
|
|
|
usage(); |
|
|
|
|
|
return 1; |
|
|
case Argopt_margins: { |
|
|
case Argopt_margins: { |
|
|
margin_thickness = atoi(optarg); |
|
|
margin_thickness = atoi(optarg); |
|
|
if (margin_thickness < 0 || |
|
|
if (margin_thickness < 0 || |
|
@ -1782,9 +1828,25 @@ int main(int argc, char** argv) { |
|
|
case Argopt_strict_timing: { |
|
|
case Argopt_strict_timing: { |
|
|
strict_timing = true; |
|
|
strict_timing = true; |
|
|
} break; |
|
|
} break; |
|
|
case '?': |
|
|
#ifdef FEAT_PORTMIDI |
|
|
usage(); |
|
|
case Argopt_portmidi_list_devices: { |
|
|
return 1; |
|
|
Pm_Initialize(); |
|
|
|
|
|
int num = Pm_CountDevices(); |
|
|
|
|
|
int output_devices = 0; |
|
|
|
|
|
for (int i = 0; i < num; ++i) { |
|
|
|
|
|
PmDeviceInfo const* info = Pm_GetDeviceInfo(i); |
|
|
|
|
|
if (!info || !info->output) |
|
|
|
|
|
continue; |
|
|
|
|
|
printf("ID: %-4d Name: %s\n", i, info->name); |
|
|
|
|
|
++output_devices; |
|
|
|
|
|
} |
|
|
|
|
|
if (output_devices == 0) { |
|
|
|
|
|
printf("No PortMIDI output devices detected.\n"); |
|
|
|
|
|
} |
|
|
|
|
|
Pm_Terminate(); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
#endif |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|