Add Pitch bend support + some note fixes
This commit is contained in:
parent
1992f6f445
commit
fd99dafc5f
6 changed files with 293 additions and 143 deletions
39
README
39
README
|
|
@ -27,15 +27,22 @@ Format is a regular shell format
|
||||||
-- Environment
|
-- Environment
|
||||||
- Global
|
- Global
|
||||||
$channel: channel of the
|
$channel: channel of the
|
||||||
$id: id of the note/controller
|
|
||||||
|
|
||||||
|
|
||||||
- Note
|
- Note
|
||||||
|
$id: id of the note
|
||||||
$velocity: velocity of the note
|
$velocity: velocity of the note
|
||||||
|
|
||||||
- Controller
|
- Controller
|
||||||
|
$id: id of the controller
|
||||||
$value: value of the controller (remapped)
|
$value: value of the controller (remapped)
|
||||||
$rawvalue: original value of the controller
|
$rawvalue: original value of the controller
|
||||||
|
|
||||||
|
- Pitch bend
|
||||||
|
$value: value of the bend (remapped)
|
||||||
|
$rawvalue: original value of the bend
|
||||||
|
|
||||||
|
|
||||||
-- FILE FORMAT --
|
-- FILE FORMAT --
|
||||||
[<device>,<device>]
|
[<device>,<device>]
|
||||||
|
|
@ -48,37 +55,39 @@ commands=[<command>,<command>]
|
||||||
-
|
-
|
||||||
*name: string referring to client name of the device
|
*name: string referring to client name of the device
|
||||||
|
|
||||||
- command format (global):
|
- <command> format (global):
|
||||||
{
|
{
|
||||||
type=<note/controller>
|
type=<note/controller/pitch>
|
||||||
id=<x>
|
|
||||||
shell=<shell command>
|
shell=<shell command>
|
||||||
channel=<*/x>
|
channel=<*/x>
|
||||||
}
|
}
|
||||||
-
|
-
|
||||||
*id: value from 0 to 127 referring to id of note/controller
|
|
||||||
> mandatory
|
|
||||||
*shell: shell command to be executed
|
*shell: shell command to be executed
|
||||||
> mandatory
|
> mandatory
|
||||||
*channel: value from 0 to 16 for channel. Can use * for any channel
|
*channel: value from 0 to 16 for channel. Can use * for any channel
|
||||||
> optional, default *
|
> optional, default *
|
||||||
|
|
||||||
|
|
||||||
- <command> format (note)
|
- <command> format (note)
|
||||||
{
|
{
|
||||||
|
id=<x>
|
||||||
trigger=<x:y/x>
|
trigger=<x:y/x>
|
||||||
}
|
}
|
||||||
-
|
-
|
||||||
|
*id: value from 0 to 127 referring to id of note/controller
|
||||||
|
> mandatory
|
||||||
*trigger: note velocity from 0 to 127 that triggers the command. Can enter an interval x:y or single value
|
*trigger: note velocity from 0 to 127 that triggers the command. Can enter an interval x:y or single value
|
||||||
> optional, default 1:127
|
> optional, default 1:127
|
||||||
|
|
||||||
- <command> format (note)
|
- <command> format (controller)
|
||||||
{
|
{
|
||||||
|
id=<x>
|
||||||
range=<x:y>
|
range=<x:y>
|
||||||
remap=<x:y>
|
remap=<x:y>
|
||||||
float=<true/false>
|
float=<true/false>
|
||||||
}
|
}
|
||||||
-
|
-
|
||||||
|
*id: value from 0 to 127 referring to id of note/controller
|
||||||
|
> mandatory
|
||||||
*range: controller value from 0 to 127 that triggers command. Can enter an interval x:y or single value
|
*range: controller value from 0 to 127 that triggers command. Can enter an interval x:y or single value
|
||||||
> optional, default 0:127
|
> optional, default 0:127
|
||||||
*remap: remaps the range to given interval. Interval can be inversed and float
|
*remap: remaps the range to given interval. Interval can be inversed and float
|
||||||
|
|
@ -86,4 +95,18 @@ float=<true/false>
|
||||||
*float: boolean value defining if output is a floating point value
|
*float: boolean value defining if output is a floating point value
|
||||||
> optional, default false
|
> optional, default false
|
||||||
|
|
||||||
|
- <command> format (pitch)
|
||||||
|
{
|
||||||
|
range=<x:y>
|
||||||
|
remap=<x:y>
|
||||||
|
float=<true/false>
|
||||||
|
}
|
||||||
|
-
|
||||||
|
*range: controller value from -8192 to 8192 that triggers command. Can enter an interval x:y or single value
|
||||||
|
> optional, default -8192:8192
|
||||||
|
*remap: remaps the range to given interval. Interval can be inversed and float
|
||||||
|
> optional, default same as range
|
||||||
|
*float: boolean value defining if output is a floating point value
|
||||||
|
> optional, default false
|
||||||
|
|
||||||
- Comments can be written inside {} by doing //=<COMMENT>
|
- Comments can be written inside {} by doing //=<COMMENT>
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,11 @@
|
||||||
{
|
{
|
||||||
type=note
|
type=note
|
||||||
id=9
|
id=9
|
||||||
channel=0
|
|
||||||
trigger=1:127
|
|
||||||
shell=echo "Note $id on ch$channel v$velocity"
|
shell=echo "Note $id on ch$channel v$velocity"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type=note
|
type=note
|
||||||
id=9
|
id=9
|
||||||
channel=0
|
|
||||||
trigger=0
|
trigger=0
|
||||||
shell=echo "Note $id off ch$channel"
|
shell=echo "Note $id off ch$channel"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ class NoteCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NoteCommand(uint8_t i, uint8_t ch, uint8_t l, uint8_t h, std::string sh);
|
NoteCommand(uint8_t i, int8_t ch, uint8_t l, uint8_t h, std::string sh);
|
||||||
|
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
uint8_t channel;
|
int8_t channel;
|
||||||
uint8_t low;
|
uint8_t low;
|
||||||
uint8_t high;
|
uint8_t high;
|
||||||
std::string shell;
|
std::string shell;
|
||||||
|
|
@ -34,5 +34,20 @@ public:
|
||||||
std::string shell;
|
std::string shell;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PitchCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
PitchCommand(uint8_t ch, int16_t l, int16_t h, float ml, float mh, bool fl, std::string sh);
|
||||||
|
|
||||||
|
int8_t channel;
|
||||||
|
int16_t min;
|
||||||
|
int16_t max;
|
||||||
|
float mapMin;
|
||||||
|
float mapMax;
|
||||||
|
bool floating;
|
||||||
|
std::string shell;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif //COMMAND_HPP
|
#endif //COMMAND_HPP
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ public:
|
||||||
virtual ~Device();
|
virtual ~Device();
|
||||||
|
|
||||||
bool start_loop();
|
bool start_loop();
|
||||||
|
void run_signal(char* buff);
|
||||||
|
|
||||||
bool import_chunk(Chunk const& ch);
|
bool import_chunk(Chunk const& ch);
|
||||||
Chunk export_chunk();
|
Chunk export_chunk();
|
||||||
|
|
@ -26,7 +27,8 @@ public:
|
||||||
uint32_t nb_command;
|
uint32_t nb_command;
|
||||||
std::vector<NoteCommand> noteCommands[128];
|
std::vector<NoteCommand> noteCommands[128];
|
||||||
std::vector<ControllerCommand> ctrlCommands[128];
|
std::vector<ControllerCommand> ctrlCommands[128];
|
||||||
// std::vector<Command> systCommands;
|
std::vector<PitchCommand> pitchCommands;
|
||||||
|
// std::vector<Command> sysCommands;
|
||||||
|
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
|
|
||||||
NoteCommand::NoteCommand(uint8_t i, uint8_t ch, uint8_t l, uint8_t h, std::string sh)
|
NoteCommand::NoteCommand(uint8_t i, int8_t ch, uint8_t l, uint8_t h, std::string sh)
|
||||||
{
|
{
|
||||||
this->id=i;
|
this->id=i;
|
||||||
this->channel=ch;
|
this->channel=ch;
|
||||||
|
|
@ -20,3 +20,14 @@ ControllerCommand::ControllerCommand(uint8_t i, int8_t ch, uint8_t l, uint8_t h,
|
||||||
this->floating=fl;
|
this->floating=fl;
|
||||||
this->shell=sh;
|
this->shell=sh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PitchCommand::PitchCommand(uint8_t ch, int16_t l, int16_t h, float ml, float mh, bool fl, std::string sh)
|
||||||
|
{
|
||||||
|
this->channel=ch;
|
||||||
|
this->min=l;
|
||||||
|
this->max=h;
|
||||||
|
this->mapMin=ml;
|
||||||
|
this->mapMax=mh;
|
||||||
|
this->floating=fl;
|
||||||
|
this->shell=sh;
|
||||||
|
}
|
||||||
|
|
|
||||||
358
src/device.cpp
358
src/device.cpp
|
|
@ -54,12 +54,8 @@ bool Device::import_chunk(Chunk const& ch)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int8_t channel;
|
int8_t channel;
|
||||||
uint8_t id;
|
|
||||||
std::string shell;
|
std::string shell;
|
||||||
|
|
||||||
//id
|
|
||||||
id=stoi(tch["id"].strval());
|
|
||||||
|
|
||||||
//channel
|
//channel
|
||||||
if(tch.subChunkPtr("channel") == nullptr || tch["channel"].strval()=="*")
|
if(tch.subChunkPtr("channel") == nullptr || tch["channel"].strval()=="*")
|
||||||
channel=-1;
|
channel=-1;
|
||||||
|
|
@ -72,37 +68,50 @@ bool Device::import_chunk(Chunk const& ch)
|
||||||
//type
|
//type
|
||||||
if(tstr == "note") //type note
|
if(tstr == "note") //type note
|
||||||
{
|
{
|
||||||
uint8_t low;
|
uint8_t id;
|
||||||
uint8_t high;
|
uint8_t low=1;
|
||||||
|
uint8_t high=127;
|
||||||
std::string tt;
|
std::string tt;
|
||||||
|
|
||||||
|
//id
|
||||||
|
id=stoi(tch["id"].strval());
|
||||||
|
|
||||||
//trigger
|
//trigger
|
||||||
tt=tch["trigger"].strval();
|
Chunk* ttch=tch.subChunkPtr("trigger");
|
||||||
auto tpos=tt.find(':');
|
if(ttch != nullptr)
|
||||||
if(tpos == std::string::npos)
|
|
||||||
{
|
{
|
||||||
//single value
|
tt=ttch->strval();
|
||||||
low=stoi(tt);
|
auto tpos=tt.find(':');
|
||||||
high=low;
|
if(tpos == std::string::npos)
|
||||||
}
|
{
|
||||||
else
|
//single value
|
||||||
{
|
low=stoi(tt);
|
||||||
//range
|
high=low;
|
||||||
low=stoi(tt.substr(0,tpos));
|
}
|
||||||
tpos++;
|
else
|
||||||
high=stoi(tt.substr(tpos, tt.size()-tpos));
|
{
|
||||||
|
//range
|
||||||
|
low=stoi(tt.substr(0,tpos));
|
||||||
|
tpos++;
|
||||||
|
high=stoi(tt.substr(tpos, tt.size()-tpos));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
printf("%d:%d\n",low,high);
|
||||||
this->noteCommands[id].push_back(NoteCommand(id,channel,low,high,shell));
|
this->noteCommands[id].push_back(NoteCommand(id,channel,low,high,shell));
|
||||||
this->nb_command++;
|
this->nb_command++;
|
||||||
}
|
}
|
||||||
else if(tstr == "controller") //type controller
|
else if(tstr == "controller") //type controller
|
||||||
{
|
{
|
||||||
|
uint8_t id;
|
||||||
uint8_t min=0;
|
uint8_t min=0;
|
||||||
uint8_t max=127;
|
uint8_t max=127;
|
||||||
float mapMin;
|
float mapMin;
|
||||||
float mapMax;
|
float mapMax;
|
||||||
bool floating=false;
|
bool floating=false;
|
||||||
|
|
||||||
|
//id
|
||||||
|
id=stoi(tch["id"].strval());
|
||||||
|
|
||||||
//range
|
//range
|
||||||
Chunk* ttch=tch.subChunkPtr("range");
|
Chunk* ttch=tch.subChunkPtr("range");
|
||||||
if(ttch != nullptr)
|
if(ttch != nullptr)
|
||||||
|
|
@ -152,6 +161,63 @@ bool Device::import_chunk(Chunk const& ch)
|
||||||
this->ctrlCommands[id].push_back(ControllerCommand(id,channel,min,max,mapMin,mapMax,floating,shell));
|
this->ctrlCommands[id].push_back(ControllerCommand(id,channel,min,max,mapMin,mapMax,floating,shell));
|
||||||
this->nb_command++;
|
this->nb_command++;
|
||||||
}
|
}
|
||||||
|
else if(tstr == "pitch") //type pitch bend
|
||||||
|
{
|
||||||
|
int16_t min=-8192;
|
||||||
|
int16_t max=8192;
|
||||||
|
float mapMin;
|
||||||
|
float mapMax;
|
||||||
|
bool floating=false;
|
||||||
|
|
||||||
|
//range
|
||||||
|
Chunk* ttch=tch.subChunkPtr("range");
|
||||||
|
if(ttch != nullptr)
|
||||||
|
{
|
||||||
|
std::string range=ttch->strval();
|
||||||
|
auto tpos=range.find(':');
|
||||||
|
if(tpos == std::string::npos)
|
||||||
|
{
|
||||||
|
//single value
|
||||||
|
min=stoi(range);
|
||||||
|
max=min;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//range
|
||||||
|
min=stoi(range.substr(0,tpos));
|
||||||
|
tpos++;
|
||||||
|
max=stoi(range.substr(tpos, range.size()-tpos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//remap
|
||||||
|
ttch=tch.subChunkPtr("remap");
|
||||||
|
if(ttch != nullptr)
|
||||||
|
{
|
||||||
|
std::string map=ttch->strval();
|
||||||
|
auto tpos=map.find(':');
|
||||||
|
mapMin=stof(map.substr(0,tpos));
|
||||||
|
tpos++;
|
||||||
|
mapMax=stof(map.substr(tpos, map.size()-tpos));
|
||||||
|
}
|
||||||
|
|
||||||
|
//floating
|
||||||
|
ttch=tch.subChunkPtr("float");
|
||||||
|
if(ttch != nullptr)
|
||||||
|
{
|
||||||
|
std::string tfl=ttch->strval();
|
||||||
|
if( tfl == "true" || tfl == "yes" || tfl == "y")
|
||||||
|
floating=true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapMin=min;
|
||||||
|
mapMax=max;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->pitchCommands.push_back(PitchCommand(channel,min,max,mapMin,mapMax,floating,shell));
|
||||||
|
this->nb_command++;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Command type " + tstr + " doesn't exist");
|
throw std::runtime_error("Command type " + tstr + " doesn't exist");
|
||||||
|
|
@ -162,6 +228,150 @@ bool Device::import_chunk(Chunk const& ch)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::run_signal(char* buff)
|
||||||
|
{
|
||||||
|
if ( (strstr(buff, "Port unsubscribed") != NULL) ) // distonnected
|
||||||
|
{
|
||||||
|
std::string kill_command=KILL_COMMAND_FH + this->name + KILL_COMMAND_SH;
|
||||||
|
system(kill_command.c_str()); // kill the process
|
||||||
|
this->busy=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (index(buff, ':') != NULL) // MIDI command
|
||||||
|
{
|
||||||
|
if (strstr(buff, "System exclusive") != NULL)
|
||||||
|
{
|
||||||
|
printf("%s", buff);
|
||||||
|
//do stuff
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int t;
|
||||||
|
char type;
|
||||||
|
int8_t channel;
|
||||||
|
int ctid;
|
||||||
|
int16_t value;
|
||||||
|
char* pos=NULL;
|
||||||
|
bool note_off=false;
|
||||||
|
|
||||||
|
//note off special case
|
||||||
|
if (strstr(buff,"Note off") != NULL)
|
||||||
|
note_off=true;
|
||||||
|
|
||||||
|
// type read
|
||||||
|
if (strstr(buff,"note") != NULL)
|
||||||
|
type='n';
|
||||||
|
else if (strstr(buff,"controller") != NULL)
|
||||||
|
type='c';
|
||||||
|
else if (strstr(buff,"Pitch") != NULL)
|
||||||
|
type='p';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Unknown MIDI signal\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//channel read
|
||||||
|
pos=index(buff, ',');
|
||||||
|
t=1;
|
||||||
|
while (*(pos-t-1) != ' ')
|
||||||
|
t++;
|
||||||
|
channel = std::stoi( std::string(pos-t, t) );
|
||||||
|
pos+=2;
|
||||||
|
|
||||||
|
//ctid read (only note anc controller)
|
||||||
|
if(type=='n' || type=='c')
|
||||||
|
{
|
||||||
|
while (*(pos) != ' ')
|
||||||
|
pos++;
|
||||||
|
pos++;
|
||||||
|
t=1;
|
||||||
|
while ( isNum(*(pos+t)) )
|
||||||
|
t++;
|
||||||
|
ctid = std::stoi( std::string(pos, t) );
|
||||||
|
pos+=t+2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//value read
|
||||||
|
if(!note_off)
|
||||||
|
{
|
||||||
|
while (*(pos) != ' ')
|
||||||
|
pos++;
|
||||||
|
pos++;
|
||||||
|
t=1;
|
||||||
|
while ( isNum(*(pos+t)) )
|
||||||
|
t++;
|
||||||
|
value = std::stoi( std::string(pos, t));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
value=0;
|
||||||
|
|
||||||
|
if (type == 'n')
|
||||||
|
{
|
||||||
|
for( auto it : this->noteCommands[ctid])
|
||||||
|
{
|
||||||
|
if((it.channel == -1 || it.channel == channel) && it.low <= value && it.high >= value)
|
||||||
|
{
|
||||||
|
std::string command="id=" + std::to_string(ctid) + ";channel=" + std::to_string(channel) + ";velocity=" + std::to_string(value) + ";";
|
||||||
|
command += it.shell;
|
||||||
|
std::thread(sh, command).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == 'c')
|
||||||
|
{
|
||||||
|
for( auto it : this->ctrlCommands[ctid])
|
||||||
|
{
|
||||||
|
if((it.channel == -1 || it.channel == channel) && it.min <= value && it.max >= value)
|
||||||
|
{
|
||||||
|
//remapping of value
|
||||||
|
float result;
|
||||||
|
if(it.min == it.max)
|
||||||
|
result = it.mapMin;
|
||||||
|
else
|
||||||
|
result=(value-it.min)*(it.mapMax-it.mapMin)/(it.max-it.min)+it.mapMin;
|
||||||
|
|
||||||
|
//command execution
|
||||||
|
std::string command="id=" + std::to_string(ctid) + ";channel=" + std::to_string(channel) + ";rawvalue=" + std::to_string(value) + ";value=";
|
||||||
|
if(it.floating)
|
||||||
|
command += std::to_string(result);
|
||||||
|
else
|
||||||
|
command += std::to_string((long int) result);
|
||||||
|
command += ";" + it.shell;
|
||||||
|
std::thread(sh, command).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(type == 'p')
|
||||||
|
{
|
||||||
|
for( auto it : this->pitchCommands)
|
||||||
|
{
|
||||||
|
if((it.channel == -1 || it.channel == channel) && it.min <= value && it.max >= value)
|
||||||
|
{
|
||||||
|
//remapping of value
|
||||||
|
float result;
|
||||||
|
if(it.min == it.max)
|
||||||
|
result = it.mapMin;
|
||||||
|
else
|
||||||
|
result=(value-it.min)*(it.mapMax-it.mapMin)/(it.max-it.min)+it.mapMin;
|
||||||
|
|
||||||
|
//command execution
|
||||||
|
std::string command="id=" + std::to_string(ctid) + ";channel=" + std::to_string(channel) + ";rawvalue=" + std::to_string(value) + ";value=";
|
||||||
|
if(it.floating)
|
||||||
|
command += std::to_string(result);
|
||||||
|
else
|
||||||
|
command += std::to_string((long int) result);
|
||||||
|
command += ";" + it.shell;
|
||||||
|
std::thread(sh, command).detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // if type
|
||||||
|
|
||||||
|
} //if system exclusive
|
||||||
|
} //while
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Device::loop(Device* dev)
|
void Device::loop(Device* dev)
|
||||||
{
|
{
|
||||||
std::string command = "aseqdump -p '" + dev->name + '\'';
|
std::string command = "aseqdump -p '" + dev->name + '\'';
|
||||||
|
|
@ -171,115 +381,7 @@ void Device::loop(Device* dev)
|
||||||
|
|
||||||
while (getline(&buff, &buff_size, stream) > 0)
|
while (getline(&buff, &buff_size, stream) > 0)
|
||||||
{
|
{
|
||||||
if ( (strstr(buff, "Port unsubscribed") != NULL) ) // distonnected
|
dev->run_signal(buff);
|
||||||
{
|
|
||||||
std::string kill_command=KILL_COMMAND_FH + dev->name + KILL_COMMAND_SH;
|
|
||||||
system(kill_command.c_str()); // kill the process
|
|
||||||
dev->busy=false;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (index(buff, ':') != NULL) // MIDI command
|
|
||||||
{
|
|
||||||
if (strstr(buff, "System exclusive") != NULL)
|
|
||||||
{
|
|
||||||
printf("%s", buff);
|
|
||||||
//do stuff
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int t;
|
|
||||||
char type;
|
|
||||||
int8_t channel;
|
|
||||||
int ctid;
|
|
||||||
uint8_t value;
|
|
||||||
char* pos=NULL;
|
|
||||||
bool note_off=false;
|
|
||||||
|
|
||||||
if (strstr(buff,"Note off") != NULL)
|
|
||||||
note_off=true;
|
|
||||||
|
|
||||||
//channel read
|
|
||||||
pos=index(buff, ',');
|
|
||||||
t=1;
|
|
||||||
while (*(pos-t-1) != ' ')
|
|
||||||
t++;
|
|
||||||
channel = std::stoi( std::string(pos-t, t) );
|
|
||||||
pos+=2;
|
|
||||||
|
|
||||||
//type
|
|
||||||
if (*pos == 'c') //controller signal
|
|
||||||
type='c';
|
|
||||||
else if (*pos == 'n') //note signal
|
|
||||||
type='n';
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Unknown MIDI signal\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ctid read
|
|
||||||
while (*(pos) != ' ')
|
|
||||||
pos++;
|
|
||||||
pos++;
|
|
||||||
t=1;
|
|
||||||
while ( isNum(*(pos+t)) )
|
|
||||||
t++;
|
|
||||||
ctid = std::stoi( std::string(pos, t) );
|
|
||||||
pos+=t+2;
|
|
||||||
|
|
||||||
|
|
||||||
//value read
|
|
||||||
if(!note_off)
|
|
||||||
{
|
|
||||||
while (*(pos) != ' ')
|
|
||||||
pos++;
|
|
||||||
pos++;
|
|
||||||
t=1;
|
|
||||||
while ( isNum(*(pos+t)) )
|
|
||||||
t++;
|
|
||||||
value = std::stoi( std::string(pos, t));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
value=0;
|
|
||||||
|
|
||||||
if (type == 'n')
|
|
||||||
{
|
|
||||||
for( auto it : dev->noteCommands[ctid])
|
|
||||||
{
|
|
||||||
if((it.channel == -1 || it.channel == channel) && it.low <= value && it.high >= value)
|
|
||||||
{
|
|
||||||
std::string command="id=" + std::to_string(ctid) + ";channel=" + std::to_string(channel) + ";velocity=" + std::to_string(value) + ";";
|
|
||||||
command += it.shell;
|
|
||||||
std::thread(sh, command).detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(type == 'c')
|
|
||||||
{
|
|
||||||
for( auto it : dev->ctrlCommands[ctid])
|
|
||||||
{
|
|
||||||
if((it.channel == -1 || it.channel == channel) && it.min <= value && it.max >= value)
|
|
||||||
{
|
|
||||||
//remapping of value
|
|
||||||
float result;
|
|
||||||
if(it.min == it.max)
|
|
||||||
result = it.mapMin;
|
|
||||||
else
|
|
||||||
result=(value-it.min)*(it.mapMax-it.mapMin)/(it.max-it.min)+it.mapMin;
|
|
||||||
|
|
||||||
//command execution
|
|
||||||
std::string command="id=" + std::to_string(ctid) + ";channel=" + std::to_string(channel) + ";rawvalue=" + std::to_string(value) + ";value=";
|
|
||||||
if(it.floating)
|
|
||||||
command += std::to_string(result);
|
|
||||||
else
|
|
||||||
command += std::to_string((long int) result);
|
|
||||||
command += ";" + it.shell;
|
|
||||||
std::thread(sh, command).detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Device '%s' disconnected\n", dev->name.c_str());
|
printf("Device '%s' disconnected\n", dev->name.c_str());
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue