@@ -131,25 +131,20 @@ static const Ports master_ports = { | |||
d.reply("/free", "sb", "Part", sizeof(void*), &m->part[i]); | |||
m->part[i] = p; | |||
p->initialize_rt(); | |||
//printf("part %d is now pointer %p\n", i, p); | |||
}}, | |||
{"Pvolume::i", rProp(parameter) rDoc("Master Volume"), 0, | |||
}}, | |||
{"Pvolume::i", rProp(parameter) rLinear(0,127) rDoc("Master Volume"), 0, | |||
[](const char *m, rtosc::RtData &d) { | |||
if(rtosc_narguments(m)==0) { | |||
d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume); | |||
} else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') { | |||
((Master*)d.obj)->setPvolume(limit<char>(rtosc_argument(m,0).i,0,127)); | |||
d.broadcast(d.loc, "i", ((Master*)d.obj)->Pvolume);}}}, | |||
{"volume::i", rProp(parameter) rDoc("Master Volume"), 0, | |||
{"volume::i", rProp(parameter) rLinear(0,127) rDoc("Master Volume"), 0, | |||
[](const char *m, rtosc::RtData &d) { | |||
if(rtosc_narguments(m)==0) { | |||
d.reply(d.loc, "i", ((Master*)d.obj)->Pvolume); | |||
} else if(rtosc_narguments(m)==1 && rtosc_type(m,0)=='i') { | |||
//printf("looking at value %d\n", rtosc_argument(m,0).i); | |||
//printf("limited value is %d\n", limit<char>( | |||
// rtosc_argument(m,0).i, 0,127)); | |||
((Master*)d.obj)->setPvolume(limit<char>(rtosc_argument(m,0).i,0,127)); | |||
//printf("sets volume to value %d\n", ((Master*)d.obj)->Pvolume); | |||
d.broadcast(d.loc, "i", ((Master*)d.obj)->Pvolume);}}}, | |||
{"Psysefxvol#" STRINGIFY(NUM_SYS_EFX) "/::i", 0, &sysefxPort, | |||
[](const char *msg, rtosc::RtData &d) { | |||
@@ -176,18 +171,21 @@ static const Ports master_ports = { | |||
[](const char *m,RtData &d){ | |||
Master *M = (Master*)d.obj; | |||
M->setController(rtosc_argument(m,0).i,rtosc_argument(m,1).i,rtosc_argument(m,2).i);}}, | |||
{"Panic:", rDoc("Stop All Sound"), 0, | |||
{"Panic:", rDoc("Stop all sound"), 0, | |||
[](const char *, RtData &d) { | |||
Master &M = *(Master*)d.obj; | |||
M.ShutUp(); | |||
}}, | |||
{"freeze_state:", rDoc("Internal Read-only Mode"), 0, | |||
{"freeze_state:", rProp(internal) rDoc("Disable OSC event handling\n" | |||
"This sets up a read-only mode from which it's safe for another" | |||
" thread to save parameters"), 0, | |||
[](const char *,RtData &d) { | |||
Master *M = (Master*)d.obj; | |||
std::atomic_thread_fence(std::memory_order_release); | |||
M->frozenState = true; | |||
d.reply("/state_frozen", "");}}, | |||
{"thaw_state:", rDoc("Internal Read-only Mode"), 0, | |||
{"thaw_state:", rProp(internal) rDoc("Resume handling OSC messages\n" | |||
"See /freeze_state for more information"), 0, | |||
[](const char *,RtData &d) { | |||
Master *M = (Master*)d.obj; | |||
M->frozenState = false;}}, | |||
@@ -216,11 +214,11 @@ static const Ports master_ports = { | |||
m.memory->addMemory(mem, i); | |||
m.pendingMemory = false; | |||
}}, | |||
{"samplerate:", rMap(unit, Hz) rDoc("Synthesizer Global Sample Rate"), 0, [](const char *, RtData &d) { | |||
{"samplerate:", rMap(unit, Hz) rDoc("Get synthesizer sample rate"), 0, [](const char *, RtData &d) { | |||
Master &m = *(Master*)d.obj; | |||
d.reply("/samplerate", "f", m.synth.samplerate_f); | |||
}}, | |||
{"oscilsize:", rDoc("Synthesizer Global Oscillator Size"), 0, [](const char *, RtData &d) { | |||
{"oscilsize:", rDoc("Get synthesizer oscillator size"), 0, [](const char *, RtData &d) { | |||
Master &m = *(Master*)d.obj; | |||
d.reply("/oscilsize", "f", m.synth.oscilsize_f); | |||
d.reply("/oscilsize", "i", m.synth.oscilsize); | |||
@@ -639,7 +637,7 @@ void Master::AudioOut(float *outl, float *outr) | |||
DataObj d{loc_buf, 1024, this, bToU}; | |||
memset(loc_buf, 0, sizeof(loc_buf)); | |||
int events = 0; | |||
while(uToB && uToB->hasNext() && events < 10) { | |||
while(uToB && uToB->hasNext() && events < 100) { | |||
const char *msg = uToB->read(); | |||
if(!strcmp(msg, "/load-master")) { | |||
@@ -58,10 +58,10 @@ const rtosc::Ports Microtonal::ports = { | |||
rParamZyn(Pmiddlenote, "Scale degree 0 note"), | |||
//TODO check to see if this should be exposed | |||
rParamZyn(Pmapsize, "UNDOCUMENTED"), | |||
rParamZyn(Pmapsize, "Size of key map"), | |||
rToggle(Pmappingenabled, "Mapping Enable"), | |||
rParams(Pmapping, "UNDOCUMENTED"), | |||
rParams(Pmapping, 128, "Mapping of keys"), | |||
rParamZyn(Pglobalfinedetune, "Fine detune for all notes"), | |||
rString(Pname, MICROTONAL_MAX_NAME_LEN, "Microtonal Name"), | |||
@@ -71,16 +71,18 @@ static const Ports partPorts = { | |||
rParamZyn(Pvelsns, "Velocity sensing"), | |||
rParamZyn(Pveloffs, "Velocity offset"), | |||
rToggle(Pnoteon, "If the channel accepts note on events"), | |||
//TODO FIXME Change to 0=OFF 1=MULTI 2=SINGLE | |||
rParamI(Pkitmode, "Kit mode enable"), | |||
rOption(Pkitmode, rOptions(Off, Multi-Kit, Single-Kit), "Kit mode/enable\n" | |||
"Off - Only the first kit is ever utilized\n" | |||
"Multi-kit - Every applicable kit is run for a note\n" | |||
"Single-kit - The first applicable kit is run for a given note"), | |||
rToggle(Pdrummode, "Drum mode enable\n" | |||
"When drum mode is enabled all keys are mapped to 12tET and legato is disabled"), | |||
rToggle(Ppolymode, "Polyphoney mode"), | |||
rToggle(Plegatomode, "Legato enable"), | |||
rToggle(Ppolymode, "Polyphony mode"), | |||
rToggle(Plegatomode, "Legato mode"), | |||
rParamZyn(info.Ptype, "Class of Instrument"), | |||
rString(info.Pauthor, MAX_INFO_TEXT_SIZE, "Instrument Author"), | |||
rString(info.Pcomments, MAX_INFO_TEXT_SIZE, "Instrument Comments"), | |||
rString(Pname, PART_MAX_NAME_LEN, "Kit User Specified Label"), | |||
rString(info.Pauthor, MAX_INFO_TEXT_SIZE, "Instrument author"), | |||
rString(info.Pcomments, MAX_INFO_TEXT_SIZE, "Instrument comments"), | |||
rString(Pname, PART_MAX_NAME_LEN, "User specified label"), | |||
rArray(Pefxroute, NUM_PART_EFX, "Effect Routing"), | |||
rArrayT(Pefxbypass, NUM_PART_EFX, "If an effect is bypassed"), | |||
{"captureMin:", rDoc("Capture minimum valid note"), NULL, | |||
@@ -90,7 +92,13 @@ static const Ports partPorts = { | |||
[](const char *, RtData &r) | |||
{Part *p = (Part*)r.obj; p->Pmaxkey = p->lastnote;}}, | |||
{"polyType::c:i", rProp(parameter) rOptions(Polyphonic, Monophonic, Legato) | |||
rDoc("synthesis polyphony type"), NULL, | |||
rDoc("Synthesis polyphony type\n" | |||
"Polyphonic - Each note is played independently\n" | |||
"Monophonic - A single note is played at a time with" | |||
" envelopes resetting between notes\n" | |||
"Legato - A single note is played at a time without" | |||
" envelopes resetting between notes\n" | |||
), NULL, | |||
[](const char *msg, RtData &d) | |||
{ | |||
Part *p = (Part*)d.obj; | |||
@@ -188,8 +196,6 @@ static const Ports kitPorts = { | |||
assert(o.subpars == NULL); | |||
o.subpars = *(decltype(o.subpars)*)rtosc_argument(msg, 0).b.data; | |||
}}, | |||
// []( | |||
}; | |||
const Ports &Part::Kit::ports = kitPorts; | |||
@@ -95,7 +95,8 @@ static const Ports voicePorts = { | |||
//Modulator Stuff | |||
rParamZyn(PFMEnabled, "Modulator Enable/Type"), | |||
rOption(PFMEnabled, rOptions(none, morph, ring modulation, phase modulation, | |||
frequency modulation, pitch modulation), "Modulator mode"), | |||
rParamI(PFMVoice, "Modulator Oscillator Selection"), | |||
rParamZyn(PFMVolume, "Modulator Magnitude"), | |||
rParamZyn(PFMVolumeDamp, "Modulator HF dampening"), | |||
@@ -36,13 +36,17 @@ using namespace rtosc; | |||
static const rtosc::Ports _ports = { | |||
rSelf(LFOParams), | |||
rPaste, | |||
rParamF(Pfreq, "frequency of LFO"), | |||
rParamF(Pfreq, 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,"Shape of LFO"), | |||
rParamZyn(Prandomness, rSpecial(disable), "Amplitude Randomness"), | |||
rParamZyn(Pfreqrand, rSpecial(disable), "Frequency Randomness"), | |||
rParamZyn(Pdelay, rSpecial(disable), "Delay before LFO start"), | |||
rOption(PLFOtype, 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" | |||
"0..4 second delay"), | |||
rToggle(Pcontinous, "Enable for global operation"), | |||
rParamZyn(Pstretch, rCentered, "Note frequency stretch"), | |||
}; | |||
@@ -90,7 +90,7 @@ class PhaseSlider {: {public Fl_Osc_TSlider} | |||
setRounding(1); | |||
reset_value=0; | |||
setTransform(180.0/64, 0); | |||
}} | |||
} {}} | |||
Function {OSC_value(int i)} {open return_type void | |||
} { code { | |||
value(64-i); | |||
@@ -277,7 +277,7 @@ void BankView::react(int event, int nslot) | |||
} | |||
//Reads from slot | |||
if ((event==1)&&(mode==1)&&(!slot.empty())){ | |||
if ((event==1)&&(mode==1) && !isempty){ | |||
printf("Loading a part #%d with file '%s'\n", nslot, slot.filename()); | |||
osc->write("/load-part", "is", *npart, slot.filename()); | |||
osc->writeValue("/part"+to_s(*npart)+"/name", slot.name()); | |||
@@ -287,25 +287,23 @@ void BankView::react(int event, int nslot) | |||
//save(write) to slot | |||
if(event==1 && mode==2){ | |||
if(!isempty && !fl_choice("Overwrite the slot no. %d ?","No","Yes",NULL,nslot+1)) | |||
return; | |||
osc->write("/save-bank-part", "ii", *npart, nslot); | |||
osc->write("/refresh_bank", "i", nslot); | |||
//pthread_mutex_lock(&master->part[*npart]->load_mutex); | |||
//bank->savetoslot(slot,master->part[*npart]); | |||
//pthread_mutex_unlock(&master->part[*npart]->load_mutex); | |||
if(isempty || | |||
fl_choice("Overwrite the slot no. %d ?","No","Yes",NULL,nslot+1)) { | |||
osc->write("/save-bank-part", "ii", *npart, nslot); | |||
osc->write("/refresh_bank", "i", nslot); | |||
} | |||
bvc->mode(1); | |||
} | |||
//Clears the slot | |||
if(event==1 && mode==3 && !isempty) { | |||
if (fl_choice("Clear the slot no. %d ?","No","Yes",NULL, nslot+1)) { | |||
if(event==1 && mode==3) { | |||
if (!isempty && | |||
fl_choice("Clear the slot no. %d ?","No","Yes",NULL, nslot+1)) { | |||
osc->write("/clear-bank-slot", "i", nslot); | |||
osc->write("/refresh_bank", "i", nslot); | |||
} | |||
bvc->mode(1); | |||
} | |||
//Swap | |||
@@ -314,7 +312,6 @@ void BankView::react(int event, int nslot) | |||
osc->write("/swap-bank-slots", "ii", nselected, nslot); | |||
osc->write("/refresh_bank", "i", nslot); | |||
osc->write("/refresh_bank", "i", nselected); | |||
//bank->swapslot(nselected,slot); | |||
nselected=-1; | |||
} else if(nselected<0 || event==2) { | |||
nselected=nslot; | |||
@@ -106,7 +106,7 @@ int Fl_Osc_Slider::handle(int ev, int X, int Y, int W, int H) | |||
if (step < 1) | |||
step = 1; | |||
} | |||
int dy = minimum() <= maximum() ? Fl::e_dy : -Fl::e_dy; | |||
int dy = minimum() <= maximum() ? -Fl::e_dy : Fl::e_dy; | |||
handle_drag(clamp(value() + step * dy)); | |||
} | |||
return 1; | |||
@@ -136,18 +136,23 @@ maxkcounter->do_callback();} | |||
} | |||
Fl_Button adeditbutton { | |||
label edit | |||
callback {partui->showparameters(n,0);} | |||
callback { | |||
if (Fl::event_shift()) { | |||
partui->showvoiceparams(n, true); | |||
} else if (Fl::event_ctrl()) { | |||
partui->showvoiceparams(n, false); | |||
} else | |||
partui->showparameters(n,0); | |||
} | |||
xywh {420 0 40 15} box THIN_UP_BOX labelsize 11 | |||
code1 {if (n==0) o->hide();} | |||
} | |||
Fl_Button subeditbutton { | |||
label edit | |||
callback {partui->showparameters(n,1);} | |||
xywh {490 0 40 15} box THIN_UP_BOX labelsize 11 | |||
code1 {if (n==0) o->hide();} | |||
} | |||
Fl_Check_Button mutedcheck { | |||
private xywh {60 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 | |||
public xywh {60 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 | |||
code0 {o->init("Pmuted");} | |||
class Fl_Osc_Check | |||
} | |||
@@ -167,7 +172,6 @@ maxkcounter->do_callback();} | |||
else adeditbutton->deactivate();} | |||
private xywh {400 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 | |||
code0 {o->init("Padenabled");} | |||
code1 {if (n==0) o->hide();} | |||
class Fl_Osc_Check | |||
} | |||
Fl_Check_Button subcheck { | |||
@@ -175,7 +179,6 @@ maxkcounter->do_callback();} | |||
else subeditbutton->deactivate();} | |||
private xywh {470 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 | |||
code0 {o->init("Psubenabled");} | |||
code1 {if (n==0) o->hide();} | |||
class Fl_Osc_Check | |||
} | |||
Fl_Choice sendtoeffect { | |||
@@ -188,14 +191,12 @@ maxkcounter->do_callback();} | |||
label edit | |||
callback {partui->showparameters(n,2);} | |||
xywh {560 0 40 15} box THIN_UP_BOX labelsize 11 | |||
code1 {if (n==0) o->hide();} | |||
} | |||
Fl_Check_Button padcheck { | |||
callback {if (o->value()!=0) padeditbutton->activate(); | |||
else padeditbutton->deactivate();} | |||
private xywh {540 0 20 15} down_box DOWN_BOX labelfont 1 labelsize 11 align 4 | |||
code0 {o->init("Ppadenabled");} | |||
code1 {if (n==0) o->hide();} | |||
class Fl_Osc_Check | |||
} | |||
} | |||
@@ -231,6 +232,11 @@ partui->showparameters(n,-1);//use to delete the ui, if it is not to item 0} | |||
ext = "kit"+to_s(n)+"/"; | |||
partui=partui_; | |||
make_window(); | |||
if (n == 0) | |||
mutedcheck->deactivate(); | |||
else | |||
deactivate(); | |||
//partkititem->show(); | |||
end();} {} | |||
} | |||
@@ -353,7 +359,12 @@ if (event==FL_RIGHT_MOUSE){ | |||
} | |||
Fl_Button {} { | |||
label {Edit instrument} | |||
callback {instrumenteditwindow->show();} | |||
callback { | |||
if (Fl::event_shift() || Fl::event_ctrl()) | |||
instrumentkitlist->show(); | |||
else | |||
instrumenteditwindow->show(); | |||
} | |||
xywh {15 90 130 30} color 52 labelfont 1 labelsize 13 | |||
} | |||
Fl_Button {} { | |||
@@ -745,7 +756,7 @@ if (x==2) part->partefx[ninseff]->setdryonly(true); | |||
Fl_Button {} { | |||
label {Close Window} | |||
callback {instrumentkitlist->hide();} | |||
xywh {375 350 160 20} box THIN_UP_BOX | |||
xywh {255 350 160 20} box THIN_UP_BOX | |||
} | |||
Fl_Scroll kitlist {open | |||
xywh {0 15 670 330} type VERTICAL box UP_FRAME | |||
@@ -781,7 +792,14 @@ if (x==2) part->partefx[ninseff]->setdryonly(true); | |||
} | |||
Fl_Choice {} { | |||
label Mode | |||
callback {if (o->value()==0) { kitlist->deactivate(); } else { kitlist->activate(); };} | |||
callback {if (o->value()==0) { | |||
for (int i=1;i<NUM_KIT_ITEMS;i++) | |||
partkititem[i]->deactivate(); | |||
partkititem[0]->mutedcheck->deactivate(); | |||
} else { | |||
for (int i=1;i<NUM_KIT_ITEMS;i++) | |||
partkititem[i]->activate(); | |||
partkititem[0]->mutedcheck->activate(); };} | |||
xywh {35 350 70 15} down_box BORDER_BOX labelsize 11 textfont 1 textsize 11 | |||
code0 {o->init("Pkitmode");} | |||
class Fl_Osc_Choice | |||
@@ -801,10 +819,21 @@ if (x==2) part->partefx[ninseff]->setdryonly(true); | |||
} | |||
Fl_Check_Button {} { | |||
label {Drum mode} | |||
xywh {285 350 70 15} down_box DOWN_BOX labelsize 10 | |||
xywh {125 350 80 15} down_box DOWN_BOX labelsize 10 | |||
code0 {o->init("Pdrummode");} | |||
class Fl_Osc_Check | |||
} | |||
Fl_Button {} { | |||
label Comments | |||
callback {instrumenteditwindow->show();} | |||
xywh {481 350 106 20} box THIN_UP_BOX | |||
} | |||
Fl_Button {} { | |||
label Effects | |||
callback {partfx->show();} selected | |||
xywh {600 350 70 20} box THIN_UP_BOX | |||
} | |||
Fl_Box {} { | |||
label {FX.r.} | |||
xywh {620 0 30 15} labelfont 1 labelsize 11 align 18 | |||
@@ -863,7 +892,14 @@ if (x==2) part->partefx[ninseff]->setdryonly(true); | |||
} | |||
Fl_Button adeditbutton { | |||
label Edit | |||
callback {showparameters(0,0);} | |||
callback { | |||
if (Fl::event_shift()) { | |||
showvoiceparams(0, true); | |||
} else if (Fl::event_ctrl()) { | |||
showvoiceparams(0, false); | |||
} else | |||
showparameters(0,0); | |||
} | |||
xywh {15 281 80 34} color 51 selection_color 51 labelfont 1 labelsize 13 align 128 | |||
} | |||
} | |||
@@ -1030,6 +1066,23 @@ end(); | |||
//if (config.ui.showinstrumentinfo!=0) instrumenteditwindow->show(); | |||
} {} | |||
} | |||
Function {cleanuplastkit(int kititem)} {open return_type int | |||
} { | |||
code { | |||
if (kititem==lastkititem) | |||
return 0; | |||
delete adnoteui; | |||
delete subnoteui; | |||
delete padnoteui; | |||
adnoteui=NULL;subnoteui=NULL;padnoteui=NULL; | |||
lastkititem=kititem; | |||
if(kititem>=NUM_KIT_ITEMS) return 1;//bad kit item | |||
if(kititem<0) return 1; | |||
return 0; | |||
} {}} | |||
Function {showparameters(int kititem,int engine)} {open | |||
} { | |||
code { | |||
@@ -1043,16 +1096,8 @@ if (engine==-1){//this is used if I want to clear the engine from the part | |||
return; | |||
} | |||
if (kititem!=lastkititem){ | |||
delete adnoteui; | |||
delete subnoteui; | |||
delete padnoteui; | |||
adnoteui=NULL;subnoteui=NULL;padnoteui=NULL; | |||
lastkititem=kititem; | |||
if(kititem>=NUM_KIT_ITEMS) return;//bad kit item | |||
if(kititem<0) return; | |||
} | |||
if (cleanuplastkit(kititem)) | |||
return; | |||
if(!adnoteui && engine==0)//adsynenabledcheck->value()) | |||
adnoteui=new ADnoteUI(loc+"kit"+to_s(kititem)+"/adpars/", osc); | |||
@@ -1067,6 +1112,23 @@ if (engine==0&&adnoteui) adnoteui->ADnoteGlobalParameters->show(); | |||
if (engine==1&&subnoteui) subnoteui->SUBparameters->show(); | |||
if (engine==2&&padnoteui) padnoteui->padnotewindow->show();} {} | |||
} | |||
Function {showvoiceparams(int kititem, bool voicelist)} {open | |||
} { | |||
code { | |||
if (cleanuplastkit(kititem)) | |||
return; | |||
if(adnoteui || | |||
(adnoteui=new ADnoteUI(loc+"kit"+to_s(kititem)+"/adpars/", osc))) | |||
if(voicelist) | |||
adnoteui->ADnoteVoiceList->show(); | |||
else { | |||
if (adnoteui->advoice->mod_type->value() == 0) | |||
adnoteui->advoice->voiceFMparametersgroup->deactivate(); | |||
else | |||
adnoteui->advoice->voiceFMparametersgroup->activate(); | |||
adnoteui->ADnoteVoice->show(); | |||
}} {}} | |||
Function {~PartUI()} {} { | |||
code {delete adnoteui; | |||
delete subnoteui; | |||
@@ -48,7 +48,7 @@ class SUBSlider {: {public Fl_Osc_TSlider} | |||
} { | |||
Function {SUBSlider(int x,int y, int w, int h, const char *label=0) | |||
:Fl_Osc_TSlider(x,y,w,h,label)} {open | |||
} { code {}} | |||
} { code {} {}} | |||
Function {OSC_value(char c)} {open return_type void | |||
} { code { | |||
value(127-c); | |||
@@ -41,6 +41,7 @@ int WidgetPDial::handle(int event) | |||
if (event == FL_RELEASE && Fl::event_clicks() == 1) { | |||
Fl::event_clicks(0); | |||
value(reset_value); | |||
tipwin->hide(); | |||
value_damage(); | |||
if (this->when() != 0) | |||
do_callback(); | |||
@@ -791,6 +791,63 @@ static void units(std::ostream &o, const char *u) | |||
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; | |||
} | |||
static ostream &dump_t_f_port(ostream &o, string name, string doc) | |||
{ | |||
o << " <message_in pattern=\"" << name << "\" typetag=\"T\">\n"; | |||
@@ -899,6 +956,13 @@ void dump_ports_cb(const rtosc::Port *p, const char *name, void *v) | |||
o << " <range_min_max " << (type == 'f' ? "lmin=\"[\" lmax=\"]\"" : ""); | |||
o << " min=\"" << meta["min"] << "\" max=\"" << meta["max"] << "\"/>\n"; | |||
o << " </param_" << type << ">"; | |||
} else if(meta.find("enumerated") != meta.end()) { | |||
o << " <param_" << type << " symbol=\"x\">\n"; | |||
o << " <range_min_max min=\"" << enum_min(meta) << "\" max=\""; | |||
o << enum_max(meta) << "\">\n"; | |||
add_options(o, meta); | |||
o << " </range_min_max>\n"; | |||
o << " </param_" << type << ">\n"; | |||
} else { | |||
o << " <param_" << type << " symbol=\"x\""; | |||
units(o, meta["unit"]); | |||
@@ -917,6 +981,13 @@ void dump_ports_cb(const rtosc::Port *p, const char *name, void *v) | |||
o << " <range_min_max " << (type == 'f' ? "lmin=\"[\" lmax=\"]\"" : ""); | |||
o << " min=\"" << meta["min"] << "\" max=\"" << meta["max"] << "\"/>\n"; | |||
o << " </param_" << type << ">\n"; | |||
} else if(meta.find("enumerated") != meta.end()) { | |||
o << " <param_" << type << " symbol=\"x\">\n"; | |||
o << " <range_min_max min=\"" << enum_min(meta) << "\" max=\""; | |||
o << enum_max(meta) << "\">\n"; | |||
add_options(o, meta); | |||
o << " </range_min_max>\n"; | |||
o << " </param_" << type << ">\n"; | |||
} else { | |||
o << " <param_" << type << " symbol=\"x\""; | |||
units(o, meta["unit"]); | |||
@@ -138,7 +138,7 @@ struct rtosc_hack_decltype_t | |||
#define rToggle(name, ...) \ | |||
{STRINGIFY(name) "::T:F",rProp(parameter) DOC(__VA_ARGS__), NULL, rToggleCb(name)} | |||
#define rOption(name, ...) \ | |||
{STRINGIFY(name) "::i:c",rProp(parameter) DOC(__VA_ARGS__), NULL, rOptionCb(name)} | |||
{STRINGIFY(name) "::i:c",rProp(parameter) rProp(enumerated) DOC(__VA_ARGS__), NULL, rOptionCb(name)} | |||
//Array operators | |||
#define rArrayF(name, length, ...) \ | |||