#include "gui.h" #include "guiConst.h" #include "../ta-log.h" int MIDIMap::at(const TAMidiMessage& where) { if (map==NULL) return 0; int type=(where.type>>4)-8; int chan=where.type&15; int data1=where.data[0]; int data2=where.data[1]; if (type<0) return 0; if (map[type]==NULL) return 0; int** chanMap=map[type][chan]; if (chanMap==NULL) { chanMap=map[type][16]; if (chanMap==NULL) return 0; } int* dataMap=chanMap[data1]; if (dataMap==NULL) { dataMap=chanMap[128]; if (dataMap==NULL) return 0; } int ret=dataMap[data2]; if (ret==0) { ret=dataMap[128]; if (ret==0) { // maybe this is not the correct mapping dataMap=chanMap[128]; if (dataMap==NULL) { chanMap=map[type][16]; if (chanMap==NULL) return 0; dataMap=chanMap[data1]; if (dataMap==NULL) { dataMap=chanMap[128]; if (dataMap==NULL) return 0; } ret=dataMap[data2]; if (ret==0) { ret=dataMap[128]; } } else { ret=dataMap[data2]; if (ret==0) { ret=dataMap[128]; } } } } return ret; } #define UNDERSTAND_OPTION(x) if (optionNameS==#x) { \ x=std::stoi(optionValueS); \ } #define UNDERSTAND_FLOAT_OPTION(x) if (optionNameS==#x) { \ x=std::stof(optionValueS); \ } #define UNDERSTAND_ARRAY_OPTION(x,yMax) if (optionNameS==#x) { \ if (optionIndex<0 || optionIndex>=yMax) { \ logW("MIDI map array option %d out of range (0-%d) at line %d: %s",optionIndex,yMax,curLine,line); \ break; \ } \ x[optionIndex]=std::stoi(optionValueS); \ } bool MIDIMap::read(String path) { char line[4096]; int curLine=1; FILE* f=fopen(path.c_str(),"rb"); if (f==NULL) { if (errno!=ENOENT) { logE("error while loading MIDI mapping! %s",strerror(errno)); } return false; } binds.clear(); while (fgets(line,4096,f)) { char* nlPos=strrchr(line,'\n'); if (nlPos!=NULL) *nlPos=0; if (strstr(line,"aOption")==line) { char optionName[256]; int optionIndex=-1; char optionValue[256]; String optionNameS, optionValueS; int result=sscanf(line,"aOption %255s %d %255s",optionName,&optionIndex,optionValue); if (result!=3) { logW("MIDI map garbage data at line %d: %s",curLine,line); break; } optionNameS=optionName; optionValueS=optionValue; try { UNDERSTAND_ARRAY_OPTION(valueInputSpecificStyle,18) else UNDERSTAND_ARRAY_OPTION(valueInputSpecificMSB,18) else UNDERSTAND_ARRAY_OPTION(valueInputSpecificLSB,18) else UNDERSTAND_ARRAY_OPTION(valueInputSpecificSingle,18) else { logW("MIDI map unknown array option %s at line %d: %s",optionName,curLine,line); } } catch (std::out_of_range& e) { logW("MIDI map invalid value %s for array option %s at line %d: %s",optionValue,optionName,curLine,line); } catch (std::invalid_argument& e) { logW("MIDI map invalid value %s for array option %s at line %d: %s",optionValue,optionName,curLine,line); } curLine++; continue; } if (strstr(line,"option")==line) { char optionName[256]; char optionValue[256]; String optionNameS, optionValueS; int result=sscanf(line,"option %255s %255s",optionName,optionValue); if (result!=2) { logW("MIDI map garbage data at line %d: %s",curLine,line); break; } optionNameS=optionName; optionValueS=optionValue; try { UNDERSTAND_OPTION(noteInput) else UNDERSTAND_OPTION(volInput) else UNDERSTAND_OPTION(rawVolume) else UNDERSTAND_OPTION(polyInput) else UNDERSTAND_OPTION(directChannel) else UNDERSTAND_OPTION(programChange) else UNDERSTAND_OPTION(midiClock) else UNDERSTAND_OPTION(midiTimeCode) else UNDERSTAND_OPTION(yamahaFMResponse) else UNDERSTAND_OPTION(valueInputStyle) else UNDERSTAND_OPTION(valueInputControlMSB) else UNDERSTAND_OPTION(valueInputControlLSB) else UNDERSTAND_OPTION(valueInputControlSingle) else UNDERSTAND_FLOAT_OPTION(volExp) else { logW("MIDI map unknown option %s at line %d: %s",optionName,curLine,line); } } catch (std::out_of_range& e) { logW("MIDI map invalid value %s for option %s at line %d: %s",optionValue,optionName,curLine,line); } catch (std::invalid_argument& e) { logW("MIDI map invalid value %s for option %s at line %d: %s",optionValue,optionName,curLine,line); } curLine++; continue; } char bindAction[256]; MIDIBind bind; int result=sscanf(line,"%d %d %d %d %255s",&bind.type,&bind.channel,&bind.data1,&bind.data2,bindAction); if (result!=5 || result==EOF) { logW("MIDI map garbage data at line %d: %s",curLine,line); break; } bool foundAction=false; for (int i=0; i15) continue; if (i.channel<0 || i.channel>16) continue; if (i.data1<0 || i.data1>128) continue; if (i.data2<0 || i.data2>128) continue; if (map[i.type-8]==NULL) { map[i.type-8]=new int**[17]; memset(map[i.type-8],0,sizeof(int**)*17); } if (map[i.type-8][i.channel]==NULL) { map[i.type-8][i.channel]=new int*[129]; memset(map[i.type-8][i.channel],0,sizeof(int*)*129); } if (map[i.type-8][i.channel][i.data1]==NULL) { map[i.type-8][i.channel][i.data1]=new int[129]; memset(map[i.type-8][i.channel][i.data1],0,sizeof(int)*129); } map[i.type-8][i.channel][i.data1][i.data2]=i.action; logD("MIDI mapping %d %d %d %d to %d",i.type-8,i.channel,i.data1,i.data2,i.action); } }