@@ -1,6 +1,6 @@ | |||
/* | |||
* Carla Native Plugins | |||
* Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
* Copyright (C) 2012-2016 Filipe Coelho <falktx@falktx.com> | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public License as | |||
@@ -22,7 +22,6 @@ | |||
# define errx(...) {} | |||
# define warnx(...) {} | |||
# define rindex strrchr | |||
using std::isnan; | |||
#else | |||
# include <err.h> | |||
#endif | |||
@@ -44,10 +44,10 @@ static const Ports partPorts = { | |||
rRecurs(kit, 16, "Kit"),//NUM_KIT_ITEMS | |||
rRecursp(partefx, 3, "Part Effect"), | |||
rRecur(ctl, "Controller"), | |||
rToggle(Penabled, "Part enable"), | |||
rToggle(Penabled, rShort("enable"), "Part enable"), | |||
#undef rChangeCb | |||
#define rChangeCb obj->setPvolume(obj->Pvolume); | |||
rParamZyn(Pvolume, "Part Volume"), | |||
rParamZyn(Pvolume, rShort("Vol"), "Part Volume"), | |||
#undef rChangeCb | |||
#define rChangeCb obj->setPpanning(obj->Ppanning); | |||
rParamZyn(Ppanning, "Set Panning"), | |||
@@ -56,9 +56,9 @@ static const Ports partPorts = { | |||
rParamI(Pkeylimit, rProp(parameter), rMap(min,0), rMap(max, POLYPHONY), "Key limit per part"), | |||
#undef rChangeCb | |||
#define rChangeCb | |||
rParamZyn(Pminkey, "Min Used Key"), | |||
rParamZyn(Pmaxkey, "Max Used Key"), | |||
rParamZyn(Pkeyshift, "Part keyshift"), | |||
rParamZyn(Pminkey, rShort("min"), "Min Used Key"), | |||
rParamZyn(Pmaxkey, rShort("max"), "Max Used Key"), | |||
rParamZyn(Pkeyshift, rShort("shift"), "Part keyshift"), | |||
rParamZyn(Prcvchn, "Active MIDI channel"), | |||
rParamZyn(Pvelsns, "Velocity sensing"), | |||
rParamZyn(Pveloffs, "Velocity offset"), | |||
@@ -0,0 +1,191 @@ | |||
#include <ostream> | |||
#include <rtosc/ports.h> | |||
using namespace rtosc; | |||
/* | |||
* root : | |||
* - 'parameters' : [parameter...] | |||
* - 'actions' : [action...] | |||
* parameter : | |||
* - 'path' : path-id | |||
* - 'name' : string | |||
* - 'shortname' : string [OPTIONAL] | |||
* - 'tooltip' : string [OPTIONAL] | |||
* - 'type' : type | |||
* - 'domain' : range [OPTIONAL] | |||
* type : {'int', 'float', 'boolean'} | |||
* action : | |||
* - 'path' : path-id | |||
* - 'args' : [arg...] | |||
* arg : | |||
* - 'type' : type | |||
* - 'domain' : range [OPTIONAL] | |||
*/ | |||
void walk_ports2(const rtosc::Ports *base, | |||
char *name_buffer, | |||
size_t buffer_size, | |||
void *data, | |||
rtosc::port_walker_t walker); | |||
using std::ostream; | |||
using std::string; | |||
static int enum_min(Port::MetaContainer meta) | |||
{ | |||
int min = 0; | |||
for(auto m:meta) | |||
if(strstr(m.title, "map ")) | |||
min = atoi(m.title+4); | |||
for(auto m:meta) | |||
if(strstr(m.title, "map ")) | |||
min = min>atoi(m.title+4) ? atoi(m.title+4) : min; | |||
return min; | |||
} | |||
static int enum_max(Port::MetaContainer meta) | |||
{ | |||
int max = 0; | |||
for(auto m:meta) | |||
if(strstr(m.title, "map ")) | |||
max = atoi(m.title+4); | |||
for(auto m:meta) | |||
if(strstr(m.title, "map ")) | |||
max = max<atoi(m.title+4) ? atoi(m.title+4) : max; | |||
return max; | |||
} | |||
static ostream &add_options(ostream &o, Port::MetaContainer meta) | |||
{ | |||
string sym_names = "xyzabcdefghijklmnopqrstuvw"; | |||
int sym_idx = 0; | |||
bool has_options = false; | |||
for(auto m:meta) | |||
if(strstr(m.title, "map ")) | |||
has_options = true; | |||
for(auto m:meta) | |||
if(strcmp(m.title, "documentation") && | |||
strcmp(m.title, "parameter") && | |||
strcmp(m.title, "max") && | |||
strcmp(m.title, "min")) | |||
printf("m.title = <%s>\n", m.title); | |||
if(!has_options) | |||
return o; | |||
o << " <hints>\n"; | |||
for(auto m:meta) { | |||
if(strstr(m.title, "map ")) { | |||
o << " <point symbol=\"" << sym_names[sym_idx++] << "\" value=\""; | |||
o << m.title+4 << "\">" << m.value << "</point>\n"; | |||
} | |||
} | |||
o << " </hints>\n"; | |||
return o; | |||
} | |||
/* | |||
* parameter : | |||
* - 'path' : path-id | |||
* - 'name' : string | |||
* - 'shortname' : string [OPTIONAL] | |||
* - 'tooltip' : string [OPTIONAL] | |||
* - 'type' : type | |||
* - 'domain' : range [OPTIONAL] | |||
*/ | |||
static bool first = true; | |||
void dump_param_cb(const rtosc::Port *p, const char *name, void *v) | |||
{ | |||
std::ostream &o = *(std::ostream*)v; | |||
auto meta = p->meta(); | |||
const char *args = strchr(p->name, ':'); | |||
auto mparameter = meta.find("parameter"); | |||
auto mdoc = meta.find("documentation"); | |||
auto msname = meta.find("shortname"); | |||
string doc; | |||
//Escape Characters | |||
if(mdoc != p->meta().end()) { | |||
while(*mdoc.value) { | |||
if(*mdoc.value == '\n') | |||
doc += "\\n"; | |||
else if(*mdoc.value == '\"') | |||
doc += "\\\""; | |||
else | |||
doc += *mdoc.value; | |||
mdoc.value++; | |||
} | |||
} | |||
if(meta.find("internal") != meta.end()) | |||
return; | |||
char type = 0; | |||
if(mparameter != p->meta().end()) { | |||
if(args) { | |||
if(strchr(args, 'f')) | |||
type = 'f'; | |||
else if(strchr(args, 'i')) | |||
type = 'i'; | |||
else if(strchr(args, 'c')) | |||
type = 'c'; | |||
else if(strchr(args, 'T')) | |||
type = 't'; | |||
else if(strchr(args, 's')) | |||
type = 's'; | |||
} | |||
if(!type) { | |||
fprintf(stderr, "rtosc port dumper: Cannot handle '%s'\n", name); | |||
fprintf(stderr, " args = <%s>\n", args); | |||
return; | |||
} | |||
} else { | |||
//fprintf(stderr, "Skipping \"%s\"\n", name); | |||
//if(args) { | |||
// fprintf(stderr, " type = %s\n", args); | |||
//} | |||
return; | |||
} | |||
const char *min = meta["min"]; | |||
const char *max = meta["max"]; | |||
if(!first) | |||
o << ",\n"; | |||
else | |||
first = false; | |||
o << " {\n"; | |||
o << " \"path\" : \"" << name << "\",\n"; | |||
if(msname != meta.end()) | |||
o << " \"shortname\": \"" << msname.value << "\",\n"; | |||
o << " \"name\" : \"" << p->name << "\",\n"; | |||
o << " \"tooltip\" : \"" << doc << "\",\n"; | |||
o << " \"type\" : \"" << type << "\""; | |||
if(min && max) | |||
o << ",\n \"range\" : [" << min << "," << max << "]\n"; | |||
else | |||
o << "\n"; | |||
o << " }"; | |||
} | |||
void dump_json(std::ostream &o, const rtosc::Ports &p) | |||
{ | |||
first = true; | |||
o << "{\n"; | |||
o << " \"parameter\" : [\n"; | |||
char buffer[1024]; | |||
memset(buffer, 0, sizeof(buffer)); | |||
walk_ports2(&p, buffer, 1024, &o, dump_param_cb); | |||
o << "\n ],\n"; | |||
o << " \"actions\" : [\n"; | |||
//walk_ports2(formatter.p, buffer, 1024, &o, dump_action_cb); | |||
o << " ]\n"; | |||
o << "}"; | |||
} | |||
@@ -16,6 +16,7 @@ | |||
#include "../globals.h" | |||
#include "../Misc/Util.h" | |||
#include "../Misc/XMLwrapper.h" | |||
#include "../Misc/Time.h" | |||
#include "LFOParams.h" | |||
#include <rtosc/port-sugar.h> | |||
@@ -29,19 +30,21 @@ using namespace rtosc; | |||
static const rtosc::Ports _ports = { | |||
rSelf(LFOParams), | |||
rPaste, | |||
rParamF(Pfreq, rLinear(0.0,1.0), "frequency of LFO\n" | |||
rParamF(Pfreq, rShort("freq"), rLinear(0.0,1.0), "frequency of LFO\n" | |||
"lfo frequency = (2^(10*Pfreq)-1)/12 * stretch\n" | |||
"true frequency is [0,85.33] Hz"), | |||
rParamZyn(Pintensity, "Intensity of LFO"), | |||
rParamZyn(Pstartphase, rSpecial(random), "Starting Phase"), | |||
rOption(PLFOtype, rOptions(sine, triangle, square, ramp-up, ramp-down, | |||
rParamZyn(Pintensity, rShort("depth"), "Intensity of LFO"), | |||
rParamZyn(Pstartphase, rShort("start"), rSpecial(random), "Starting Phase"), | |||
rOption(PLFOtype, rShort("type"), rOptions(sine, triangle, square, ramp-up, ramp-down, | |||
exponential-down1, exponential-down2), "Shape of LFO"), | |||
rParamZyn(Prandomness, rSpecial(disable), "Amplitude Randomness (calculated uniformly at each cycle)"), | |||
rParamZyn(Pfreqrand, rSpecial(disable), "Frequency Randomness (calculated uniformly at each cycle)"), | |||
rParamZyn(Pdelay, rSpecial(disable), "Delay before LFO start\n" | |||
rParamZyn(Prandomness, rShort("a.r."), rSpecial(disable), | |||
"Amplitude Randomness (calculated uniformly at each cycle)"), | |||
rParamZyn(Pfreqrand, rShort("f.r."), rSpecial(disable), | |||
"Frequency Randomness (calculated uniformly at each cycle)"), | |||
rParamZyn(Pdelay, rShort("delay"), rSpecial(disable), "Delay before LFO start\n" | |||
"0..4 second delay"), | |||
rToggle(Pcontinous, "Enable for global operation"), | |||
rParamZyn(Pstretch, rCentered, "Note frequency stretch"), | |||
rToggle(Pcontinous, rShort("c"), "Enable for global operation"), | |||
rParamZyn(Pstretch, rShort("str"), rCentered, "Note frequency stretch"), | |||
}; | |||
#undef rChangeCb | |||
@@ -168,7 +168,7 @@ int main(int argc, char *argv[]) | |||
"swap", 2, NULL, 'S' | |||
}, | |||
{ | |||
"no-gui", 2, NULL, 'U' | |||
"no-gui", 0, NULL, 'U' | |||
}, | |||
{ | |||
"dummy", 2, NULL, 'Y' | |||
@@ -206,6 +206,9 @@ int main(int argc, char *argv[]) | |||
{ | |||
"dump-oscdoc", 2, NULL, 'd' | |||
}, | |||
{ | |||
"dump-json-schema", 2, NULL, 'D' | |||
}, | |||
{ | |||
"ui-title", 1, NULL, 'u' | |||
}, | |||
@@ -226,7 +229,7 @@ int main(int argc, char *argv[]) | |||
/**\todo check this process for a small memory leak*/ | |||
opt = getopt_long(argc, | |||
argv, | |||
"l:L:r:b:o:I:O:N:e:P:A:u:hvapSDUY", | |||
"l:L:r:b:o:I:O:N:e:P:A:u:D:hvapSDUY", | |||
opts, | |||
&option_index); | |||
char *optarguments = optarg; | |||
@@ -338,6 +341,15 @@ int main(int argc, char *argv[]) | |||
outfile << s; | |||
} | |||
break; | |||
case 'D': | |||
if(optarguments) | |||
{ | |||
ofstream outfile(optarguments); | |||
void dump_json(std::ostream &o, | |||
const rtosc::Ports &p); | |||
dump_json(outfile, Master::ports); | |||
} | |||
break; | |||
case 'u': | |||
if(optarguments) | |||
ui_title = optarguments; | |||
@@ -723,6 +723,11 @@ void rtosc::walk_ports(const Ports *base, | |||
void *data, | |||
port_walker_t walker) | |||
{ | |||
//only walk valid ports | |||
if(!base) | |||
return; | |||
assert(name_buffer); | |||
//XXX buffer_size is not properly handled yet | |||
if(name_buffer[0] == 0) | |||
@@ -794,6 +799,9 @@ void walk_ports2(const rtosc::Ports *base, | |||
void *data, | |||
rtosc::port_walker_t walker) | |||
{ | |||
if(!base) | |||
return; | |||
assert(name_buffer); | |||
//XXX buffer_size is not properly handled yet | |||
if(name_buffer[0] == 0) | |||
@@ -71,7 +71,6 @@ static char tmp[256]; | |||
void UndoHistoryImpl::rewind(const char *msg) | |||
{ | |||
memset(tmp, 0, sizeof(tmp)); | |||
printf("rewind('%s')\n", msg); | |||
rtosc_arg_t arg = rtosc_argument(msg,1); | |||
rtosc_amessage(tmp, 256, rtosc_argument(msg,0).s, | |||
rtosc_argument_string(msg)+2, | |||
@@ -81,9 +80,7 @@ void UndoHistoryImpl::rewind(const char *msg) | |||
void UndoHistoryImpl::replay(const char *msg) | |||
{ | |||
printf("replay...'%s'\n", msg); | |||
rtosc_arg_t arg = rtosc_argument(msg,2); | |||
printf("replay address: '%s'\n", rtosc_argument(msg, 0).s); | |||
int len = rtosc_amessage(tmp, 256, rtosc_argument(msg,0).s, | |||
rtosc_argument_string(msg)+2, | |||
&arg); | |||
@@ -141,8 +138,6 @@ void UndoHistory::seekHistory(int distance) | |||
if(!distance) | |||
return; | |||
printf("distance == '%d'\n", distance); | |||
printf("history_pos == '%ld'\n", impl->history_pos); | |||
//TODO account for traveling back in time | |||
if(distance<0) | |||
while(distance++) | |||
@@ -1,5 +1,5 @@ | |||
/* | |||
* Copyright (c) 2013 Mark McCurry | |||
* Copyright (c) 2016 Mark McCurry | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a | |||
* copy of this software and associated documentation files (the "Software"), | |||
@@ -211,6 +211,9 @@ template<class T> constexpr T spice(T*t) {return *t;} | |||
#define rOpt(numeric,symbolic) rMap(map numeric, symbolic) | |||
#define rOptions(...) OPTIONS(__VA_ARGS__) | |||
//Zest Metadata | |||
#define rShort(name) ":shortname\0=" name "\0" | |||
//Callback Implementations | |||
#define rBOIL_BEGIN [](const char *msg, rtosc::RtData &data) { \ | |||