|
|
|
|
|
|
|
|
*/ |
|
|
*/ |
|
|
#include <alsa/asoundlib.h> |
|
|
#include <alsa/asoundlib.h> |
|
|
#include <pthread.h> /* for threading */ |
|
|
#include <pthread.h> /* for threading */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// function declarations: |
|
|
|
|
|
void alsa_error (const char *format, ...); |
|
|
|
|
|
void* midiinfunction (void * arg); |
|
|
|
|
|
void midi_in_dispatch (void * arg, unsigned char * m); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <lo/lo.h> |
|
|
|
|
|
#include "mapping.h" |
|
|
|
|
|
|
|
|
typedef struct { |
|
|
typedef struct { |
|
|
snd_rawmidi_t* midiin; |
|
|
snd_rawmidi_t* midiin; |
|
|
snd_rawmidi_t* midiout; |
|
|
snd_rawmidi_t* midiout; |
|
|
|
|
|
lo_address osc_out; |
|
|
unsigned char hui_in_zone; |
|
|
unsigned char hui_in_zone; |
|
|
} housicIO; |
|
|
} 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","*"}, |
|
|
|
|
|
{"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 main(int argc, char *argv[]) { |
|
|
int status; |
|
|
int status; |
|
|
int mode = SND_RAWMIDI_SYNC; |
|
|
int mode = SND_RAWMIDI_SYNC; |
|
|
pthread_t midiinthread; |
|
|
pthread_t midiinthread; |
|
|
|
|
|
|
|
|
housicIO IOs = {NULL,NULL,0}; |
|
|
|
|
|
|
|
|
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"); |
|
|
|
|
|
|
|
|
// snd_rawmidi_t* midiin = NULL; |
|
|
|
|
|
const char* portname = "virtual"; |
|
|
const char* portname = "virtual"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MIDI |
|
|
if ((status = snd_rawmidi_open(&IOs.midiin, NULL, portname, mode)) < 0) { |
|
|
if ((status = snd_rawmidi_open(&IOs.midiin, NULL, portname, mode)) < 0) { |
|
|
alsa_error("Problem opening MIDI input: %s", snd_strerror(status)); |
|
|
alsa_error("Problem opening MIDI input: %s", snd_strerror(status)); |
|
|
exit(1); |
|
|
exit(1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
status = pthread_create(&midiinthread, NULL, midiinfunction, &IOs); |
|
|
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); |
|
|
pthread_join(midiinthread, NULL); |
|
|
|
|
|
|
|
|
//snd_rawmidi_close(midiin); |
|
|
|
|
|
//midiin=NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// midiinfunction -- Thread function which waits around until a MIDI |
|
|
// midiinfunction -- Thread function which waits around until a MIDI |
|
|
// input byte arrives and then react correspondingly |
|
|
// 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) { |
|
|
void *midiinfunction(void *arg) { |
|
|
housicIO* IOs = (housicIO*)arg; |
|
|
housicIO* IOs = (housicIO*)arg; |
|
|
|
|
|
|
|
|
if (m[1] == 0x0f) { |
|
|
if (m[1] == 0x0f) { |
|
|
// received a zone select |
|
|
// received a zone select |
|
|
IOs->hui_in_zone = m[2]; |
|
|
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 |
|
|
// error -- print error message |
|
|
|
|
|
|
|
|
va_end(ap); |
|
|
va_end(ap); |
|
|
putc('\n', stderr); |
|
|
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); |
|
|
|
|
|
} |