ref: af8178e8f65b48bf5065175e16d12ef1c3bfe962
parent: 8c20e0eb8b38aa0bdcb50d9af2e9a6839d9f143c
author: cancel <cancel@cancel.fm>
date: Sat Jan 4 23:45:03 EST 2020
Add start of PortMidi device choosing (WIP) Does not yet let you actually pick the device, only list.
--- a/term_util.c
+++ b/term_util.c
@@ -213,6 +213,53 @@
return qm;
}
+void qmsg_printf_push(char const* title, char const* fmt, ...) {
+ int titlewidth = title ? (int)strlen(title) : 0;
+ va_list ap;
+ va_start(ap, fmt);
+ int msgbytes = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+ char* buffer = malloc((Usz)msgbytes + 1);
+ if (!buffer)
+ exit(1);
+ va_start(ap, fmt);
+ vsnprintf(buffer, (Usz)msgbytes + 1, fmt, ap);
+ va_end(ap);
+ int lines = 1;
+ int curlinewidth = 0;
+ int maxlinewidth = 0;
+ for (int i = 0; i < msgbytes; i++) {
+ if (buffer[i] == '\n') {
+ buffer[i] = '\0'; // This is terrifying :)
+ lines++;
+ if (curlinewidth > maxlinewidth)
+ maxlinewidth = curlinewidth;
+ curlinewidth = 0;
+ } else {
+ curlinewidth++;
+ }
+ }
+ if (curlinewidth > maxlinewidth)
+ maxlinewidth = curlinewidth;
+ int width = titlewidth > maxlinewidth ? titlewidth + 1 : maxlinewidth + 1;
+ Qmsg* msg = qmsg_push(lines, width); // no wrapping yet, no real wcwidth, etc
+ WINDOW* msgw = qmsg_window(msg);
+ int i = 0;
+ int offset = 0;
+ for (;;) {
+ if (offset == msgbytes + 1)
+ break;
+ int numbytes = (int)strlen(buffer + offset);
+ wmove(msgw, i, 1);
+ waddstr(msgw, buffer + offset);
+ offset += numbytes + 1;
+ i++;
+ }
+ free(buffer);
+ if (title)
+ qmsg_set_title(msg, title);
+}
+
bool qmsg_drive(Qmsg* qm, int key) {
(void)qm;
switch (key) {
@@ -236,6 +283,7 @@
qm->id = id;
return qm;
}
+void qmenu_destroy(Qmenu* qm) { qmenu_free(qm); }
int qmenu_id(Qmenu const* qm) { return qm->id; }
void qmenu_set_title(Qmenu* qm, char const* title) {
qblock_set_title(&qm->qblock, title);
--- a/term_util.h
+++ b/term_util.h
@@ -119,10 +119,18 @@
Qmsg* qmsg_push(int height, int width);
WINDOW* qmsg_window(Qmsg* qm);
void qmsg_set_title(Qmsg* qm, char const* title);
+#ifdef __GNUC__
+__attribute__((format(printf, 2, 3)))
+#endif
+void qmsg_printf_push(char const* title, char const* fmt, ...);
bool qmsg_drive(Qmsg* qm, int key);
Qmsg* qmsg_of(Qblock* qb);
Qmenu* qmenu_create(int id);
+// Useful if menu creation needs to be aborted part-way. Otherwise, no need to
+// call -- pushing the qmenu to the qnav stack transfers ownership. (Still
+// working on this design, not sure yet.)
+void qmenu_destroy(Qmenu* qm);
int qmenu_id(Qmenu const* qm);
void qmenu_set_title(Qmenu* qm, char const* title);
void qmenu_add_choice(Qmenu* qm, char const* text, int id);
--- a/tui_main.c
+++ b/tui_main.c
@@ -1859,6 +1859,9 @@
Set_grid_dims_form_id,
Autofit_menu_id,
Confirm_new_file_menu_id,
+#ifdef FEAT_PORTMIDI
+ Portmidi_output_device_menu_id,
+#endif
};
enum {
Open_name_text_line_id = 1,
@@ -1892,6 +1895,9 @@
Main_menu_set_grid_dims,
Main_menu_autofit_grid,
Main_menu_about,
+#ifdef FEAT_PORTMIDI
+ Main_menu_choose_portmidi_output,
+#endif
};
void push_main_menu(void) {
@@ -1906,6 +1912,10 @@
qmenu_add_choice(qm, "Set Grid Size...", Main_menu_set_grid_dims);
qmenu_add_choice(qm, "Auto-fit Grid", Main_menu_autofit_grid);
qmenu_add_spacer(qm);
+#ifdef FEAT_PORTMIDI
+ qmenu_add_choice(qm, "PortMIDI Output", Main_menu_choose_portmidi_output);
+ qmenu_add_spacer(qm);
+#endif
qmenu_add_choice(qm, "Controls...", Main_menu_controls);
qmenu_add_choice(qm, "Operators...", Main_menu_opers_guide);
qmenu_add_choice(qm, "About...", Main_menu_about);
@@ -2162,6 +2172,38 @@
qform_push_to_nav(qf);
}
+#ifdef FEAT_PORTMIDI
+void push_portmidi_output_device_menu(void) {
+ Qmenu* qm = qmenu_create(Portmidi_output_device_menu_id);
+ qmenu_set_title(qm, "PortMidi Device Selection");
+ PmError e = portmidi_init_if_necessary();
+ if (e) {
+ qmenu_destroy(qm);
+ qmsg_printf_push("PortMidi Error",
+ "PortMidi error during initialization:\n%s",
+ Pm_GetErrorText(e));
+ return;
+ }
+ 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;
+ qmenu_add_choice(qm, info->name, i);
+ // printf("ID: %-4d Name: %s\n", i, info->name);
+ ++output_devices;
+ }
+ if (output_devices == 0) {
+ qmenu_destroy(qm);
+ qmsg_printf_push("No PortMidi Devices",
+ "No PortMidi output devices found.");
+ return;
+ }
+ qmenu_push_to_nav(qm);
+}
+#endif
+
//
// Misc utils
//
@@ -2849,6 +2891,11 @@
case Main_menu_autofit_grid:
push_autofit_menu();
break;
+#ifdef FEAT_PORTMIDI
+ case Main_menu_choose_portmidi_output:
+ push_portmidi_output_device_menu();
+ break;
+#endif
}
} else if (qmenu_id(qm) == Autofit_menu_id) {
Usz new_field_h, new_field_w;