commit 5c34e0a67e235d885c5d328c37e1374ea79d8aa4
parent 515fde8af546f5d93a258a71fe04f1b8ac9ce17d
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Sat, 31 Oct 2015 14:03:18 -0400
Initial Refactor Of OSC Message Flow In MW
- Start to encoperate forwarded messages
- Start to split dispatch tables for oscilgen and padsynth
- Introduce a test for the flow of these messages
Diffstat:
11 files changed, 785 insertions(+), 561 deletions(-)
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -228,7 +228,7 @@ static const Ports master_ports = {
{"undo_resume:",rProp(internal) rDoc("resume undo event recording"),0,
[](const char *, rtosc::RtData &d) {d.reply("/undo_resume", "");}},
{"config/", rDoc("Top Level Application Configuration Parameters"), &Config::ports,
- [](const char *, rtosc::RtData &){}},
+ [](const char *, rtosc::RtData &d){d.forward();}},
{"presets/", rDoc("Parameter Presets"), &preset_ports, rBOIL_BEGIN
SNIP
preset_ports.dispatch(msg, data);
@@ -252,6 +252,7 @@ class DataObj:public rtosc::RtData
loc_size = loc_size_;
obj = obj_;
bToU = bToU_;
+ forwarded = false;
}
virtual void reply(const char *path, const char *args, ...) override
@@ -280,9 +281,18 @@ class DataObj:public rtosc::RtData
}
virtual void broadcast(const char *msg) override
{
- reply("/broadcast");
+ reply("/broadcast", "");
reply(msg);
- };
+ }
+
+ virtual void forward(const char *reason) override
+ {
+ assert(message);
+ reply("/forward", "");
+ printf("forwarding '%s'\n", message);
+ forwarded = true;
+ }
+ bool forwarded;
private:
rtosc::ThreadLink *bToU;
};
@@ -341,7 +351,7 @@ Master::Master(const SYNTH_T &synth_, Config* config)
DataObj d{loc_buf, 1024, the_master, the_bToU};
memset(loc_buf, 0, sizeof(loc_buf));
//printf("sending an event to the owner of '%s'\n", m);
- Master::ports.dispatch(m+1, d);
+ Master::ports.dispatch(m, d, true);
};
#else
midi.event_cb = [](const char *) {};
@@ -362,8 +372,8 @@ void Master::applyOscEvent(const char *msg)
DataObj d{loc_buf, 1024, this, bToU};
memset(loc_buf, 0, sizeof(loc_buf));
d.matches = 0;
- ports.dispatch(msg+1, d);
- if(d.matches == 0)
+ ports.dispatch(msg, d, true);
+ if(d.matches == 0 || d.forwarded)
fprintf(stderr, "Unknown path '%s'\n", msg);
}
@@ -658,9 +668,7 @@ void Master::AudioOut(float *outl, float *outr)
rtosc_argument_string(msg));
fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
}
- d.matches = 0;
- //fprintf(stdout, "address '%s'\n", uToB->peak());
- ports.dispatch(msg+1, d);
+ ports.dispatch(msg, d, true);
events++;
if(!d.matches) {// && !ports.apropos(msg)) {
fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp
@@ -189,101 +189,36 @@ void preparePadSynth(string path, PADnoteParameters *p, rtosc::ThreadLink *uToB)
}
}
-/*****************************************************************************
- * Instrument Banks *
- * *
- * Banks and presets in general are not classed as realtime safe *
- * *
- * The supported operations are: *
- * - Load Names *
- * - Load Bank *
- * - Refresh List of Banks *
- *****************************************************************************/
-void refreshBankView(const Bank &bank, unsigned loc, std::function<void(const char*)> cb)
-{
- if(loc >= BANK_SIZE)
- return;
-
- char response[2048];
- if(!rtosc_message(response, 1024, "/bankview", "iss",
- loc, bank.ins[loc].name.c_str(),
- bank.ins[loc].filename.c_str()))
- errx(1, "Failure to handle bank update properly...");
-
-
- if(cb)
- cb(response);
-}
-
-void bankList(Bank &bank, std::function<void(const char*)> cb)
-{
- char response[2048];
- int i = 0;
-
- for(auto &elm : bank.banks) {
- if(!rtosc_message(response, 2048, "/bank-list", "iss",
- i++, elm.name.c_str(), elm.dir.c_str()))
- errx(1, "Failure to handle bank update properly...");
- if(cb)
- cb(response);
- }
-}
-
-void rescanForBanks(Bank &bank, std::function<void(const char*)> cb)
-{
- bank.rescanforbanks();
- bankList(bank, cb);
-}
-
-void loadBank(Bank &bank, int pos, std::function<void(const char*)> cb)
-{
- char response[2048];
- if(!rtosc_message(response, 2048, "/loadbank", "i", pos))
- errx(1, "Failure to handle bank update properly...");
- if(cb)
- cb(response);
- if(bank.bankpos != pos) {
- bank.bankpos = pos;
- bank.loadbank(bank.banks[pos].dir);
- for(int i=0; i<BANK_SIZE; ++i)
- refreshBankView(bank, i, cb);
- }
-}
-
-void bankPos(Bank &bank, std::function<void(const char *)> cb)
-{
- char response[2048];
-
- if(!rtosc_message(response, 2048, "/loadbank", "i", bank.bankpos))
- errx(1, "Failure to handle bank update properly...");
- if(cb)
- cb(response);
-}
/*****************************************************************************
* Data Object for Non-RT Class Dispatch *
*****************************************************************************/
-class DummyDataObj:public rtosc::RtData
+class MwDataObj:public rtosc::RtData
{
public:
- DummyDataObj(char *loc_, size_t loc_size_, void *obj_, MiddleWareImpl *mwi_,
- rtosc::ThreadLink *uToB_)
+ MwDataObj(MiddleWareImpl *mwi_)
{
- memset(loc_, 0, sizeof(loc_size_));
+ loc_size = 1024;
+ loc = new char[loc_size];
+ memset(loc, 0, loc_size);
buffer = new char[4*4096];
memset(buffer, 0, 4*4096);
- loc = loc_;
- loc_size = loc_size_;
- obj = obj_;
- mwi = mwi_;
- uToB = uToB_;
+ obj = mwi_;
+ mwi = mwi_;
+ forwarded = false;
}
- ~DummyDataObj(void)
+
+ ~MwDataObj(void)
{
delete[] buffer;
}
+ //Replies and broadcasts go to the remote
+
+ //Chain calls repeat the call into handle()
+
+ //Forward calls send the message directly to the realtime
virtual void reply(const char *path, const char *args, ...)
{
//printf("reply building '%s'\n", path);
@@ -292,26 +227,26 @@ class DummyDataObj:public rtosc::RtData
if(!strcmp(path, "/forward")) { //forward the information to the backend
args++;
path = va_arg(va, const char *);
- //fprintf(stderr, "forwarding information to the backend on '%s'<%s>\n",
- // path, args);
rtosc_vmessage(buffer,4*4096,path,args,va);
- uToB->raw_write(buffer);
} else {
- //printf("path = '%s' args = '%s'\n", path, args);
- //printf("buffer = '%p'\n", buffer);
rtosc_vmessage(buffer,4*4096,path,args,va);
- //printf("buffer = '%s'\n", buffer);
reply(buffer);
}
va_end(va);
}
- virtual void reply(const char *msg);
+ virtual void reply(const char *msg){};
//virtual void broadcast(const char *path, const char *args, ...){(void)path;(void)args;};
//virtual void broadcast(const char *msg){(void)msg;};
+
+ virtual void forward(const char *) override
+ {
+ forwarded = true;
+ }
+
+ bool forwarded;
private:
char *buffer;
MiddleWareImpl *mwi;
- rtosc::ThreadLink *uToB;
};
@@ -393,6 +328,25 @@ struct NonRtObjStore
{
return objmap[loc];
}
+
+ void handleOscil(const char *msg, rtosc::RtData &d) {
+ }
+ void handlePad(const char *msg, rtosc::RtData &d) {
+ }
+#if 0
+ if(strstr(msg, "oscilgen/") || strstr(msg, "FMSmp/") || strstr(msg, "OscilSmp/")) {
+ if(!handleOscil(obj_rl, last_path+1, obj_store.get(obj_rl)))
+ uToB->raw_write(msg);
+ //else if(strstr(obj_rl.c_str(), "kititem"))
+ // handleKitItem(obj_rl, objmap[obj_rl],atoi(rindex(msg,'m')+1),rtosc_argument(msg,0).T);
+ } else if(strstr(msg, "padpars/prepare"))
+ preparePadSynth(obj_rl,(PADnoteParameters *) obj_store.get(obj_rl), uToB);
+ else if(strstr(msg, "padpars")) {
+ if(!handlePAD(obj_rl, last_path+1, obj_store.get(obj_rl)))
+ uToB->raw_write(msg);
+ } else //just forward the message
+ uToB->raw_write(msg);
+#endif
};
/******************************************************************************
@@ -467,7 +421,9 @@ namespace Nio
/* Implementation */
class MiddleWareImpl : TmpFileMgr
{
+ public:
MiddleWare *parent;
+ private:
//Detect if the name of the process is 'zynaddsubfx'
bool isPlugin() const
@@ -489,69 +445,9 @@ public:
int preferred_port);
~MiddleWareImpl(void);
- void warnMemoryLeaks(void);
-
//Apply function while parameters are write locked
void doReadOnlyOp(std::function<void()> read_only_fn);
-
- void saveBankSlot(int npart, int nslot, Master *master)
- {
- int err = 0;
- doReadOnlyOp([master,nslot,npart,&err](){
- err = master->bank.savetoslot(nslot, master->part[npart]);});
- if(err) {
- char buffer[1024];
- rtosc_message(buffer, 1024, "/alert", "s",
- "Failed To Save To Bank Slot, please check file permissions");
- GUI::raiseUi(ui, buffer);
- }
- }
-
- void renameBankSlot(int slot, string name, Master *master)
- {
- int err = master->bank.setname(slot, name, -1);
- if(err) {
- char buffer[1024];
- rtosc_message(buffer, 1024, "/alert", "s",
- "Failed To Rename Bank Slot, please check file permissions");
- GUI::raiseUi(ui, buffer);
- }
- }
-
- void swapBankSlot(int slota, int slotb, Master *master)
- {
- int err = master->bank.swapslot(slota, slotb);
- if(err) {
- char buffer[1024];
- rtosc_message(buffer, 1024, "/alert", "s",
- "Failed To Swap Bank Slots, please check file permissions");
- GUI::raiseUi(ui, buffer);
- }
- }
-
- void clearBankSlot(int slot, Master *master)
- {
- int err = master->bank.clearslot(slot);
- if(err) {
- char buffer[1024];
- rtosc_message(buffer, 1024, "/alert", "s",
- "Failed To Clear Bank Slot, please check file permissions");
- GUI::raiseUi(ui, buffer);
- }
- }
-
- void saveMaster(const char *filename)
- {
- //Copy is needed as filename WILL get trashed during the rest of the run
- std::string fname = filename;
- //printf("saving master('%s')\n", filename);
- doReadOnlyOp([this,fname](){
- int res = master->saveXML(fname.c_str());
- (void)res;
- /*printf("results: '%s' '%d'\n",fname.c_str(), res);*/});
- }
-
void savePart(int npart, const char *filename)
{
//Copy is needed as filename WILL get trashed during the rest of the run
@@ -647,8 +543,6 @@ public:
//deallocation
uToB->write("/load-part", "ib", npart, sizeof(Part*), &p);
GUI::raiseUi(ui, "/damage", "s", ("/part"+to_s(npart)+"/").c_str());
- //if(osc)
- // osc->damage(("/part"+to_s(npart)+"/").c_str());
}
//Well, you don't get much crazier than changing out all of your RT
@@ -686,9 +580,10 @@ public:
//If currently broadcasting messages
bool broadcast = false;
+ bool forward = false;
//If accepting undo events as user driven
bool recording_undo = true;
- void bToUhandle(const char *rtmsg, bool dummy=false);
+ void bToUhandle(const char *rtmsg);
void tick(void)
{
@@ -700,86 +595,6 @@ public:
}
}
- bool handlePAD(string path, const char *msg, void *v)
- {
- if(!v)
- return true;
- char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- DummyDataObj d(buffer, 1024, v, this, uToB);
- strcpy(buffer, path.c_str());
-
- PADnoteParameters::ports.dispatch(msg, d);
- if(!d.matches) {
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
- fprintf(stderr, "Unknown location '%s%s'<%s>\n",
- path.c_str(), msg, rtosc_argument_string(msg));
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
- }
-
- return true;
- }
-
- void handlePresets(const char *msg)
- {
- char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- DummyDataObj d(buffer, 1024, (void*)parent, this, uToB);
- strcpy(buffer, "/presets/");
-
- //012345678
- ///presets/
- real_preset_ports.dispatch(msg+9, d);
- //printf("Something <%s>\n", msg+9);
- if(strstr(msg, "paste") && rtosc_argument_string(msg)[0] == 's') {
- char buffer[1024];
- rtosc_message(buffer, 1024, "/damage", "s",
- rtosc_argument(msg, 0).s);
- GUI::raiseUi(ui, buffer);
- }
-
-
- if(!d.matches) {
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
- fprintf(stderr, "Unknown location '%s'<%s>\n",
- msg, rtosc_argument_string(msg));
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
- }
- }
-
- void handleIo(const char *msg)
- {
- char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- DummyDataObj d(buffer, 1024, (void*)&config, this, uToB);
- strcpy(buffer, "/io/");
-
- Nio::ports.dispatch(msg+4, d);
- if(!d.matches) {
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
- fprintf(stderr, "Unknown location '%s'<%s>\n",
- msg, rtosc_argument_string(msg));
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
- }
- }
-
- void handleConfig(const char *msg)
- {
- char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- DummyDataObj d(buffer, 1024, (void*)config, this, uToB);
- strcpy(buffer, "/config/");
-
- Config::ports.dispatch(msg+8, d);
- if(!d.matches) {
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
- fprintf(stderr, "Unknown location '%s'<%s>\n",
- msg, rtosc_argument_string(msg));
- fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
- }
- }
-
- bool handleOscil(string path, const char *msg, void *v);
void kitEnable(const char *msg);
void kitEnable(int part, int kit, int type);
@@ -787,11 +602,16 @@ public:
// Handle an event with special cases
void handleMsg(const char *msg);
-
void write(const char *path, const char *args, ...);
void write(const char *path, const char *args, va_list va);
+ // Send a message to a remote client
+ void sendToRemote(const char *msg, std::string dest);
+ // Broadcast a message to all listening remote clients
+ void broadcastToRemote(const char *msg);
+
+
/*
* Provides a mapping for non-RT objects stored inside the backend
* - Oscilgen almost all parameters can be safely set
@@ -838,6 +658,294 @@ public:
PresetsStore presetsstore;
};
+
+static int extractInt(const char *msg)
+{
+ const char *mm = msg;
+ while(*mm && !isdigit(*mm)) ++mm;
+ if(isdigit(*mm))
+ return atoi(mm);
+ return -1;
+}
+
+static const char *chomp(const char *msg)
+{
+ while(*msg && *msg!='/') ++msg; \
+ msg = *msg ? msg+1 : msg;
+ return msg;
+};
+
+using rtosc::RtData;
+#define rObject Bank
+#define rBegin [](const char *msg, RtData &d) { (void)msg;(void)d;\
+ rObject &impl = *((rObject*)d.obj);(void)impl;
+#define rEnd }
+/*****************************************************************************
+ * Instrument Banks *
+ * *
+ * Banks and presets in general are not classed as realtime safe *
+ * *
+ * The supported operations are: *
+ * - Load Names *
+ * - Load Bank *
+ * - Refresh List of Banks *
+ *****************************************************************************/
+rtosc::Ports bankPorts = {
+ {"rescan:", 0, 0,
+ rBegin;
+ impl.rescanforbanks();
+ //Send updated banks
+ int i = 0;
+ for(auto &elm : impl.banks)
+ d.reply("/bank-list", "iss", i++, elm.name.c_str(), elm.dir.c_str());
+
+ rEnd},
+ {"slot#1024:", 0, 0,
+ rBegin;
+ const int loc = extractInt(msg);
+ if(loc >= BANK_SIZE)
+ return;
+
+ d.reply("/bankview", "iss",
+ loc, impl.ins[loc].name.c_str(),
+ impl.ins[loc].filename.c_str());
+ rEnd},
+ {"slots:", 0, 0,
+ rBegin;
+ int i = 0;
+ for(auto &elm : impl.banks)
+ d.reply("/bank-list", "iss", i++, elm.name.c_str(), elm.dir.c_str());
+ rEnd},
+ {"bank_select::i", 0, 0,
+ rBegin
+ if(rtosc_narguments(msg)) {
+ const int pos = rtosc_argument(msg, 0).i;
+ d.reply(d.loc, "i", pos);
+ if(impl.bankpos != pos) {
+ impl.bankpos = pos;
+ impl.loadbank(impl.banks[pos].dir);
+
+ //Reload bank slots
+ for(int i=0; i<BANK_SIZE; ++i)
+ d.reply("/bankview", "iss",
+ i, impl.ins[i].name.c_str(),
+ impl.ins[i].filename.c_str());
+ }
+ } else
+ d.reply("/bank_select", "i", impl.bankpos);
+ rEnd},
+ {"save_to_slot:ii", 0, 0,
+ rBegin;
+ const int part_id = rtosc_argument(msg, 0).i;
+ const int slot = rtosc_argument(msg, 1).i;
+ //impl.saveBankSlot(part_id, slot, master);
+
+ //int err = 0;
+ //doReadOnlyOp([master,nslot,npart,&err](){
+ // err = master->bank.savetoslot(nslot, master->part[npart]);});
+ //if(err) {
+ // char buffer[1024];
+ // rtosc_message(buffer, 1024, "/alert", "s",
+ // "Failed To Save To Bank Slot, please check file permissions");
+ // GUI::raiseUi(ui, buffer);
+ //}
+ assert(false);
+ rEnd},
+ {"rename_slot:is", 0, 0,
+ rBegin;
+ const int slot = rtosc_argument(msg, 0).i;
+ const char *name = rtosc_argument(msg, 1).s;
+ const int err = impl.setname(slot, name, -1);
+ if(err) {
+ d.reply("/alert", "s",
+ "Failed To Rename Bank Slot, please check file permissions");
+ }
+ rEnd},
+ {"swap_slots:ii", 0, 0,
+ rBegin;
+ const int slota = rtosc_argument(msg, 0).i;
+ const int slotb = rtosc_argument(msg, 1).i;
+ const int err = impl.swapslot(slota, slotb);
+ if(err)
+ d.reply("/alert", "s",
+ "Failed To Swap Bank Slots, please check file permissions");
+ rEnd},
+ {"clear_slot:i", 0, 0,
+ rBegin;
+ const int slot = rtosc_argument(msg, 0).i;
+ const int err = impl.clearslot(slot);
+ if(err)
+ d.reply("/alert", "s",
+ "Failed To Clear Bank Slot, please check file permissions");
+ rEnd},
+};
+
+/******************************************************************************
+ * MiddleWare Snooping Ports *
+ * *
+ * These ports handle: *
+ * - Events going to the realtime thread which cannot be safely handled *
+ * there *
+ * - Events generated by the realtime thread which are not destined for a *
+ * user interface *
+ ******************************************************************************/
+
+#undef rObject
+#define rObject MiddleWareImpl
+/*
+ * BASE/part#/kititem#
+ * BASE/part#/kit#/adpars/voice#/oscil/\*
+ * BASE/part#/kit#/adpars/voice#/mod-oscil/\*
+ * BASE/part#/kit#/padpars/prepare
+ * BASE/part#/kit#/padpars/oscil/\*
+ */
+static rtosc::Ports middwareSnoopPorts = {
+ {"part#16/kit#8/adpars/VoicePar#8/OscilSmp/", 0, 0,
+ rBegin;
+ printf("snoop for oscilsmp\n");
+ impl.obj_store.handleOscil(msg, d);
+ rEnd},
+ {"part#16/kit#8/adpars/VoicePar#8/FMSmp/", 0, 0,
+ rBegin
+ printf("snoop for fmsmp\n");
+ impl.obj_store.handleOscil(msg, d);
+ rEnd},
+ {"part#16/kit#8/padpars/", 0, 0,
+ rBegin
+ printf("snoop for padpars\n");
+ impl.obj_store.handlePad(msg, d);
+ rEnd},
+ {"bank/", 0, &bankPorts,
+ rBegin;
+ printf("bank port\n");
+ d.obj = &impl.master->bank;
+ bankPorts.dispatch(chomp(msg),d);
+ rEnd},
+ {"config/", 0, &Config::ports, [](const char *msg, RtData &d) {
+ printf("config port\n");
+ Config::ports.dispatch(chomp(msg), d);}},
+ {"presets/", 0, &real_preset_ports, [](const char *msg, RtData &d) {
+ printf("presets port\n");
+ MiddleWareImpl *obj = (MiddleWareImpl*)d.obj;
+ d.obj = (void*)obj->parent;
+ real_preset_ports.dispatch(chomp(msg), d);
+ if(strstr(msg, "paste") && rtosc_argument_string(msg)[0] == 's')
+ d.reply("/damage", "s", rtosc_argument(msg, 0).s);
+ }},
+ {"io/", 0, &Nio::ports, [](const char *msg, RtData &d) {
+ printf("io port\n");
+ Nio::ports.dispatch(chomp(msg), d);}},
+ {"part*/kit*/{Padenabled,Ppadenabled,Psubenabled}:T:F", 0, 0,
+ rBegin;
+ printf("enable engine port...\n");
+ impl.kitEnable(msg);
+ d.forward();
+ rEnd},
+ {"save_xmz:s", 0, 0,
+ rBegin;
+ const char *file = rtosc_argument(msg, 0).s;
+ //Copy is needed as filename WILL get trashed during the rest of the run
+ impl.doReadOnlyOp([&impl,file](){
+ int res = impl.master->saveXML(file);
+ (void)res;});
+ rEnd},
+ {"save_xiz:is", 0, 0,
+ rBegin;
+ const int part_id = rtosc_argument(msg,0).i;
+ const char *file = rtosc_argument(msg,1).s;
+ impl.savePart(part_id, file);
+ rEnd},
+ {"load_xmz:s", 0, 0,
+ rBegin;
+ const char *file = rtosc_argument(msg, 0).s;
+ impl.loadMaster(file);
+ rEnd},
+ {"reset_master:", 0, 0,
+ rBegin;
+ impl.loadMaster(NULL);
+ rEnd},
+ {"load_xiz:is", 0, 0,
+ rBegin;
+ const int part_id = rtosc_argument(msg,0).i;
+ const char *file = rtosc_argument(msg,1).s;
+ impl.pending_load[part_id]++;
+ impl.loadPart(part_id, file, impl.master);
+ rEnd},
+ {"load-part:is", 0, 0,
+ rBegin;
+ const int part_id = rtosc_argument(msg,0).i;
+ const char *file = rtosc_argument(msg,1).s;
+ impl.pending_load[part_id]++;
+ impl.loadPart(part_id, file, impl.master);
+ rEnd},
+ {"setprogram:i:c", 0, 0,
+ rBegin;
+ const int slot = rtosc_argument(msg, 0).i;
+ impl.pending_load[0]++;
+ impl.loadPart(0, impl.master->bank.ins[slot].filename.c_str(), impl.master);
+ rEnd},
+ {"part#16/clear:", 0, 0,
+ rBegin;
+ printf("clear part port...\n");
+ impl.loadClearPart(extractInt(msg));
+ rEnd},
+ {"/undo:", 0, 0,
+ rBegin;
+ impl.undo.seekHistory(-1);
+ rEnd},
+ {"/redo:", 0, 0,
+ rBegin;
+ impl.undo.seekHistory(+1);
+ rEnd},
+ //drop this message into the abyss
+ {"/ui/title:", 0, 0, [](const char *msg, RtData &d) {}}
+};
+
+static rtosc::Ports middlewareReplyPorts = {
+ {"echo:ss", 0, 0,
+ rBegin;
+ const char *type = rtosc_argument(msg, 0).s;
+ const char *url = rtosc_argument(msg, 1).s;
+ if(!strcmp(type, "OSC_URL"))
+ impl.curr_url = url;
+ rEnd},
+ {"free:sb", 0, 0,
+ rBegin;
+ const char *type = rtosc_argument(msg, 0).s;
+ void *ptr = rtosc_argument(msg, 1).b.data;
+ deallocate(type, ptr);
+ rEnd},
+ {"request_memory:", 0, 0,
+ rBegin;
+ //Generate out more memory for the RT memory pool
+ //5MBi chunk
+ size_t N = 5*1024*1024;
+ void *mem = malloc(N);
+ impl.uToB->write("/add-rt-memory", "bi", sizeof(void*), &mem, N);
+ rEnd},
+ {"setprogram:cc:ii", 0, 0,
+ rBegin;
+ const int part = rtosc_argument(msg, 0).i;
+ const int program = rtosc_argument(msg, 1).i;
+ impl.loadPart(part, impl.master->bank.ins[program].filename.c_str(), impl.master);
+ rEnd},
+ {"undo_pause:", 0, 0, rBegin; impl.recording_undo = false; rEnd},
+ {"undo_resume:", 0, 0, rBegin; impl.recording_undo = true; rEnd},
+ {"undo_change", 0, 0,
+ rBegin;
+ if(impl.recording_undo)
+ impl.undo.recordEvent(msg);
+ rEnd},
+ {"broadcast:", 0, 0, rBegin; impl.broadcast = true; rEnd},
+ {"foward:", 0, 0, rBegin; impl.forward = true; rEnd},
+};
+#undef rBegin
+#undef rEnd
+
+/******************************************************************************
+ * MiddleWare Implementation *
+ ******************************************************************************/
+
MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_,
Config* config, int preferrred_port)
:parent(mw), config(config), ui(nullptr), synth(std::move(synth_)),
@@ -900,16 +1008,10 @@ MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_,
});
}
-void DummyDataObj::reply(const char *msg)
-{
- mwi->bToUhandle(msg, true);
-}
MiddleWareImpl::~MiddleWareImpl(void)
{
remove(get_tmp_nam().c_str());
- warnMemoryLeaks();
-
if(server)
lo_server_free(server);
@@ -945,6 +1047,7 @@ MiddleWareImpl::~MiddleWareImpl(void)
void MiddleWareImpl::doReadOnlyOp(std::function<void()> read_only_fn)
{
+ assert(uToB);
uToB->write("/freeze_state","");
std::list<const char *> fico;
@@ -978,126 +1081,70 @@ void MiddleWareImpl::doReadOnlyOp(std::function<void()> read_only_fn)
}
}
-void MiddleWareImpl::bToUhandle(const char *rtmsg, bool dummy)
+void MiddleWareImpl::broadcastToRemote(const char *rtmsg)
{
- assert(strcmp(rtmsg, "/part0/kit0/Ppadenableda"));
- assert(strcmp(rtmsg, "/ze_state"));
- //Dump Incomming Events For Debugging
- if(strcmp(rtmsg, "/vu-meter") && false) {
- fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 1 + 30, 0 + 40);
- fprintf(stdout, "frontend: '%s'<%s>\n", rtmsg,
- rtosc_argument_string(rtmsg));
- fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
- }
+ //Always send to the local UI
+ sendToRemote(rtmsg, "GUI");
- //Activity dot
- //printf(".");fflush(stdout);
-
- if(!strcmp(rtmsg, "/echo")
- && !strcmp(rtosc_argument_string(rtmsg),"ss")
- && !strcmp(rtosc_argument(rtmsg,0).s, "OSC_URL"))
- curr_url = rtosc_argument(rtmsg,1).s;
- else if(!strcmp(rtmsg, "/free")
- && !strcmp(rtosc_argument_string(rtmsg),"sb")) {
- deallocate(rtosc_argument(rtmsg, 0).s, *((void**)rtosc_argument(rtmsg, 1).b.data));
- } else if(!strcmp(rtmsg, "/request-memory")) {
- //Generate out more memory for the RT memory pool
- //5MBi chunk
- size_t N = 5*1024*1024;
- void *mem = malloc(N);
- uToB->write("/add-rt-memory", "bi", sizeof(void*), &mem, N);
- } else if(!strcmp(rtmsg, "/setprogram")
- && !strcmp(rtosc_argument_string(rtmsg),"cc")) {
- loadPart(rtosc_argument(rtmsg,0).i, master->bank.ins[rtosc_argument(rtmsg,1).i].filename.c_str(), master);
- } else if(!strcmp(rtmsg, "/setbank")
- && !strcmp(rtosc_argument_string(rtmsg), "c")) {
- loadPendingBank(rtosc_argument(rtmsg,0).i, master->bank);
- } else if(!strcmp("/undo_pause", rtmsg)) {
- recording_undo = false;
- } else if(!strcmp("/undo_resume", rtmsg)) {
- recording_undo = true;
- } else if(!strcmp("undo_change", rtmsg) && recording_undo) {
- undo.recordEvent(rtmsg);
- } else if(!strcmp(rtmsg, "/broadcast")) {
- broadcast = true;
- } else if(broadcast) {
- broadcast = false;
-#ifdef PLUGINVERSION
- if (!curr_url.empty()) // falktx: check added
- cb(ui, rtmsg);
-
- // falktx: changed curr_url to last_url
- if(last_url != "GUI") {
- lo_message msg = lo_message_deserialise((void*)rtmsg,
- rtosc_message_length(rtmsg, bToU->buffer_size()), NULL);
-
- //Send to known url
- if(!last_url.empty()) {
- lo_address addr = lo_address_new_from_url(last_url.c_str());
- lo_send_message(addr, rtmsg, msg);
- }
- }
-#else
- cb(ui, rtmsg);
+ //Send to remote UI if there's one listening
+ if(curr_url != "GUI")
+ sendToRemote(rtmsg, curr_url);
- if(curr_url != "GUI") {
- lo_message msg = lo_message_deserialise((void*)rtmsg,
- rtosc_message_length(rtmsg, bToU->buffer_size()), NULL);
+ broadcast = false;
+}
- //Send to known url
- if(!curr_url.empty()) {
- lo_address addr = lo_address_new_from_url(curr_url.c_str());
- lo_send_message(addr, rtmsg, msg);
- }
- }
-#endif
- } else if((dummy?last_url:curr_url) == "GUI" || !strcmp(rtmsg, "/close-ui")) {
+void MiddleWareImpl::sendToRemote(const char *rtmsg, std::string dest)
+{
+ if(dest == "GUI") {
cb(ui, rtmsg);
- } else{
+ } else if(!dest.empty()) {
lo_message msg = lo_message_deserialise((void*)rtmsg,
rtosc_message_length(rtmsg, bToU->buffer_size()), NULL);
//Send to known url
- if(!curr_url.empty()) {
- lo_address addr = lo_address_new_from_url(dummy?last_url.c_str():curr_url.c_str());
+ lo_address addr = lo_address_new_from_url(dest.c_str());
+ if(addr)
lo_send_message(addr, rtmsg, msg);
- }
}
}
-bool MiddleWareImpl::handleOscil(string path, const char *msg, void *v)
+/**
+ * Handle all events coming from the backend
+ *
+ * This includes forwarded events which need to be retransmitted to the backend
+ * after the snooping code inspects the message
+ */
+void MiddleWareImpl::bToUhandle(const char *rtmsg)
{
- //printf("handleOscil...\n");
- char buffer[1024];
- memset(buffer, 0, sizeof(buffer));
- DummyDataObj d(buffer, 1024, v, this, uToB);
- strcpy(buffer, path.c_str());
- if(!v)
- return true;
-
- //Paste To Non-Realtime Parameters and then forward
- if(strstr(msg, "paste") && !strstr(msg, "padpars")) {
- }
+ //Verify Message isn't a known corruption bug
+ assert(strcmp(rtmsg, "/part0/kit0/Ppadenableda"));
+ assert(strcmp(rtmsg, "/ze_state"));
- if(!strstr(msg, "padpars")) {
- for(auto &p:OscilGen::ports.ports) {
- if(strstr(p.name,msg) && strstr(p.metadata, "realtime") &&
- !strcmp("b", rtosc_argument_string(msg))) {
- //printf("sending along packet '%s'...\n", msg);
- return false;
- }
- }
+ //Dump Incomming Events For Debugging
+ if(strcmp(rtmsg, "/vu-meter") && false) {
+ fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 1 + 30, 0 + 40);
+ fprintf(stdout, "frontend: '%s'<%s>\n", rtmsg,
+ rtosc_argument_string(rtmsg));
+ fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
}
- OscilGen::ports.dispatch(msg, d);
- if(!d.matches) {
- //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 1, 7 + 30, 0 + 40);
- //fprintf(stderr, "Unknown location '%s%s'<%s>\n",
- // path.c_str(), msg, rtosc_argument_string(msg));
- //fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
+ //Activity dot
+ printf(".");fflush(stdout);
+
+ MwDataObj d(this);
+ middlewareReplyPorts.dispatch(rtmsg, d, true);
+
+ //Normal message not captured by the ports
+ if(d.matches == 0) {
+ if(forward) {
+ forward = false;
+ handleMsg(rtmsg);
+ } if(broadcast)
+ broadcastToRemote(rtmsg);
+ else
+ sendToRemote(rtmsg, curr_url);
}
-
- return true;
+
}
//Allocate kits on a as needed basis
@@ -1115,8 +1162,7 @@ void MiddleWareImpl::kitEnable(const char *msg)
type = 1;
else if(strstr(msg, "Psubenabled"))
type = 2;
-
- if(type == -1)
+ else
return;
const char *tmp = strstr(msg, "part");
@@ -1138,7 +1184,7 @@ void MiddleWareImpl::kitEnable(const char *msg)
void MiddleWareImpl::kitEnable(int part, int kit, int type)
{
- //printf("attempting a kit enable<%d,%d,%d>\n", part, kit, type);
+ printf("attempting a kit enable<%d,%d,%d>\n", part, kit, type);
string url = "/part"+to_s(part)+"/kit"+to_s(kit)+"/";
void *ptr = NULL;
if(type == 0 && kits.add[part][kit] == NULL) {
@@ -1159,14 +1205,13 @@ void MiddleWareImpl::kitEnable(int part, int kit, int type)
uToB->write(url.c_str(), "b", sizeof(void*), &ptr);
}
-/* BASE/part#/kititem#
- * BASE/part#/kit#/adpars/voice#/oscil/\*
- * BASE/part#/kit#/adpars/voice#/mod-oscil/\*
- * BASE/part#/kit#/padpars/prepare
- * BASE/part#/kit#/padpars/oscil/\*
+
+/*
+ * Handle all messages traveling to the realtime side.
*/
void MiddleWareImpl::handleMsg(const char *msg)
{
+ //Check for known bugs
assert(msg && *msg && rindex(msg, '/')[1]);
assert(strstr(msg,"free") == NULL || strstr(rtosc_argument_string(msg), "b") == NULL);
assert(strcmp(msg, "/part0/Psysefxvol"));
@@ -1175,95 +1220,27 @@ void MiddleWareImpl::handleMsg(const char *msg)
assert(strcmp(msg, "sysefx0sysefx0/preset"));
assert(strcmp(msg, "/sysefx0preset"));
assert(strcmp(msg, "Psysefxvol0/part0"));
- //fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 6 + 30, 0 + 40);
- //fprintf(stdout, "middleware: '%s':%s\n", msg, rtosc_argument_string(msg));
- //fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
+
+ fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 6 + 30, 0 + 40);
+ fprintf(stdout, "middleware: '%s':%s\n", msg, rtosc_argument_string(msg));
+ fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
+
const char *last_path = rindex(msg, '/');
- if(!last_path)
+ if(!last_path) {
+ printf("Bad message in handleMsg() <%s>\n", msg);
+ assert(false);
return;
+ }
+ MwDataObj d(this);
+ middwareSnoopPorts.dispatch(msg, d, true);
- //printf("watching '%s' go by\n", msg);
- //Get the object resource locator
- string obj_rl(msg, last_path+1);
- int npart = -1;
- char testchr = 0;
-
- std::function<void(const char*)> bank_cb;
- if(last_url == "GUI")
- bank_cb = [this](const char *msg){if(osc)osc->tryLink(msg);};
- else
- bank_cb = [this](const char *msg){if(osc)osc->tryLink(msg);this->bToUhandle(msg, 1);};
-
- if(!strcmp(msg, "/refresh_bank") && !strcmp(rtosc_argument_string(msg), "i")) {
- refreshBankView(master->bank, rtosc_argument(msg,0).i, bank_cb);
- } else if(!strcmp(msg, "/bank-list") && !strcmp(rtosc_argument_string(msg), "")) {
- bankList(master->bank, bank_cb);
- } else if(!strcmp(msg, "/rescanforbanks") && !strcmp(rtosc_argument_string(msg), "")) {
- rescanForBanks(master->bank, bank_cb);
- } else if(!strcmp(msg, "/loadbank") && !strcmp(rtosc_argument_string(msg), "i")) {
- loadBank(master->bank, rtosc_argument(msg, 0).i, bank_cb);
- } else if(!strcmp(msg, "/loadbank") && !strcmp(rtosc_argument_string(msg), "")) {
- bankPos(master->bank, bank_cb);
- } else if(obj_store.has(obj_rl)) {
- //try some over simplified pattern matching
- if(strstr(msg, "oscilgen/") || strstr(msg, "FMSmp/") || strstr(msg, "OscilSmp/")) {
- if(!handleOscil(obj_rl, last_path+1, obj_store.get(obj_rl)))
- uToB->raw_write(msg);
- //else if(strstr(obj_rl.c_str(), "kititem"))
- // handleKitItem(obj_rl, objmap[obj_rl],atoi(rindex(msg,'m')+1),rtosc_argument(msg,0).T);
- } else if(strstr(msg, "padpars/prepare"))
- preparePadSynth(obj_rl,(PADnoteParameters *) obj_store.get(obj_rl), uToB);
- else if(strstr(msg, "padpars")) {
- if(!handlePAD(obj_rl, last_path+1, obj_store.get(obj_rl)))
- uToB->raw_write(msg);
- } else //just forward the message
- uToB->raw_write(msg);
- } else if(strstr(msg, "/save_xmz") && !strcmp(rtosc_argument_string(msg), "s")) {
- saveMaster(rtosc_argument(msg,0).s);
- } else if(strstr(msg, "/save_xiz") && !strcmp(rtosc_argument_string(msg), "is")) {
- savePart(rtosc_argument(msg,0).i,rtosc_argument(msg,1).s);
- } else if(strstr(msg, "/load_xmz") && !strcmp(rtosc_argument_string(msg), "s")) {
- loadMaster(rtosc_argument(msg,0).s);
- } else if(strstr(msg, "/reset_master") && !strcmp(rtosc_argument_string(msg), "")) {
- loadMaster(NULL);
- } else if(!strcmp(msg, "/load_xiz") && !strcmp(rtosc_argument_string(msg), "is")) {
- pending_load[rtosc_argument(msg,0).i]++;
- loadPart(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master);
- } else if(strstr(msg, "load-part") && !strcmp(rtosc_argument_string(msg), "is")) {
- pending_load[rtosc_argument(msg,0).i]++;
- loadPart(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master);
- } else if(!strcmp(msg, "/setprogram")
- && !strcmp(rtosc_argument_string(msg),"c")) {
- pending_load[0]++;
- loadPart(0, master->bank.ins[rtosc_argument(msg,0).i].filename.c_str(), master);
- } else if(strstr(msg, "save-bank-part") && !strcmp(rtosc_argument_string(msg), "ii")) {
- saveBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).i, master);
- } else if(strstr(msg, "bank-rename") && !strcmp(rtosc_argument_string(msg), "is")) {
- renameBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).s, master);
- } else if(strstr(msg, "swap-bank-slots") && !strcmp(rtosc_argument_string(msg), "ii")) {
- swapBankSlot(rtosc_argument(msg,0).i, rtosc_argument(msg,1).i, master);
- } else if(strstr(msg, "clear-bank-slot") && !strcmp(rtosc_argument_string(msg), "i")) {
- clearBankSlot(rtosc_argument(msg,0).i, master);
- } else if(strstr(msg, "/config/")) {
- handleConfig(msg);
- } else if(strstr(msg, "/presets/")) {
- handlePresets(msg);
- } else if(strstr(msg, "/io/")) {
- handleIo(msg);
- } else if(strstr(msg, "Padenabled") || strstr(msg, "Ppadenabled") || strstr(msg, "Psubenabled")) {
- kitEnable(msg);
+ //A message unmodified by snooping
+ if(d.matches == 0 || d.forwarded) {
+ printf("Message Continuing on...\n");
uToB->raw_write(msg);
- } else if(sscanf(msg, "/part%d/clea%c", &npart, &testchr) == 2 && testchr == 'r') {
- loadClearPart(npart);
- } else if(!strcmp(msg, "/undo")) {
- undo.seekHistory(-1);
- } else if(!strcmp(msg, "/redo")) {
- undo.seekHistory(+1);
- } else if(!strcmp(msg, "/ui/title")) {
- ;//drop the message into the abyss
} else
- uToB->raw_write(msg);
+ printf("Message Handled...\n");
}
void MiddleWareImpl::write(const char *path, const char *args, ...)
@@ -1289,9 +1266,6 @@ void MiddleWareImpl::write(const char *path, const char *args, va_list va)
warnx("Failed to write message to '%s'", path);
}
-void MiddleWareImpl::warnMemoryLeaks(void)
-{}
-
/******************************************************************************
* MidleWare Forwarding Stubs *
******************************************************************************/
@@ -1309,6 +1283,8 @@ void MiddleWare::updateResources(Master *m)
}
Master *MiddleWare::spawnMaster(void)
{
+ assert(impl->master);
+ assert(impl->master->uToB);
return impl->master;
}
Fl_Osc_Interface *MiddleWare::spawnUiApi(void)
@@ -1354,7 +1330,7 @@ void MiddleWare::transmitMsg(const char *path, const char *args, ...)
va_end(va);
}
-void MiddleWare::transmitMsg(const char *path, const char *args, va_list va)
+void MiddleWare::transmitMsg_va(const char *path, const char *args, va_list va)
{
char buffer[1024];
if(rtosc_vmessage(buffer, 1024, path, args, va))
diff --git a/src/Misc/MiddleWare.h b/src/Misc/MiddleWare.h
@@ -32,11 +32,15 @@ class MiddleWare
//Handle a rtosc Message uToB
void transmitMsg(const char *, const char *args, ...);
//Handle a rtosc Message uToB
- void transmitMsg(const char *, const char *args, va_list va);
+ void transmitMsg_va(const char *, const char *args, va_list va);
+
//Indicate that a bank will be loaded
+ //NOTE: Can only be called by realtime thread
void pendingSetBank(int bank);
//Indicate that a program will be loaded on a known part
+ //NOTE: Can only be called by realtime thread
void pendingSetProgram(int part, int program);
+
//Get/Set the active bToU url
std::string activeUrl(void);
void activeUrl(std::string u);
diff --git a/src/Misc/PresetExtractor.cpp b/src/Misc/PresetExtractor.cpp
@@ -32,6 +32,7 @@ const rtosc::Ports real_preset_ports =
{"scan-for-presets:", 0, 0,
[](const char *, rtosc::RtData &d) {
MiddleWare &mw = *(MiddleWare*)d.obj;
+ assert(d.obj);
mw.getPresetsStore().scanforpresets();
auto &pre = mw.getPresetsStore().presets;
d.reply(d.loc, "i", pre.size());
@@ -45,6 +46,7 @@ const rtosc::Ports real_preset_ports =
{"copy:s:ss:si:ssi", 0, 0,
[](const char *msg, rtosc::RtData &d) {
MiddleWare &mw = *(MiddleWare*)d.obj;
+ assert(d.obj);
std::string args = rtosc_argument_string(msg);
d.reply(d.loc, "s", "clipboard copy...");
printf("\nClipboard Copy...\n");
@@ -65,6 +67,7 @@ const rtosc::Ports real_preset_ports =
{"paste:s:ss:si:ssi", 0, 0,
[](const char *msg, rtosc::RtData &d) {
MiddleWare &mw = *(MiddleWare*)d.obj;
+ assert(d.obj);
std::string args = rtosc_argument_string(msg);
d.reply(d.loc, "s", "clipboard paste...");
printf("\nClipboard Paste...\n");
@@ -85,11 +88,13 @@ const rtosc::Ports real_preset_ports =
{"clipboard-type:", 0, 0,
[](const char *, rtosc::RtData &d) {
const MiddleWare &mw = *(MiddleWare*)d.obj;
+ assert(d.obj);
d.reply(d.loc, "s", mw.getPresetsStore().clipboard.type.c_str());
}},
{"delete:s", 0, 0,
[](const char *msg, rtosc::RtData &d) {
MiddleWare &mw = *(MiddleWare*)d.obj;
+ assert(d.obj);
mw.getPresetsStore().deletepreset(rtosc_argument(msg,0).s);
}},
@@ -133,6 +138,7 @@ class Capture:public rtosc::RtData
{
matches = 0;
memset(locbuf, 0, sizeof(locbuf));
+ memset(msgbuf, 0, sizeof(msgbuf));
loc = locbuf;
loc_size = sizeof(locbuf);
obj = obj_;
@@ -193,7 +199,9 @@ std::string doCopy(MiddleWare &mw, string url, string name)
mw.doReadOnlyOp([&xml, url, name, &mw](){
Master *m = mw.spawnMaster();
//Get the pointer
+ printf("capture at <%s>\n", (url+"self").c_str());
T *t = (T*)capture<void*>(m, url+"self");
+ assert(t);
//Extract Via mxml
//t->add2XML(&xml);
t->copy(mw.getPresetsStore(), name.empty()? NULL:name.c_str());
@@ -303,6 +311,7 @@ void doClassPaste(std::string type, std::string type_, MiddleWare &mw, string ur
std::string doClassCopy(std::string type, MiddleWare &mw, string url, string name)
{
+ printf("doClassCopy(%p)\n", mw.spawnMaster()->uToB);
if(type == "EnvelopeParams")
return doCopy<EnvelopeParams>(mw, url, name);
else if(type == "LFOParams")
diff --git a/src/Params/ADnoteParameters.cpp b/src/Params/ADnoteParameters.cpp
@@ -42,8 +42,23 @@ using rtosc::RtData;
#define rObject ADnoteVoiceParam
static const Ports voicePorts = {
- rRecurp(OscilSmp, "Primary Oscillator"),
- rRecurp(FMSmp, "Modulating Oscillator"),
+ //Send Messages To Oscillator Realtime Table
+ {"OscilSmp/", rDoc("Primary Oscillator"),
+ &OscilGen::ports,
+ rBOIL_BEGIN
+ if(obj->OscilSmp == NULL) return;
+ data.obj = obj->OscilSmp;
+ SNIP
+ OscilGen::realtime_ports.dispatch(msg, data);
+ rBOIL_END},
+ {"FMSmp/", rDoc("Modulating Oscillator"),
+ &OscilGen::ports,
+ rBOIL_BEGIN
+ if(obj->FMSmp == NULL) return;
+ data.obj = obj->FMSmp;
+ SNIP
+ OscilGen::realtime_ports.dispatch(msg, data);
+ rBOIL_END},
rRecurp(FreqLfo, "Frequency LFO"),
rRecurp(AmpLfo, "Amplitude LFO"),
rRecurp(FilterLfo, "Filter LFO"),
@@ -107,7 +122,7 @@ static const Ports voicePorts = {
rToggle(PFMFreqEnvelopeEnabled, "Modulator Frequency Envelope"),
rToggle(PFMAmpEnvelopeEnabled, "Modulator Amplitude Envelope"),
-
+
//weird stuff for PCoarseDetune
{"detunevalue:", rMap(unit,cents) rDoc("Get detune in cents"), NULL,
[](const char *, RtData &d)
@@ -148,7 +163,7 @@ static const Ports voicePorts = {
obj->PCoarseDetune = k + (obj->PCoarseDetune/1024)*1024;
}
}},
-
+
//weird stuff for PCoarseDetune
{"FMdetunevalue:", rMap(unit,cents) rDoc("Get modulator detune"), NULL, [](const char *, RtData &d)
{
diff --git a/src/Params/PADnoteParameters.cpp b/src/Params/PADnoteParameters.cpp
@@ -34,77 +34,101 @@
using namespace rtosc;
-#define PC(x) rParamZyn(P##x, "undocumented padnote parameter")
-
-template<int i>
-void simpleset(const char *m, rtosc::RtData &d)
-{
- unsigned char *addr = ((unsigned char*) d.obj)+i;
- if(!rtosc_narguments(m))
- d.reply(d.loc, "c", *addr);
- else
- *addr = rtosc_argument(m, 0).i;
-}
-
#define rObject PADnoteParameters
-
-#define P_C(x) rtosc::Port{#x "::c", "::", NULL, \
- simpleset<__builtin_offsetof(class PADnoteParameters, P##x)>}
static const rtosc::Ports PADnotePorts =
{
- rRecurp(oscilgen, "Oscillator"),
rRecurp(FreqLfo, "Frequency LFO"),
rRecurp(AmpLfo, "Amplitude LFO"),
rRecurp(FilterLfo, "Filter LFO"),
- rRecurp(resonance, "Resonance"),
rRecurp(FreqEnvelope, "Frequency Envelope"),
rRecurp(AmpEnvelope, "Amplitude Envelope"),
rRecurp(FilterEnvelope, "Filter Envelope"),
rRecurp(GlobalFilter, "Post Filter"),
- rParamI(Pmode, rMap(min, 0), rMap(max, 2), "0 - bandwidth, 1 - discrete 2 - continious"),
- PC(Volume),
- PC(hp.base.type),
- PC(hp.base.par1),
- PC(hp.freqmult),
- PC(hp.modulator.par1),
- PC(hp.modulator.freq),
- PC(hp.width),
- PC(hp.amp.mode),
- PC(hp.amp.type),
- PC(hp.amp.par1),
- PC(hp.amp.par2),
+
+ //Harmonic Source Distribution
+ rRecurp(oscilgen, "Oscillator"),
+ rRecurp(resonance, "Resonance"),
+
+ //Harmonic Shape
+ rOption(Pmode, rMap(min, 0), rMap(max, 2), rOptions(bandwidth,discrete,continious),
+ "Harmonic Distribution Model"),
+ rOption(Php.base.type, rOptions(Gaussian, Rectanglar, Double Exponential),
+ "Harmonic profile shape"),
+ rParamZyn(Php.base.par1, "Harmonic shape distribution parameter"),
+ rParamZyn(Php.freqmult, "Frequency multiplier on distribution"),
+ rParamZyn(Php.modulator.par1, "Distribution modulator parameter"),
+ rParamZyn(Php.modulator.freq, "Frequency of modulator parameter"),
+ rParamZyn(Php.width, "Width of base harmonic"),
+ rOption(Php.amp.mode, rOptions(Sum, Mult, Div1, Div2),
+ "Amplitude harmonic multiplier type"),
+
+ //Harmonic Modulation
+ rOption(Php.amp.type, rOptions(Off, Gauss, Sine, Flat),
+ "Type of amplitude multipler"),
+ rParamZyn(Php.amp.par1, "Amplitude multiplier parameter"),
+ rParamZyn(Php.amp.par2, "Amplitude multiplier parameter"),
rToggle(Php.autoscale, "Autoscaling Harmonics"),
- PC(hp.onehalf),
-
- PC(bwscale),
-
- PC(hrpos.type),
- PC(hrpos.par1),
- PC(hrpos.par2),
- PC(hrpos.par3),
-
- PC(quality.samplesize),
- PC(quality.basenote),
- PC(quality.oct),
- PC(quality.smpoct),
-
- PC(fixedfreq),
- PC(fixedfreqET),
- PC(Stereo),
- PC(Panning),
- PC(AmpVelocityScaleFunction),
- PC(PunchStrength),
- PC(PunchTime),
- PC(PunchStretch),
- PC(PunchVelocitySensing),
- PC(FilterVelocityScale),
- PC(FilterVelocityScaleFunction),
+ rOption(Php.onehalf,
+ rOptions(Full, Upper Half, Lower Half),
+ "Harmonic cutoff model"),
+
+ //Harmonic Bandwidth
+ rOption(Pbwscale,
+ rOptions(Normal,
+ EqualHz, Quater,
+ Half, 75%, 150%,
+ Double, Inv. Half),
+ "Bandwidth scaling"),
+
+ //Harmonic Position Modulation
+ rOption(Phrpos.type,
+ rOptions(Harmonic, ShiftU, ShiftL, PowerU, PowerL, Sine,
+ Power, Shift),
+ "Harmonic Overtone shifting mode"),
+ rParamZyn(Phrpos.par1, "Harmonic position parameter"),
+ rParamZyn(Phrpos.par2, "Harmonic position parameter"),
+ rParamZyn(Phrpos.par3, "Harmonic position parameter"),
+
+ //Quality
+ rOption(Pquality.samplesize,
+ rOptions(16k (Tiny), 32k, 64k (Small), 128k,
+ 256k (Normal), 512k, 1M (Big)),
+ "Size of each wavetable element"),
+ rOption(Pquality.basenote,
+ rOptions( C-2, G-2, C-3, G-3, C-4,
+ G-4, C-5, G-5, G-6,),
+ "Base note for wavetable"),
+ rOption(Pquality.smpoct,
+ rOptions(0.5, 1, 2, 3, 4, 6, 12),
+ "Samples per octave"),
+ rParamI(Pquality.oct, rLinear(0,7),
+ "Number of octaves to sample (above the first sample"),
+
+ //Volume
+ rToggle(PStereo, "Stereo/Mono Mode"),
+ rParamZyn(PPanning, "Left Right Panning"),
+ rParamZyn(PVolume, "Synth Volume"),
+ rParamZyn(PAmpVelocityScaleFunction, "Amplitude Velocity Sensing function"),
+
+ //Punch
+ rParamZyn(PPunchStrength, "Punch Strength"),
+ rParamZyn(PPunchTime, "UNKNOWN"),
+ rParamZyn(PPunchStretch, "How Punch changes with note frequency"),
+ rParamZyn(PPunchVelocitySensing, "Punch Velocity control"),
+
+ //Filter
+ rParamZyn(PFilterVelocityScale, "Filter Velocity Magnitude"),
+ rParamZyn(PFilterVelocityScaleFunction, "Filter Velocity Function Shape"),
+
+ //Freq
+ rToggle(Pfixedfreq, "Base frequency fixed frequency enable"),
+ rParamZyn(PfixedfreqET, "Equal temeperate control for fixed frequency operation"),
rParamI(PDetune, "Fine Detune"),
rParamI(PCoarseDetune, "Coarse Detune"),
rParamZyn(PDetuneType, "Magnitude of Detune"),
- {"Pbandwidth::i", rProp(parameter) rDoc("Bandwith Of Harmonics"), NULL,
+ {"Pbandwidth::i", rProp(parameter) rLinear(0,1000) rDoc("Bandwith Of Harmonics"), NULL,
[](const char *msg, rtosc::RtData &d) {
PADnoteParameters *p = ((PADnoteParameters*)d.obj);
if(rtosc_narguments(msg)) {
@@ -191,6 +215,69 @@ static const rtosc::Ports PADnotePorts =
}},
};
+#if 0
+rtosc::ClonePort non_realtime{
+ PADnotePorts,
+ {
+ //Recursions
+ {"oscilgen/", rRecurCb(oscilgen)},
+ {"resonance/", rRecurCb(resonance)},
+ //Harmonic Shape
+ {"Pmode::i", rParamICb}
+
+ {Php.base.type::i, rOptionCb},
+ {Php.base.par1::i, rParamZynCb},
+ {Php.freqmult::i, rParamZynCb},
+ {Php.modulator.par1::i, rParamZynCb},
+ {Php.modulator.freq::i, rParamZynCb},
+ {Php.width::i, rParamZynCb},
+ {Php.amp.mode::i, rOptionCb},
+
+ //Harmonic Modulation
+ {Php.amp.type::i, rOptionCb},
+ {Php.amp.par1::i, rParamZynCb},
+ {Php.amp.par2::i, rParamZynCb},
+ {Php.autoscale, rToggleCb},
+ //...
+ rOption(Php.onehalf,
+ rOptions(Full, Upper Half, Lower Half),
+ "Harmonic cutoff model"),
+
+ //Harmonic Bandwidth
+ rOption(Pbwscale,
+ rOptions(Normal,
+ EqualHz, Quater,
+ Half, 75%, 150%,
+ Double, Inv. Half),
+ "Bandwidth scaling"),
+
+ //Harmonic Position Modulation
+ rOption(Phrpos.type,
+ rOptions(Harmonic, ShiftU, ShiftL, PowerU, PowerL, Sine,
+ Power, Shift),
+ "Harmonic Overtone shifting mode"),
+ rParamZyn(Phrpos.par1, "Harmonic position parameter"),
+ rParamZyn(Phrpos.par2, "Harmonic position parameter"),
+ rParamZyn(Phrpos.par3, "Harmonic position parameter"),
+
+ //Quality
+ rOption(Pquality.samplesize,
+ rOptions(16k (Tiny), 32k, 64k (Small), 128k,
+ 256k (Normal), 512k, 1M (Big)),
+ "Size of each wavetable element"),
+ rOption(Pquality.basenote,
+ rOptions( C-2, G-2, C-3, G-3, C-4,
+ G-4, C-5, G-5, G-6,),
+ "Base note for wavetable"),
+ rOption(Pquality.smpoct,
+ rOptions(0.5, 1, 2, 3, 4, 6, 12),
+ "Samples per octave"),
+ rParamI(Pquality.oct, rLinear(0,7),
+ "Number of octaves to sample (above the first sample"),
+
+};
+#endif
+
const rtosc::Ports &PADnoteParameters::ports = PADnotePorts;
PADnoteParameters::PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_)
diff --git a/src/Synth/OscilGen.cpp b/src/Synth/OscilGen.cpp
@@ -38,8 +38,6 @@
pthread_t main_thread;
-#define PC(x) rParamZyn(P##x, "undocumented oscilgen parameter")
-
#define rObject OscilGen
const rtosc::Ports OscilGen::ports = {
rSelf(OscilGen),
@@ -51,21 +49,10 @@ const rtosc::Ports OscilGen::ports = {
dB scale (-100)),
"Type of magnitude for harmonics"),
rOption(Pcurrentbasefunc,
- rOptions(sine, triangle,
- pulse,
- saw,
- power,
- gauss,
- diode,
- abssine,
- pulsesine,
- stretchsine,
- chirp,
- absstretchsine,
- chebyshev,
- sqr,
- spike,
- circle), rOpt(127,use-as-base waveform),
+ rOptions(sine, triangle, pulse, saw, power, gauss,
+ diode, abssine, pulsesine, stretchsine,
+ chirp, absstretchsine, chebyshev, sqr,
+ spike, circle), rOpt(127,use-as-base waveform),
"Base Waveform for harmonics"),
rParamZyn(Pbasefuncpar,
"Morph between possible base function shapes "
@@ -82,42 +69,32 @@ const rtosc::Ports OscilGen::ports = {
rParamZyn(Pwaveshaping, "Degree Of Waveshaping"),
rOption(Pwaveshapingfunction,
rOptions(Undistorted,
- Arctangent,
- Asymmetric,
- Pow,
- Sine,
- Quantisize,
- Zigzag,
- Limiter,
- Upper Limiter,
- Lower Limiter,
- Inverse Limiter,
- Clip,
- Asym2,
- Pow2,
- sigmoid), "Shape of distortion to be applied"),
+ Arctangent, Asymmetric, Pow, Sine, Quantisize,
+ Zigzag, Limiter, Upper Limiter, Lower Limiter,
+ Inverse Limiter, Clip, Asym2, Pow2, sigmoid),
+ "Shape of distortion to be applied"),
rOption(Pfiltertype, rOptions(No Filter,
lp, hp1, hp1b, bp1, bs1, lp2, hp2, bp2, bs2,
cos, sin, low_shelf, s), "Harmonic Filter"),
- PC(filterpar1),
- PC(filterpar2),
+ rParamZyn(Pfilterpar1, "Filter parameter"),
+ rParamZyn(Pfilterpar2, "Filter parameter"),
rToggle(Pfilterbeforews, "Filter before waveshaping spectra;"
"When enabled oscilfilter(freqs); then waveshape(freqs);, "
"otherwise waveshape(freqs); then oscilfilter(freqs);"),
- PC(satype),
+ rOption(Psatype, rOptions(None, Pow, ThrsD, ThrsU),
+ "Spectral Adjustment Type"),
rParamZyn(Psapar, "Spectral Adjustment Parameter"),
rParamI(Pharmonicshift, "Amount of shift on harmonics"),
rToggle(Pharmonicshiftfirst, "If harmonics are shifted before waveshaping/filtering"),
rOption(Pmodulation, rOptions(None, Rev, Sine, Power),
"Frequency Modulation To Combined Spectra"),
- rParamZyn(Pmodulationpar1,
- "modulation parameter"),
- rParamZyn(Pmodulationpar2,
- "modulation parameter"),
- rParamZyn(Pmodulationpar3,
- "modulation parameter"),
- //FIXME realtime parameters lurking below
- PC(rand),
+ rParamZyn(Pmodulationpar1, "modulation parameter"),
+ rParamZyn(Pmodulationpar2, "modulation parameter"),
+ rParamZyn(Pmodulationpar3, "modulation parameter"),
+
+ //XXX Start of realtime parameters
+ rParamZyn(Prand, "Oscilator Phase Randomness: smaller than 0 is \""
+ "group\", larger than 0 is for each harmonic"),
rParamZyn(Pamprandpower,
"Variance of harmonic randomness"),
rOption(Pamprandtype, rOptions(None, Pow, Sin),
@@ -131,6 +108,7 @@ const rtosc::Ports OscilGen::ports = {
"Adaptive Harmonic Strength"),
rParamZyn(Padaptiveharmonicspar,
"Adaptive Harmonics Postprocessing Power"),
+ //XXX End of realtime parameters
//TODO update to rArray and test
{"phase#128::c", rProp(parameter) rDoc("Sets harmonic phase"),
@@ -215,20 +193,36 @@ const rtosc::Ports OscilGen::ports = {
NULL, [](const char *, rtosc::RtData &d) {
((OscilGen*)d.obj)->useasbase();
}},
- {"prepare:b", rProp(internal) rProp(non-realtime) rProp(pointer) rDoc("Sets prepared fft data"),
+ {"prepare:b", rProp(internal) rProp(realtime) rProp(pointer) rDoc("Sets prepared fft data"),
NULL, [](const char *m, rtosc::RtData &d) {
+ assert(false && "wrong thread...");
+ }}};
+
+#define rForwardCb [](const char *msg, rtosc::RtData &d) {\
+ printf("fowarding...\n"); d.forward();}
+
+const rtosc::ClonePorts OscilGen::realtime_ports{
+ OscilGen::ports, {
+ {"self:", [](const char *, rtosc::RtData &d){
+ d.reply(d.loc, "b", sizeof(d.obj), &d.obj);}},
+ {"Prand::i", rParamICb(Prand)},
+ {"Pamprandpower::i", rParamICb(Pamprandpower)},
+ {"Pamprandtype::i:c", rOptionCb(Pamprandtype)},
+ {"Padaptiveharmonics::i:c", rOptionCb(Padaptiveharmonics)},
+ {"Padaptiveharmonicsbasefreq::i", rParamICb(Padaptiveharmonicsbasefreq)},
+ {"Padaptiveharmonicspower::i", rParamICb(Padaptiveharmonicspower)},
+ {"Padaptiveharmonicspar::i", rParamICb(Padaptiveharmonicspar)},
+ {"prepare:b", [](const char *m, rtosc::RtData &d) {
//fprintf(stderr, "prepare:b got a message from '%s'\n", m);
OscilGen &o = *(OscilGen*)d.obj;
assert(rtosc_argument(m,0).b.len == sizeof(void*));
d.reply("/free", "sb", "fft_t", sizeof(void*), &o.oscilFFTfreqs);
- //fprintf(stderr, "\n\n");
- //fprintf(stderr, "The ID of this of this thread is: %ld\n", (long)pthread_self());
- //fprintf(stderr, "o.oscilFFTfreqs = %p\n", o.oscilFFTfreqs);
- assert(main_thread != pthread_self());
assert(o.oscilFFTfreqs !=*(fft_t**)rtosc_argument(m,0).b.data);
o.oscilFFTfreqs = *(fft_t**)rtosc_argument(m,0).b.data;
}},
-};
+
+ {"*", rForwardCb}
+}};
//operations on FFTfreqs
diff --git a/src/Synth/OscilGen.h b/src/Synth/OscilGen.h
@@ -114,7 +114,8 @@ class OscilGen:public Presets
bool ADvsPAD; //if it is used by ADsynth or by PADsynth
- static const rtosc::Ports ports;
+ static const rtosc::Ports ports;
+ static const rtosc::ClonePorts realtime_ports;
/* Oscillator Frequencies -
* this is different than the hamonics set-up by the user,
diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt
@@ -14,6 +14,7 @@ CXXTEST_ADD_TEST(RandTest RandTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RandTest.h)
CXXTEST_ADD_TEST(PADnoteTest PadNoteTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PadNoteTest.h)
CXXTEST_ADD_TEST(PluginTest PluginTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PluginTest.h)
CXXTEST_ADD_TEST(MiddlewareTest MiddlewareTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareTest.h)
+CXXTEST_ADD_TEST(MessageTest MessageTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MessageTest.h)
CXXTEST_ADD_TEST(UnisonTest UnisonTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UnisonTest.h)
#CXXTEST_ADD_TEST(RtAllocTest RtAllocTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RtAllocTest.h)
CXXTEST_ADD_TEST(AllocatorTest AllocatorTest.cpp
@@ -41,6 +42,9 @@ target_link_libraries(PluginTest zynaddsubfx_core zynaddsubfx_nio
target_link_libraries(MiddlewareTest zynaddsubfx_core zynaddsubfx_nio
zynaddsubfx_gui_bridge
${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
+target_link_libraries(MessageTest zynaddsubfx_core zynaddsubfx_nio
+ zynaddsubfx_gui_bridge
+ ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
target_link_libraries(UnisonTest ${test_lib})
#target_link_libraries(RtAllocTest ${test_lib})
target_link_libraries(AllocatorTest ${test_lib})
diff --git a/src/Tests/MessageTest.h b/src/Tests/MessageTest.h
@@ -0,0 +1,124 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PluginTest.h - CxxTest for embedding zyn
+ Copyright (C) 2013-2013 Mark McCurry
+ Authors: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+#include <cxxtest/TestSuite.h>
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <thread>
+#include <rtosc/thread-link.h>
+#include <unistd.h>
+#include "../Misc/MiddleWare.h"
+#include "../Misc/Master.h"
+#include "../Misc/PresetExtractor.h"
+#include "../Misc/PresetExtractor.cpp"
+#include "../Misc/Util.h"
+#include "../globals.h"
+#include "../UI/NSM.H"
+NSM_Client *nsm = 0;
+MiddleWare *middleware = 0;
+
+using namespace std;
+
+char *instance_name=(char*)"";
+
+#define NUM_MIDDLEWARE 3
+
+class MessageTest:public CxxTest::TestSuite
+{
+ public:
+ Config config;
+ void setUp() {
+ synth = new SYNTH_T;
+ mw = new MiddleWare(std::move(*synth), &config);
+ ms = mw->spawnMaster();
+ }
+
+ void tearDown() {
+ delete mw;
+ delete synth;
+ }
+
+ void notestKitEnable(void)
+ {
+ const char *msg = NULL;
+ mw->transmitMsg("/part0/kit0/Psubenabled", "T");
+ TS_ASSERT(ms->uToB->hasNext());
+ msg = ms->uToB->read();
+ TS_ASSERT_EQUALS(string("/part0/kit0/subpars-data"), msg);
+ TS_ASSERT(ms->uToB->hasNext());
+ msg = ms->uToB->read();
+ TS_ASSERT_EQUALS(string("/part0/kit0/Psubenabled"), msg);
+ }
+
+ void notestBankCapture(void)
+ {
+ mw->transmitMsg("/bank/slots", "");
+ TS_ASSERT(!ms->uToB->hasNext());
+ mw->transmitMsg("/bank/fake", "");
+ TS_ASSERT(ms->uToB->hasNext());
+ const char *msg = ms->uToB->read();
+ TS_ASSERT_EQUALS(string("/bank/fake"), msg);
+ }
+
+ void testOscCopyPaste(void)
+ {
+ //Enable pad synth
+ mw->transmitMsg("/part0/kit0/Ppadenabled", "T");
+
+ TS_ASSERT(ms->uToB->hasNext());
+ ms->applyOscEvent(ms->uToB->read());
+ TS_ASSERT(ms->uToB->hasNext());
+ ms->applyOscEvent(ms->uToB->read());
+ TS_ASSERT(!ms->uToB->hasNext());
+
+ int do_exit = 0;
+ std::thread t([&do_exit,this](){
+ int tries = 0;
+ while(tries < 10000 && do_exit == 0) {
+ if(!ms->uToB->hasNext()) {
+ usleep(500);
+ continue;
+ }
+ const char *msg = ms->uToB->read();
+ printf("RT: handling <%s>\n", msg);
+ ms->applyOscEvent(msg);
+ }});
+
+ //Copy From ADsynth modulator
+ printf("====Copy From ADsynth modulator\n");
+ mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/VoicePar0/FMSmp/");
+
+ //Paste to PADsynth
+ printf("====Paste to PADsynth\n");
+ mw->transmitMsg("/presets/paste", "s", "/part0/kit0/padpars/oscilgen/");
+ do_exit = 1;
+ t.join();
+
+ }
+
+ private:
+ SYNTH_T *synth;
+ MiddleWare *mw;
+ Master *ms;
+};
diff --git a/src/Tests/MiddlewareTest.h b/src/Tests/MiddlewareTest.h
@@ -39,6 +39,8 @@ using namespace std;
char *instance_name=(char*)"";
+#define NUM_MIDDLEWARE 3
+
class PluginTest:public CxxTest::TestSuite
{
public:
@@ -58,19 +60,19 @@ class PluginTest:public CxxTest::TestSuite
delete synth;
synth = NULL;
- for(int i = 0; i < 16; ++i) {
+ for(int i = 0; i < NUM_MIDDLEWARE; ++i) {
synth = new SYNTH_T;
synth->buffersize = 256;
synth->samplerate = 48000;
//synth->alias();
middleware[i] = new MiddleWare(std::move(*synth), &config);
master[i] = middleware[i]->spawnMaster();
- printf("Octave size = %d\n", master[i]->microtonal.getoctavesize());
+ //printf("Octave size = %d\n", master[i]->microtonal.getoctavesize());
}
}
void tearDown() {
- for(int i = 0; i < 16; ++i)
+ for(int i = 0; i < NUM_MIDDLEWARE; ++i)
delete middleware[i];
delete[] outL;
@@ -82,7 +84,7 @@ class PluginTest:public CxxTest::TestSuite
void testInit() {
for(int x=0; x<100; ++x) {
- for(int i=0; i<16; ++i) {
+ for(int i=0; i<NUM_MIDDLEWARE; ++i) {
middleware[i]->tick();
master[i]->GetAudioOutSamples(rand()%1025,
synth->samplerate, outL, outR);
@@ -102,7 +104,7 @@ class PluginTest:public CxxTest::TestSuite
TS_ASSERT_LESS_THAN(0.1f, sum);
}
-
+
string loadfile(string fname) const
{
std::ifstream t(fname.c_str());
@@ -113,7 +115,7 @@ class PluginTest:public CxxTest::TestSuite
void testLoad(void)
{
- for(int i=0; i<16; ++i) {
+ for(int i=0; i<NUM_MIDDLEWARE; ++i) {
middleware[i]->transmitMsg("/load-part", "is", 0, (string(SOURCE_DIR) + "/../../instruments/banks/Organ/0037-Church Organ 1.xiz").c_str());
middleware[i]->tick();
master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
@@ -133,6 +135,6 @@ class PluginTest:public CxxTest::TestSuite
private:
SYNTH_T *synth;
float *outR, *outL;
- MiddleWare *middleware[16];
- Master *master[16];
+ MiddleWare *middleware[NUM_MIDDLEWARE];
+ Master *master[NUM_MIDDLEWARE];
};