Added range support to id flag

This commit is contained in:
zawz 2019-06-16 22:59:24 +02:00
parent ccac17666a
commit 94e534f151
4 changed files with 164 additions and 138 deletions

23
README
View file

@ -71,25 +71,25 @@ channel=<*/x>
- <command> format (note)
{
id=<x>
trigger=<x:y/x>
id=<x/x:y/*>
trigger=<x/x:y/*>
}
-
*id: value from 0 to 127 referring to id of note/controller
> mandatory
> optional, default 0:127
*trigger: note velocity from 0 to 127 that triggers the command. Can enter an interval x:y or single value
> optional, default 1:127
- <command> format (controller)
{
id=<x>
range=<x:y>
remap=<x:y>
id=<x/x:y/*>
range=<x/x:y/*>
remap=<x/x:y/*>
float=<true/false>
}
-
*id: value from 0 to 127 referring to id of note/controller
> mandatory
> optional, default 0:127
*range: controller value from 0 to 127 that triggers command. Can enter an interval x:y or single value
> optional, default 0:127
*remap: remaps the range to given interval. Interval can be inversed and float
@ -99,8 +99,8 @@ float=<true/false>
- <command> format (pitch)
{
range=<x:y>
remap=<x:y>
range=<x/x:y/*>
remap=<x/x:y/*>
float=<true/false>
}
-
@ -111,4 +111,9 @@ float=<true/false>
*float: boolean value defining if output is a floating point value
> optional, default false
- Format:
x:y range from x to y
x single value x
* all possible values
- Comments can be written inside {} by doing //=<COMMENT>

View file

@ -4,15 +4,11 @@
name=Launch Control
commands=[
{
type=note
id=9
shell=echo "Note $id on ch$channel v$velocity"
},
{
type=note
id=9
trigger=0
shell=echo "Note $id off ch$channel"
//=KNOB HA
//=displays value 0:127 for knobs 21-28
type=controller
id=21:28
shell=echo "Knob #$id ch$channel:$value"
},
{
//=KNOB L1
@ -58,7 +54,19 @@
,
{
name=Launchpad S
commands=[]
commands=[
{
type=note
id=*
shell=echo "Note $id on velocity:$velocity"
},
{
type=note
id=*
trigger=0
shell=echo "Note $id off"
}
]
}
]

View file

@ -39,6 +39,70 @@ bool Device::start_loop()
return true;
}
std::pair<int32_t,int32_t> importRange(Chunk const& ch, std::string const& tag, int32_t low, int32_t high)
{
Chunk* pch=ch.subChunkPtr(tag);
if(pch != nullptr)
{
std::string str=pch->strval();
auto tpos=str.find(':');
if (str=="*") //whole range
{
return std::make_pair(low,high);
}
else if(tpos == std::string::npos) //single value
{
low=stoi(str);
high=low;
}
else //range
{
low=stoi(str.substr(0,tpos));
tpos++;
high=stoi(str.substr(tpos, str.size()-tpos));
}
}
return std::make_pair(low, high);
}
std::pair<float,float> importRangeFloat(Chunk const& ch, std::string const& tag, float low, float high)
{
Chunk* pch=ch.subChunkPtr(tag);
if(pch != nullptr)
{
std::string str=pch->strval();
auto tpos=str.find(':');
if(tpos == std::string::npos)
{
//single value
low=stof(str);
high=low;
}
else
{
//range
low=stof(str.substr(0,tpos));
tpos++;
high=stof(str.substr(tpos, str.size()-tpos));
}
}
return std::make_pair(low, high);
}
bool importBool(Chunk const& ch, std::string const& tag, bool defbool)
{
Chunk* pch=ch.subChunkPtr(tag);
if(pch != nullptr)
{
std::string str=pch->strval();
if( str == "true" )
return true;
else if( str == "false" )
return false;
}
return defbool;
}
bool Device::import_chunk(Chunk const& ch)
{
Chunk& cch = ch["commands"];
@ -56,6 +120,9 @@ bool Device::import_chunk(Chunk const& ch)
int8_t channel;
std::string shell;
std::pair<int32_t,int32_t> intpair;
std::pair<float,float> floatpair;
//channel
if(tch.subChunkPtr("channel") == nullptr || tch["channel"].strval()=="*")
channel=-1;
@ -68,40 +135,33 @@ bool Device::import_chunk(Chunk const& ch)
//type
if(tstr == "note") //type note
{
uint8_t id;
uint8_t id_low=0;
uint8_t id_high=127;
uint8_t low=1;
uint8_t high=127;
std::string tt;
//id
id=stoi(tch["id"].strval());
intpair=importRange(tch, "id", id_low, id_high);
id_low=intpair.first;
id_high=intpair.second;
// id=stoi(tch["id"].strval());
//trigger
Chunk* ttch=tch.subChunkPtr("trigger");
if(ttch != nullptr)
intpair = importRange(tch, "trigger", low, high);
low=intpair.first;
high=intpair.second;
for( uint8_t i=id_low ; i <= id_high ; i++ )
{
tt=ttch->strval();
auto tpos=tt.find(':');
if(tpos == std::string::npos)
{
//single value
low=stoi(tt);
high=low;
this->noteCommands[i].push_back(NoteCommand(i,channel,low,high,shell));
}
else
{
//range
low=stoi(tt.substr(0,tpos));
tpos++;
high=stoi(tt.substr(tpos, tt.size()-tpos));
}
}
this->noteCommands[id].push_back(NoteCommand(id,channel,low,high,shell));
this->nb_command++;
}
else if(tstr == "controller") //type controller
{
uint8_t id;
uint8_t id_low=0;
uint8_t id_high=127;
uint8_t min=0;
uint8_t max=127;
float mapMin;
@ -109,55 +169,27 @@ bool Device::import_chunk(Chunk const& ch)
bool floating=false;
//id
id=stoi(tch["id"].strval());
intpair=importRange(tch, "id", id_low, id_high);
id_low=intpair.first;
id_high=intpair.second;
//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));
}
}
intpair = importRange(tch, "range", min, max);
min=intpair.first;
max=intpair.second;
//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));
}
else
{
mapMin=min;
mapMax=max;
}
floatpair = importRangeFloat(tch, "remap", min, max);
mapMin=floatpair.first;
mapMax=floatpair.second;
//floating
ttch=tch.subChunkPtr("float");
if(ttch != nullptr)
{
std::string tfl=ttch->strval();
if( tfl == "true" || tfl == "yes" || tfl == "y")
floating=true;
}
floating = importBool(tch, "float", floating);
this->ctrlCommands[id].push_back(ControllerCommand(id,channel,min,max,mapMin,mapMax,floating,shell));
for( uint8_t i=id_low ; i <= id_high ; i++ )
{
this->ctrlCommands[i].push_back(ControllerCommand(i,channel,min,max,mapMin,mapMax,floating,shell));
}
this->nb_command++;
}
else if(tstr == "pitch") //type pitch bend
@ -169,45 +201,17 @@ bool Device::import_chunk(Chunk const& ch)
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));
}
}
intpair = importRange(tch, "range", min, max);
min=intpair.first;
max=intpair.second;
//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));
}
floatpair = importRangeFloat(tch, "remap", min, max);
mapMin=floatpair.first;
mapMax=floatpair.second;
//floating
ttch=tch.subChunkPtr("float");
if(ttch != nullptr)
{
std::string tfl=ttch->strval();
if( tfl == "true" || tfl == "yes" || tfl == "y")
floating=true;
}
floating = importBool(tch, "float", floating);
this->pitchCommands.push_back(PitchCommand(channel,min,max,mapMin,mapMax,floating,shell));
this->nb_command++;
@ -261,7 +265,7 @@ void Device::run_signal(char* buff)
type='p';
else
{
throw std::runtime_error("Unknown MIDI signal\n");
throw std::runtime_error("Unknown MIDI signal:\n" + std::string(buff));
return;
}
@ -273,7 +277,7 @@ void Device::run_signal(char* buff)
channel = std::stoi( std::string(pos-t, t) );
pos+=2;
//ctid read (only note anc controller)
//ctid read (only note and controller)
if(type=='n' || type=='c')
{
while (*(pos) != ' ')
@ -300,13 +304,16 @@ void Device::run_signal(char* buff)
else
value=0;
//processing
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) + ";";
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();
}
@ -320,13 +327,16 @@ void Device::run_signal(char* buff)
{
//remapping of value
float result;
if(it.min == it.max)
if(it.min == it.max) //zero case
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=";
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
@ -344,13 +354,15 @@ void Device::run_signal(char* buff)
{
//remapping of value
float result;
if(it.min == it.max)
if(it.min == it.max) //zero case
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=";
std::string command=";channel=" + std::to_string(channel)
+ ";rawvalue=" + std::to_string(value)
+ ";value=";
if(it.floating)
command += std::to_string(result);
else
@ -362,6 +374,7 @@ void Device::run_signal(char* buff)
} // if type
} //if system exclusive
} //while
}

View file

@ -51,7 +51,7 @@ int main(int argc, char* argv[])
Device *newDevice = new Device;
newDevice->import_chunk(file.chunk()[i]);
device_list.push_back(newDevice);
printf("Added device '%s' with %d commands\n", newDevice->name.c_str(), newDevice->nb_command);
printf("Loaded %d commands for device '%s'\n", newDevice->nb_command, newDevice->name.c_str());
}
}
else