18 #include <linux/joystick.h>
54 static LiVESSList *omc_node_list;
55 static boolean omc_macros_inited =
FALSE;
57 static void init_omc_macros(
void);
61 if (!omc_macros_inited) {
63 omc_macros_inited =
TRUE;
67 if (idx >=
N_OMC_MACROS || !omc_macros[idx].msg)
return NULL;
69 return &omc_macros[idx];
76 LiVESSList *slist = omc_node_list;
84 return (omc_node_list != NULL);
89 if (mnode->
nvars > 0) {
105 static void remove_all_nodes(
boolean every,
omclearn_w *omclw) {
107 LiVESSList *slist_last = NULL, *slist_next;
108 LiVESSList *slist = omc_node_list;
111 slist_next = slist->next;
116 if (slist_last) slist_last->next = slist->next;
117 else omc_node_list = slist->next;
118 omc_match_node_free(mnode);
119 }
else slist_last = slist;
131 char **array = lives_strsplit(
string,
" ", -1);
132 int res = atoi(array[1]);
133 lives_strfreev(array);
138 static int midi_msg_type(
const char *
string) {
139 int type = atoi(
string);
159 static int get_nfixed(
int type,
const char *
string) {
171 type = midi_msg_type(
string);
172 return get_nfixed(type, NULL);
198 array = lives_strsplit(
string,
" ", -1);
199 res = atoi(array[nfixed - 1]);
200 lives_strfreev(array);
210 const char *get_js_filename(
void) {
215 js_fname =
"/dev/input/js";
216 js_fd = open(js_fname, O_RDONLY | O_NONBLOCK);
219 js_fname =
"/dev/input/js0";
220 js_fd = open(js_fname, O_RDONLY | O_NONBLOCK);
222 js_fname =
"/dev/js0";
223 js_fd = open(js_fname, O_RDONLY | O_NONBLOCK);
235 boolean js_open(
void) {
240 if (js_fd < 0)
return FALSE;
242 const char *tmp = get_js_filename();
256 void js_close(
void) {
264 char *js_mangle(
void) {
271 bytes = read(js_fd, &jse,
sizeof(jse));
273 if (bytes !=
sizeof(jse))
return NULL;
275 jse.type &= ~JS_EVENT_INIT;
276 if (jse.type == JS_EVENT_AXIS) {
278 if (jse.value == 0)
return NULL;
279 }
else if (jse.type == JS_EVENT_BUTTON) {
280 if (jse.value == 0)
return NULL;
306 midi_fname =
"/dev/midi";
307 midi_fd = open(midi_fname, O_RDONLY | O_NONBLOCK);
309 midi_fname =
"/dev/midi0";
310 midi_fd = open(midi_fname, O_RDONLY | O_NONBLOCK);
312 midi_fname =
"/dev/midi1";
313 midi_fd = open(midi_fname, O_RDONLY | O_NONBLOCK);
329 if (
prefs->use_alsa_midi) {
330 d_print(
_(
"Creating ALSA MIDI port(s)..."));
331 mainw->alsa_midi_dummy = -1;
334 if (snd_seq_open(&
mainw->seq_handle,
"default", SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK) < 0) {
341 snd_seq_set_client_name(
mainw->seq_handle,
"LiVES");
343 if ((
mainw->alsa_midi_port = snd_seq_create_simple_port(
mainw->seq_handle,
"LiVES",
344 SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
345 SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_PORT | SND_SEQ_PORT_TYPE_SOFTWARE)) < 0) {
346 snd_seq_close(
mainw->seq_handle);
347 mainw->seq_handle = NULL;
351 if (
prefs->alsa_midi_dummy) {
353 d_print(
_(
"dummy MIDI OUT port..."));
355 if ((
mainw->alsa_midi_dummy = snd_seq_create_simple_port(
mainw->seq_handle,
358 SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
359 SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_PORT | SND_SEQ_PORT_TYPE_SOFTWARE)) < 0) {
360 snd_seq_delete_simple_port(
mainw->seq_handle,
mainw->alsa_midi_port);
361 snd_seq_close(
mainw->seq_handle);
362 mainw->seq_handle = NULL;
374 if (midi_fd < 0)
return FALSE;
399 if (
mainw->seq_handle) {
401 snd_seq_delete_simple_port(
mainw->seq_handle,
mainw->alsa_midi_port);
402 if (
mainw->alsa_midi_dummy >= 0) snd_seq_delete_simple_port(
mainw->seq_handle,
mainw->alsa_midi_dummy);
403 snd_seq_close(
mainw->seq_handle);
404 mainw->seq_handle = NULL;
417 static int get_midi_len(
int msgtype) {
436 unsigned char midbuf[4], xbuf[4];
437 int target = 1, mtype = 0, channel;
438 boolean got_target =
FALSE;
442 struct pollfd *pfd = NULL;
445 boolean hasmore =
FALSE;
447 if (
mainw->seq_handle) {
448 if (snd_seq_event_input_pending(
mainw->seq_handle, 0) == 0) {
450 npfd = snd_seq_poll_descriptors_count(
mainw->seq_handle, POLLIN);
452 if (npfd < 1)
return NULL;
454 pfd = (
struct pollfd *)
lives_malloc(npfd *
sizeof(
struct pollfd));
457 snd_seq_poll_descriptors(
mainw->seq_handle, pfd, npfd, POLLIN);
458 }
else hasmore =
TRUE;
460 if (hasmore || poll(pfd, npfd, 0) > 0) {
462 if (snd_seq_event_input(
mainw->seq_handle, &ev) < 0) {
467 case SND_SEQ_EVENT_CONTROLLER:
471 string =
lives_strdup_printf(
"%d %d %u %d", typeNumber + ev->data.control.channel, ev->data.control.channel,
472 ev->data.control.param,
473 ev->data.control.value);
476 ev->data.control.value);
479 case SND_SEQ_EVENT_PITCHBEND:
483 string =
lives_strdup_printf(
"%d %d %d", typeNumber + ev->data.control.channel, ev->data.control.channel,
484 ev->data.control.value);
489 case SND_SEQ_EVENT_NOTEON:
494 ev->data.note.channel, ev->data.note.note,
495 ev->data.note.velocity);
498 ev->data.note.velocity);
501 case SND_SEQ_EVENT_NOTEOFF:
506 ev->data.note.channel, ev->data.note.note,
507 ev->data.note.off_velocity);
510 ev->data.note.off_velocity);
513 case SND_SEQ_EVENT_PGMCHANGE:
518 ev->data.note.channel, ev->data.control.value);
524 snd_seq_free_event(ev);
525 }
while (snd_seq_event_input_pending(
mainw->seq_handle, 0) > 0 && !
string);
531 if (midi_fd == -1)
return NULL;
533 while (tot < target) {
534 bytes = read(midi_fd, xbuf, target - tot);
537 if (--allowed < 0)
return NULL;
543 target = get_midi_len((mtype = midi_msg_type(str)));
554 if (mtype == 0)
return NULL;
556 channel = (midbuf[0] & 0x0F);
563 else if (target == 3)
string =
lives_strdup_printf(
"%u %u %u %u", midbuf[0], channel, midbuf[1], midbuf[2]);
564 else string =
lives_strdup_printf(
"%u %u %u %u %u", midbuf[0], channel, midbuf[1], midbuf[2], midbuf[3]);
568 else if (target == 3)
string =
lives_strdup_printf(
"%u %u %u", midbuf[0], midbuf[1], midbuf[2]);
569 else string =
lives_strdup_printf(
"%u %u %u %u", midbuf[0], midbuf[1], midbuf[2], midbuf[3]);
580 #endif //OMC_MIDI_IMPL
583 LIVES_INLINE char *cut_string_elems(
const char *
string,
int nelems) {
586 char *retval = lives_strdup(
string);
588 size_t slen = strlen(
string);
590 if (nelems < 0)
return retval;
592 for (i = 0; i < slen; i++) {
593 if (!strncmp((
string + i),
" ", 1)) {
604 static char *omc_learn_get_pname(
int type,
int idx) {
611 if (idx == 1)
return (
_(
"velocity"));
622 static int omc_learn_get_pvalue(
int type,
int idx,
const char *
string) {
623 char **array = lives_strsplit(
string,
" ", -1);
625 int nfixed = get_nfixed(type, NULL);
627 res = atoi(array[nfixed + idx]);
628 lives_strfreev(array);
633 static void cell1_edited_callback(LiVESCellRenderer *spinbutton,
const char *path_string,
const char *new_text,
634 livespointer user_data) {
667 switch (omacro.
ptypes[row]) {
669 vali = atoi(new_text);
670 mnode->
fvali[row] = vali;
673 vald = lives_strtod(new_text, NULL);
674 mnode->
fvald[row] = vald;
682 #if GTK_CHECK_VERSION(3, 0, 0)
683 static void rowexpand(LiVESWidget *
tv, LiVESTreeIter *iter, LiVESTreePath *path, livespointer ud) {
692 LiVESCellRenderer *renderer;
693 LiVESTreeViewColumn *column;
695 LiVESTreeIter iter1, iter2;
697 LiVESAdjustment *adj;
699 char *strval = NULL, *vname;
700 char *oldval = NULL, *
final = NULL;
706 LIVES_COL_TYPE_OBJECT);
708 if (macro.
nparams == 0)
return;
713 for (i = 0; i < macro.
nparams; i++) {
728 if ((mfrom = mnode->
map[i]) != -1) strval = (
_(
"variable"));
730 switch (macro.
ptypes[i]) {
742 vname = macro.
pname[i];
766 g_object_set(renderer,
"width-chars", 7,
"mode", GTK_CELL_RENDERER_MODE_EDITABLE,
767 "editable",
TRUE,
"xalign", 1.0, NULL);
771 lives_signal_connect(renderer, LIVES_WIDGET_EDITED_SIGNAL, LIVES_GUI_CALLBACK(cell1_edited_callback), mnode);
781 #if GTK_CHECK_VERSION(3, 0, 0)
783 LIVES_GUI_CALLBACK(rowexpand), NULL);
787 (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
788 (LiVESAttachOptions)(LIVES_EXPAND), 0, 0);
794 int mps = omc_macro.
nparams - 1;
795 int lps = mnode->
nvars - 1;
806 if (lps > mps) lps = mps;
809 for (i = mps; i >= 0; i--) {
810 if (mnode->
matchp[lps]) lps++;
814 for (i = mps; i >= 0; i--) {
815 if (lps < 0 || lps >= mnode->
nvars) {
819 else mnode->
fvald[i] = omc_macro.
vald[i];
822 if (!mnode->
matchp[lps]) mnode->
map[i] = lps;
830 static void on_omc_combo_entry_changed(LiVESCombo *combo, livespointer ptr) {
832 const char *macro_text;
833 int i, row = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo),
"row"));
834 omclearn_w *omclw = (
omclearn_w *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(combo),
"omclw");
858 if (!strcmp(macro_text, omc_macros[i].macro_text))
break;
862 omc_learn_link_params(mnode);
863 omc_macro_row_add_params(mnode, row, omclw);
867 static void cell_toggled_callback(LiVESCellRenderer *toggle,
const char *path_string, livespointer user_data) {
893 if (!strcmp(txt,
"-")) {
904 omc_learn_link_params(mnode);
908 static void cell_edited_callback(LiVESCellRenderer *spinbutton,
const char *path_string,
const char *new_text,
909 livespointer user_data) {
912 int col = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton),
"colnum"));
939 vali = atoi(new_text);
940 mnode->
offs0[row] = vali;
943 vali = atoi(new_text);
944 mnode->
offs1[row] = vali;
947 vald = lives_strtod(new_text, NULL);
948 mnode->
scale[row] = vald;
960 if (!omc_macros[i].msg)
break;
964 if (mnode->
macro != -1) {
968 lives_signal_connect_after(LIVES_WIDGET_OBJECT(combo), LIVES_WIDGET_CHANGED_SIGNAL,
969 LIVES_GUI_CALLBACK(on_omc_combo_entry_changed), mnode);
971 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo),
"row", LIVES_INT_TO_POINTER(row));
972 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(combo),
"omclw", (livespointer)omclw);
978 static char *get_chan_string(
const char *
string) {
981 int chan = js_index(
string);
984 }
else chstr = lives_strdup(
"");
990 LiVESWidget *label, *combo;
991 LiVESWidgetObject *spinadj;
993 LiVESCellRenderer *renderer;
994 LiVESTreeViewColumn *column;
996 LiVESTreeIter iter1, iter2;
998 char *strval, *strval2, *strval3, *strval4, *vname, *valstr;
999 char *oldval = NULL, *
final = NULL;
1000 char *labelt = NULL;
1009 LIVES_COL_TYPE_STRING,
1010 LIVES_COL_TYPE_STRING, LIVES_COL_TYPE_STRING, LIVES_COL_TYPE_STRING);
1015 for (
int i = 0; i < mnode->
nvars; i++) {
1034 vname = omc_learn_get_pname(type, i);
1035 val = omc_learn_get_pvalue(type, i,
string);
1042 vname = omc_learn_get_pname(-type, i);
1044 else valstr = lives_strdup(
"-");
1056 if (type < 0) type = -type;
1060 chstr = get_chan_string(
string);
1064 chstr = get_chan_string(
string);
1068 chstr = get_chan_string(
string);
1072 chstr = get_chan_string(
string);
1076 chstr = get_chan_string(
string);
1093 #if !GTK_CHECK_VERSION(3, 0, 0)
1102 (LiVESAttachOptions)(0), (LiVESAttachOptions)(0), 0, 0);
1112 renderer, LIVES_TREE_VIEW_COLUMN_TEXT,
TITLE_COLUMN, NULL);
1118 renderer, LIVES_TREE_VIEW_COLUMN_TEXT,
VALUE_COLUMN, NULL);
1128 lives_signal_connect(renderer, LIVES_WIDGET_TOGGLED_SIGNAL, LIVES_GUI_CALLBACK(cell_toggled_callback), mnode);
1132 renderer, LIVES_TREE_VIEW_COLUMN_TEXT,
RANGE_COLUMN, NULL);
1139 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(renderer),
"colnum", LIVES_UINT_TO_POINTER(
OFFS1_COLUMN));
1144 g_object_set(renderer,
"width-chars", 7,
"mode", GTK_CELL_RENDERER_MODE_EDITABLE,
1145 "editable",
TRUE,
"xalign", 1.0,
"adjustment", spinadj, NULL);
1148 lives_signal_connect(renderer, LIVES_WIDGET_EDITED_SIGNAL, LIVES_GUI_CALLBACK(cell_edited_callback), mnode);
1151 renderer, LIVES_TREE_VIEW_COLUMN_TEXT,
OFFS1_COLUMN, NULL);
1162 g_object_set(renderer,
"width-chars", 12,
"mode", GTK_CELL_RENDERER_MODE_EDITABLE,
1163 "editable",
TRUE,
"xalign", 1.0,
"adjustment", spinadj,
1167 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(renderer),
"colnum", LIVES_UINT_TO_POINTER(
SCALE_COLUMN));
1168 lives_signal_connect(renderer, LIVES_WIDGET_EDITED_SIGNAL, LIVES_GUI_CALLBACK(cell_edited_callback), mnode);
1171 renderer, LIVES_TREE_VIEW_COLUMN_TEXT,
SCALE_COLUMN, NULL);
1181 g_object_set(renderer,
"width-chars", 7,
"mode", GTK_CELL_RENDERER_MODE_EDITABLE,
1182 "editable",
TRUE,
"xalign", 1.0,
"adjustment", spinadj, NULL);
1185 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(renderer),
"colnum", LIVES_UINT_TO_POINTER(
OFFS2_COLUMN));
1186 lives_signal_connect(renderer, LIVES_WIDGET_EDITED_SIGNAL, LIVES_GUI_CALLBACK(cell_edited_callback), mnode);
1189 renderer, LIVES_TREE_VIEW_COLUMN_TEXT,
OFFS2_COLUMN, NULL);
1193 #if LIVES_TABLE_IS_GRID
1198 (LiVESAttachOptions)(LIVES_FILL | LIVES_EXPAND),
1199 (LiVESAttachOptions)(LIVES_EXPAND), 0, 0);
1201 #if GTK_CHECK_VERSION(3, 0, 0)
1203 LIVES_GUI_CALLBACK(rowexpand), NULL);
1206 combo = create_omc_macro_combo(mnode, omclw->
tbl_currow, omclw);
1209 (LiVESAttachOptions) 0, (LiVESAttachOptions)(0), 0, 0);
1216 static void killit(LiVESWidget *widget, livespointer user_data) {
1221 static void show_existing(
omclearn_w *omclw) {
1222 LiVESSList *slist = omc_node_list;
1224 int type, supertype;
1225 char **array, *srch;
1231 srch = lives_strdup(mnode->
srch);
1232 array = lives_strsplit(srch,
" ", -1);
1234 supertype = atoi(array[0]);
1235 #ifdef OMC_MIDI_IMPL
1240 type = midi_msg_type(array[1]);
1244 srch = lives_strdup(mnode->
srch);
1247 tmp = cut_string_elems(srch, 1);
1249 tmp = lives_strdup(srch + blen + 1);
1256 idx = atoi(array[1]);
1257 #ifdef OMC_MIDI_IMPL
1260 lives_strfreev(array);
1262 omc_learner_add_row(-type, idx, mnode, srch, omclw);
1265 omc_macro_row_add_params(mnode, omclw->
tbl_currow, omclw);
1267 slist = slist->next;
1272 static void clear_unmatched(LiVESButton *button, livespointer user_data) {
1281 remove_all_nodes(
FALSE, omclw);
1283 show_existing(omclw);
1287 static void del_all(LiVESButton *button, livespointer user_data) {
1296 remove_all_nodes(
TRUE, omclw);
1302 static void close_learner_dialog(LiVESButton *button, livespointer user_data) {
1308 static omclearn_w *create_omclearn_dialog(
void) {
1309 LiVESWidget *ok_button;
1310 LiVESWidget *scrolledwindow;
1311 int winsize_h, winsize_v;
1335 LIVES_RESPONSE_NONE);
1338 LIVES_GUI_CALLBACK(clear_unmatched), (livespointer)omclw);
1343 LIVES_RESPONSE_NONE);
1346 LIVES_GUI_CALLBACK(del_all), (livespointer)omclw);
1356 LIVES_GUI_CALLBACK(close_learner_dialog), NULL);
1374 static void init_omc_macros(
void) {
1380 omc_macros[i].
msg = NULL;
1382 omc_macros[i].
pname = NULL;
1391 omc_macros[
CLIP_SELECT].
msg = lives_strdup(
"/clip/foreground/select");
1408 omc_macros[
PLAY_FASTER].
msg = lives_strdup(
"/video/play/faster");
1412 omc_macros[
PLAY_SLOWER].
msg = lives_strdup(
"/video/play/slower");
1466 omc_macros[
SET_FPS_RATIO].
info_text = (
_(
"Set the framerate ratio of the foreground clip to <(float) fps__ratio>"));
1472 _(
"Switch foreground clip to the nth valid clip, and reset the frame number"));
1491 _(
"Send LIVES_OSC_NOTIFY_USER1 notification to all listeners, with variable <value>."));
1495 if (omc_macros[i].msg) {
1496 if (omc_macros[i].nparams > 0) {
1505 omc_macros[i].
pname = (
char **)
lives_malloc(omc_macros[i].nparams *
sizeof(
char *));
1636 char **array = lives_strsplit(
sig,
" ", -1);
1638 for (i = 0; i < mnode->
nvars; i++) {
1640 if (mnode->
matchi[i] != atoi(array[nfixed + i])) {
1642 lives_strfreev(array);
1648 lives_strfreev(array);
1654 LiVESSList *nlist = omc_node_list;
1655 char *srch, *cnodex;
1664 nfixed = get_nfixed(type,
sig);
1670 if (!strncmp(cnodex, srch, strlen(cnodex))) {
1673 if (match_filtered_params(cnode,
sig, nfixed)) {
1679 nlist = nlist->next;
1730 LIVES_INLINE int get_nth_elem(
const char *
string,
int idx) {
1731 char **array = lives_strsplit(
string,
" ", -1);
1732 int retval = atoi(array[idx]);
1733 lives_strfreev(array);
1738 static lives_omc_match_node_t *lives_omc_match_node_new(
int str_type,
int index,
const char *
string,
int nfixed) {
1746 if (index > -1) srch_str =
lives_strdup_printf(
"%d %d %s", str_type, index, (tmp = cut_string_elems(
string,
1747 nfixed < 0 ? -1 : nfixed)));
1748 else srch_str =
lives_strdup_printf(
"%d %s", str_type, (tmp = cut_string_elems(
string, nfixed < 0 ? -1 : nfixed)));
1751 srch_str =
lives_strdup_printf(
"%s", (tmp = cut_string_elems(
string, nfixed < 0 ? -1 : nfixed)));
1757 mnode->
srch = srch_str;
1760 if (nfixed < 0) mnode->
nvars = -(nfixed + 1);
1763 if (mnode->
nvars > 0) {
1773 for (i = 0; i < mnode->
nvars; i++) {
1775 mnode->
scale[i] = 1.;
1780 mnode->
fvald = NULL;
1789 static int *omclearn_get_values(
const char *
string,
int nfixed) {
1792 int *retvals, count = 0, nvars;
1794 slen = strlen(
string);
1800 for (i = 0; i < slen; i++) {
1801 if (!strncmp((
string + i),
" ", 1)) {
1802 if (--nfixed <= 0) {
1803 char *tmp = lives_strdup(
string + i + 1);
1804 tslen = strlen(tmp);
1805 for (j = 0; j < tslen; j++) {
1806 if (!strncmp((tmp + j),
" ", 1)) {
1808 retvals[count++] = atoi(tmp);
1814 retvals[count++] = atoi(tmp);
1828 void omclearn_match_control(
lives_omc_match_node_t *mnode,
int str_type,
int index,
const char *
string,
int nfixed,
1836 index = get_nth_elem(
string, 1);
1842 omc_learner_add_row(str_type, index, mnode,
string, omclw);
1864 int nfixed = get_nfixed(str_type,
string);
1871 mnode = omc_match_sig(
OMC_MIDI, idx,
string);
1875 mnode = lives_omc_match_node_new(
OMC_MIDI, idx,
string, nfixed);
1876 mnode->
max[0] = 127;
1878 idx = midi_index(
string);
1879 omclearn_match_control(mnode, str_type, idx,
string, nfixed, omclw);
1886 mnode = omc_match_sig(
OMC_MIDI, idx,
string);
1890 mnode = lives_omc_match_node_new(
OMC_MIDI, idx,
string, nfixed);
1891 mnode->
max[0] = 127;
1893 idx = midi_index(
string);
1894 omclearn_match_control(mnode, str_type, idx,
string, nfixed, omclw);
1902 mnode = omc_match_sig(
OMC_MIDI, idx,
string);
1906 mnode = lives_omc_match_node_new(
OMC_MIDI, idx,
string, nfixed);
1907 mnode->
max[0] = 8192;
1908 mnode->
min[0] = -8192;
1909 omclearn_match_control(mnode, str_type, idx,
string, nfixed, omclw);
1916 mnode = omc_match_sig(
OMC_MIDI, idx,
string);
1919 mnode = lives_omc_match_node_new(
OMC_MIDI, idx,
string, nfixed);
1921 mnode->
max[0] = 127;
1924 mnode->
max[1] = 127;
1927 omclearn_match_control(mnode, str_type, idx,
string, nfixed, omclw);
1936 mnode = omc_match_sig(str_type, idx,
string);
1939 mnode = lives_omc_match_node_new(str_type, idx,
string, nfixed);
1941 mnode->
min[0] = -128;
1942 mnode->
max[0] = 128;
1944 omclearn_match_control(mnode, str_type, idx,
string, nfixed, omclw);
1950 mnode = omc_match_sig(str_type, idx,
string);
1953 mnode = lives_omc_match_node_new(str_type, idx,
string, nfixed);
1954 omclearn_match_control(mnode, str_type, idx,
string, nfixed, omclw);
1980 boolean ret =
FALSE;
1981 int type = -1, idx = -1;
1984 if (!
string)
return FALSE;
1986 if (!omc_macros_inited) {
1988 omc_macros_inited =
TRUE;
1992 switch (supertype) {
1994 supertype = type = js_msg_type(
string);
1995 idx = js_index(
string);
1999 supertype = type = js_msg_type(
string);
2000 idx = js_index(
string);
2003 #ifdef OMC_MIDI_IMPL
2005 type = midi_msg_type(
string);
2012 mnode = omc_learn(
string, type, idx, omclw);
2015 omc_node_list = lives_slist_append(omc_node_list, mnode);
2028 if (oscbuf && !OSC_isBufferEmpty(oscbuf)) {
2030 && strcmp(oscbuf->buffer,
"/video/play")
2031 && strcmp(oscbuf->buffer,
"/clip/foreground/retrigger")
2032 && strcmp(oscbuf->buffer,
"/effect_key/enable")
2033 && strcmp(oscbuf->buffer,
"/effect_key/toggle")
2036 lives_osc_act(oscbuf);
2046 omclearn_w *omclw = create_omclearn_dialog();
2047 char *
string = NULL;
2049 if (!omc_macros_inited) {
2051 omc_macros_inited =
TRUE;
2055 #ifdef OMC_MIDI_IMPL
2065 show_existing(omclw);
2080 #ifdef OMC_MIDI_IMPL
2083 #ifdef TEST_OMC_LEARN
2084 string = lives_strdup(
"176 10 0 1");
2102 remove_all_nodes(
FALSE, omclw);
2117 int *vals = omclearn_get_values(
string, nfixed);
2118 int oval0 = 1, oval1 = 0;
2120 for (i = 0; i < omacro->
nparams; i++) {
2127 int ntmpls = 0, ptype, flags;
2129 weed_plant_t *filter;
2130 weed_plant_t **ptmpls;
2131 weed_plant_t *ptmpl;
2133 if (mode == -1)
return;
2138 for (k = 0; k < ntmpls; k++) {
2143 if (flags & WEED_PARAMETER_VARIABLE_SIZE) flags ^= WEED_PARAMETER_VARIABLE_SIZE;
2144 if ((ptype == WEED_PARAM_INTEGER || ptype == WEED_PARAM_FLOAT) && flags == 0 &&
2145 weed_leaf_num_elements(ptmpl, WEED_LEAF_DEFAULT) == 1) {
2147 if (ptype == WEED_PARAM_INTEGER) {
2163 if (i == 0) oval0 = oval;
2164 if (i == 1) oval1 = oval;
2169 if (i == 0) oval0 = mnode->
fvali[i];
2170 if (i == 1) oval1 = mnode->
fvali[i];
2183 int macro, nfixed = 0;
2184 int oval0 = 1, oval1 = 0;
2185 int ntmpls = 0, ptype, flags;
2191 if (idx < 0 || idx >=
N_OMC_MACROS || !omc_macros[idx].msg)
return NULL;
2194 mnode = omc_match_sig(type, idx,
string);
2196 if (!mnode)
return NULL;
2198 macro = mnode->
macro;
2203 omacro = omc_macros[macro];
2205 if (!omacro.
msg)
return NULL;
2209 OSC_resetBuffer(&obuf);
2216 for (i = 0; i < omacro.
nparams; i++) {
2218 write_fx_tag(
string, nfixed, mnode, &omacro, typetags);
2224 OSC_writeAddressAndTypes(&obuf, omacro.
msg, typetags);
2228 if (type !=
OMC_INTERNAL) vals = omclearn_get_values(
string, nfixed);
2230 for (i = 0; i < omacro.
nparams; i++) {
2236 oval0 < mainw->vpp->num_play_params) {
2240 WEED_LEAF_TEMPLATE, NULL);
2242 if ((ptype == WEED_PARAM_INTEGER || ptype == WEED_PARAM_FLOAT) &&
2243 weed_leaf_num_elements(ptmpl, WEED_LEAF_DEFAULT) == 1) {
2244 if (ptype == WEED_PARAM_INTEGER) {
2245 int omin = mnode->
min[j];
2246 int omax = mnode->
max[j];
2247 int mini = weed_get_int_value(ptmpl, WEED_LEAF_MIN, NULL);
2248 int maxi = weed_get_int_value(ptmpl, WEED_LEAF_MAX, NULL);
2249 oval0 = (int)((
double)(vals[j] - omin) / (
double)(omax - omin) * (
double)(maxi - mini)) + mini;
2250 OSC_writeIntArg(&obuf, oval0);
2253 int omin = mnode->
min[j];
2254 int omax = mnode->
max[j];
2255 double minf = weed_get_double_value(ptmpl, WEED_LEAF_MIN, NULL);
2256 double maxf = weed_get_double_value(ptmpl, WEED_LEAF_MAX, NULL);
2257 oval = (double)(vals[j] - omin) / (double)(omax - omin) * (maxf - minf) + minf;
2258 OSC_writeFloatArg(&obuf, (
float)oval);
2265 weed_plant_t *filter;
2266 weed_plant_t **ptmpls;
2267 weed_plant_t *ptmpl;
2269 if (mode == -1)
return NULL;
2274 for (k = 0; k < ntmpls; k++) {
2279 if ((ptype == WEED_PARAM_INTEGER || ptype == WEED_PARAM_FLOAT) && flags == 0 &&
2280 weed_leaf_num_elements(ptmpl, WEED_LEAF_DEFAULT) == 1) {
2282 if (ptype == WEED_PARAM_INTEGER) {
2283 int omin = mnode->
min[j];
2284 int omax = mnode->
max[j];
2285 int mini = weed_get_int_value(ptmpl, WEED_LEAF_MIN, NULL);
2286 int maxi = weed_get_int_value(ptmpl, WEED_LEAF_MAX, NULL);
2287 int oval = (int)((
double)(vals[j] - omin) / (
double)(omax - omin) * (
double)(maxi - mini)) + mini;
2288 OSC_writeIntArg(&obuf, oval);
2291 int omin = mnode->
min[j];
2292 int omax = mnode->
max[j];
2293 double minf = weed_get_double_value(ptmpl, WEED_LEAF_MIN, NULL);
2294 double maxf = weed_get_double_value(ptmpl, WEED_LEAF_MAX, NULL);
2295 oval = (double)(vals[j] - omin) / (double)(omax - omin) * (maxf - minf) + minf;
2296 OSC_writeFloatArg(&obuf, (
float)oval);
2308 if (i == 0) oval0 = (int)oval;
2309 if (i == 1) oval1 = (int)oval;
2311 OSC_writeIntArg(&obuf, oval);
2317 if (macro !=
OSC_NOTIFY) OSC_writeFloatArg(&obuf, oval);
2325 if (i == 0) oval0 = mnode->
fvali[i];
2326 if (i == 1) oval1 = mnode->
fvali[i];
2328 if (i == 0) oval0 = omacro.
vali[i];
2329 if (i == 1) oval1 = omacro.
vali[i];
2333 oval = mnode->
fvald[i];
2335 oval = omacro.
vald[i];
2337 if (macro !=
OSC_NOTIFY) OSC_writeFloatArg(&obuf, (
float)oval);
2347 g_print(
"sending noti\n");
2362 LiVESSList *slist = omc_node_list;
2372 LiVESResponseType retval;
2394 if ((fd = open(
save_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
2396 if (retval == LIVES_RESPONSE_CANCEL) {
2411 nnodes = lives_slist_length(omc_node_list);
2417 srchlen = strlen(mnode->
srch);
2425 for (i = 0; i < mnode->
nvars; i++) {
2438 omacro = omc_macros[mnode->
macro];
2440 for (i = 0; i < omacro.
nparams; i++) {
2446 slist = slist->next;
2456 }
while (retval == LIVES_RESPONSE_RETRY);
2464 static void omc_node_list_free(LiVESSList *slist) {
2467 slist = slist->next;
2469 lives_slist_free(slist);
2474 static void do_devicemap_load_error(
const char *fname) {
2481 static void do_devicemap_version_error(
const char *fname) {
2496 char *load_file = NULL;
2499 uint8_t omnimidi = 1;
2501 uint32_t srchlen, nnodes, macro, nvars, supertype;
2508 #ifdef OMC_MIDI_IMPL
2515 if (!user_data) load_file =
choose_file(devmapdir, NULL, NULL, LIVES_FILE_CHOOSER_ACTION_OPEN, NULL, NULL);
2516 else load_file = lives_strdup((
char *)user_data);
2519 if (!load_file)
return;
2525 d_print(
_(
"Loading device mapping from file %s..."), load_file);
2527 if ((fd = open(load_file, O_RDONLY)) < 0) {
2529 char *msg =
lives_strdup_printf(
_(
"\n\nUnable to open file\n%s\nError code %d\n"), load_file, errno);
2538 if (!omc_macros_inited) {
2540 omc_macros_inited =
TRUE;
2552 if (!
mainw->
go_away) do_devicemap_version_error(load_file);
2569 if (omc_node_list) {
2570 omc_node_list_free(omc_node_list);
2571 omc_node_list = NULL;
2574 for (i = 0; i < nnodes; i++) {
2582 bytes = read(fd, srch, srchlen);
2583 if (bytes < srchlen) {
2599 supertype = atoi(srch);
2601 switch (supertype) {
2604 supertype = js_msg_type(srch);
2607 idx = js_index(srch);
2610 #ifdef OMC_MIDI_IMPL
2615 new_midi_rcv_channel = 0;
2620 tmp = cut_string_elems(srch, 1);
2622 tmp = lives_strdup(srch + blen + 1);
2632 mnode = lives_omc_match_node_new(supertype, idx, srch, -(nvars + 1));
2635 mnode->
macro = macro;
2637 for (j = 0; j < nvars; j++) {
2668 omacro = omc_macros[macro];
2674 for (j = 0; j < omacro.
nparams; j++) {
2683 bytes = read(fd, &mnode->
fvald[j], 8);
2688 omc_node_list = lives_slist_append(omc_node_list, (livespointer)mnode);
2694 #ifdef OMC_MIDI_IMPL
2706 if (new_midi_rcv_channel ==
MIDI_OMNI) dpr = (
_(
"MIDI receive channel was set to ALL CHANNELS\n"));
2707 else dpr =
lives_strdup_printf(
_(
"MIDI receive channel was set to channel %d\n"), new_midi_rcv_channel);
2712 _(
"The MIDI receive channel setting was updated by the device map.\n"
2713 "Please review the setting in Preferences and adjust it if necessary.\n"));
2721 if (!
mainw->
go_away) do_devicemap_load_error(load_file);