/* * Programmer: Dominik Schmidt-Philipp * Filename: main.c * * Dedicated to seleomlivet * */ #include #include /* for threading */ #include #include "mapping.h" typedef struct { snd_rawmidi_t* midiin; snd_rawmidi_t* midiout; lo_address osc_out; unsigned char hui_in_zone; } housicIO; typedef struct { char type; char* address; } Item; char *ZONES[] = { "channel_strip_1", "channel_strip_2", "channel_strip_3", "channel_strip_4", "channel_strip_5", "channel_strip_6", "channel_strip_7", "channel_strip_8", "keyboard_shortcuts", "window", "channel_selection", "assignment_1", "assignment_2", "cursor", "transport_main", "transport_add1", "transport_add2", "monitor_input", "monitor_output", "num_pad_1", "num_pad_2", "num_pad_3", "timecode", "auto_enable", "auto_mode", "status_group", "edit", "fn_keys", "parameter_edit", "misc" }; char *BUTTONS[0x1e][8] = { {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"fader","select","mute","solo","auto","v-sel","insert","rec_rdy"}, {"ctrl","shift","editmode","undo","alt","option","edittool","save"}, {"mix","edit","transprt","mem-loc","status","alt"}, {"chan_left","bank_left","chanl_right","bank_right"}, {"output","input","pan","send_e","send_d","send_c","send_b","send_a"}, {"assign","default","suspend","shift","mute","bypass","recrdyall"}, {"down","left","mode","right","up","scrub","shuttle"}, {"talkback","rewind","fast_fwd","stop","play","record"}, {"rtz","end","on_line","loop","quick_punch"}, {"audition","pre","in","out","post"}, {"input_3 ","input_2","input_1","mute","discrete"}, {"output_3","output_2","output_1","dim","mono"}, {"0","1","4","2","5",".","3","6"}, {"enter","+"}, {"7","8","9","-","clr","=","divide","multiply"}, {"timecode","feet","beats","rudesolo"}, {"plug_in","pan","fader","sendmute","send","mute"}, {"trim","latch","read","off","write","touch"}, {"phase","monitor","auto","suspend","create","group"}, {"paste","cut","capture","delete","copy","separate"}, {"f1","f2","f3","f4","f5","f6","f7","f8"}, {"insert","assign","select_1","select_2","select_3","select_4","bypass","compare"}, {"switch_1","switch_2","click","beep"} }; // function declarations: void alsa_error (const char *format, ...); void* midiinfunction (void * arg); void midi_in_dispatch (void * arg, unsigned char * m); void lo_error (int num, const char *m, const char *path); int osc_in_handler (const char *path, const char *types, lo_arg ** argv, int argc, void *data, void *user_data); void hui_in_button (void *arg, unsigned char m); void osc_send (void *arg, Item el, float value); void register_osc_receives(); int main(int argc, char *argv[]) { int status; int mode = SND_RAWMIDI_SYNC; pthread_t midiinthread; lo_server_thread st = lo_server_thread_new("7770", lo_error); housicIO IOs = {NULL,NULL,0,0}; IOs.osc_out = lo_address_new(NULL,"7771"); const char* portname = "virtual"; // MIDI if ((status = snd_rawmidi_open(&IOs.midiin, NULL, portname, mode)) < 0) { alsa_error("Problem opening MIDI input: %s", snd_strerror(status)); exit(1); } status = pthread_create(&midiinthread, NULL, midiinfunction, &IOs); // OSC register_osc_receives(); lo_server_thread_add_method(st, NULL, NULL, osc_in_handler, NULL); lo_server_thread_start(st); // wait for MIDI thread to end (will not happen) pthread_join(midiinthread, NULL); return 0; } ////////////////////////////// // // midiinfunction -- Thread function which waits around until a MIDI // input byte arrives and then react correspondingly // void register_osc_receives() { } ////////////////////////////// // // midiinfunction -- Thread function which waits around until a MIDI // input byte arrives and then react correspondingly // void *midiinfunction(void *arg) { housicIO* IOs = (housicIO*)arg; snd_rawmidi_t* midiin = IOs->midiin; int status; int i = 0; char buffer[3]; unsigned char message[3]; while (1) { if ((status = snd_rawmidi_read(midiin, buffer, 3)) < 0) { alsa_error("Problem reading MIDI input: %s", snd_strerror(status)); } // in case of MIDI running status, value bytes need to not override status byte for (i=1; i<=status;i++) { message[3-i] = (unsigned char) buffer[status-i]; } midi_in_dispatch(IOs,message); fflush(stdout); } } ////////////////////////////// // // midi_in_dispatch -- Thread function which waits around until a MIDI // input byte arrives and then react correspondingly // void midi_in_dispatch(void *arg, unsigned char *m) { housicIO* IOs = (housicIO*)arg; if (m[0] == 0xb0) { // received a CC message on MIDIchannel 1 if (m[1] == 0x0f) { // received a zone select IOs->hui_in_zone = m[2]; } else { if (m[1] == 0x2f) { // should always be true, if HUI is working. hui_in_button(IOs,m[2]); } } } } ////////////////////////////// // // hui_in_button -- user interacted with a button on the HUI // void hui_in_button(void *arg, unsigned char m) { housicIO* IOs = (housicIO*)arg; char address[32]; char zone = IOs->hui_in_zone; int dir = m & 0xf0; int port = m & 0x0f; sprintf(address, "/%s/%s",ZONES[zone],BUTTONS[zone][port]); Item ee = {'b',address}; if (dir == 0x40) { // down osc_send(IOs, ee, 1); } else if (dir == 0x00) { // up osc_send(IOs, ee, 0); } } ////////////////////////////// // // osc_send -- // void osc_send(void *arg, Item el, float value) { housicIO* IOs = (housicIO*)arg; lo_send(IOs->osc_out, el.address, "f", value ); } ////////////////////////////// // // osc_in_handler -- receive incoming OSC messages // int osc_in_handler (const char *path, const char *types, lo_arg ** argv, int argc, void *data, void *user_data) { int i; printf("path: <%s>\n", path); for (i = 0; i < argc; i++) { printf("arg %d '%c' ", i, types[i]); lo_arg_pp((lo_type)types[i], argv[i]); printf("\n"); } printf("\n"); fflush(stdout); return 1; } ////////////////////////////// // // error -- print error message // void alsa_error(const char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); putc('\n', stderr); } void lo_error(int num, const char *msg, const char *path) { printf("liblo server error %d in path %s: %s\n", num, path, msg); fflush(stdout); }