commit 175b88b5f00e5d8e0b2bdb5c16d56881da5157c5
parent 96ca7fcab495a0db79da60b099f870afbacb4298
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Mon, 12 Aug 2013 22:43:26 -0400
Enable Master Reloads Via Async Pointer Swap
Diffstat:
8 files changed, 63 insertions(+), 12 deletions(-)
diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp
@@ -28,6 +28,7 @@
#include "../Params/LFOParams.h"
#include "../Effects/EffectMgr.h"
#include "../DSP/FFTwrapper.h"
+#include "../Nio/Nio.h"
#include <rtosc/ports.h>
#include <rtosc/port-sugar.h>
@@ -167,7 +168,7 @@ Master::Master()
}
for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart)
- part[npart] = new Part(µtonal, fft, &mutex);
+ part[npart] = new Part(µtonal, fft);
//Insertion Effects init
for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx)
@@ -412,6 +413,16 @@ void Master::AudioOut(float *outl, float *outr)
int events = 0;
while(uToB->hasNext()) {
const char *msg = uToB->read();
+
+ if(!strcmp(msg, "/load-master")) {
+ Master *this_master = this;
+ Master *new_master = *(Master**)rtosc_argument(msg, 0).b.data;
+ new_master->AudioOut(outl, outr);
+ Nio::masterSwap(new_master);
+ bToU->write("/free", "sb", "Master", sizeof(Master*), &this_master);
+ return;
+ }
+
//XXX yes, this is not realtime safe, but it is useful...
if(strcmp(msg, "/get-vu")) {
fprintf(stdout, "%c[%d;%d;%dm", 0x1B, 0, 5 + 30, 0 + 40);
diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp
@@ -131,6 +131,8 @@ void deallocate(const char *str, void *v)
printf("deallocating a '%s' at '%p'\n", str, v);
if(!strcmp(str, "Part"))
delete (Part*)v;
+ if(!strcmp(str, "Master"))
+ delete (Master*)v;
else if(!strcmp(str, "fft_t"))
delete[] (fft_t*)v;
else
@@ -333,7 +335,7 @@ struct MiddleWareImpl
{
fprintf(stderr, "loading a part!!\n");
//Load the part
- Part *p = new Part(&master->microtonal, master->fft, &master->mutex);
+ Part *p = new Part(&master->microtonal, master->fft);
unsigned npart = rtosc_argument(msg, 0).i;
fprintf(stderr, "Part is stored in '%s'\n", rtosc_argument(msg, 1).s);
p->loadXMLinstrument(rtosc_argument(msg, 1).s);
@@ -360,6 +362,36 @@ struct MiddleWareImpl
uToB->write("/load-part", "ib", npart, sizeof(Part*), &p);
}
+ //Well, you don't get much crazier than changing out all of your RT
+ //structures at once... TODO error handling
+ void loadMaster(const char *filename)
+ {
+ Master *m = new Master();
+ m->loadXML(filename);
+ m->applyparameters();
+
+ //Update resource locator table
+ objmap.clear();
+ for(int i=0; i < NUM_MIDI_PARTS; ++i) {
+ for(int j=0; j < NUM_KIT_ITEMS; ++j) {
+ objmap["/part"+to_s(i)+"/kit"+to_s(j)+"/padpars/"] =
+ m->part[i]->kit[j].padpars;
+ objmap["/part"+to_s(i)+"/kit"+to_s(j)+"/padpars/oscil/"] =
+ m->part[i]->kit[j].padpars->oscilgen;
+ for(int k=0; k<NUM_VOICES; ++k) {
+ objmap["/part"+to_s(i)+"/kit"+to_s(j)+"/adpars/voice"+to_s(k)+"/oscil/"] =
+ m->part[i]->kit[j].adpars->VoicePar[k].OscilSmp;
+ objmap["/part"+to_s(i)+"/kit"+to_s(j)+"/adpars/voice"+to_s(k)+"/oscil-mod/"] =
+ m->part[i]->kit[j].adpars->VoicePar[k].FMSmp;
+ }
+ }
+ }
+ //Give it to the backend and wait for the old part to return for
+ //deallocation
+ //printf("writing something to the location called '%s'\n", msg);
+ uToB->write("/load-master", "b", sizeof(Master*), &m);
+ }
+
void tick(void)
{
osc_check(cb, ui);
@@ -459,6 +491,8 @@ struct MiddleWareImpl
uToB->raw_write(msg);
} else //just forward the message
uToB->raw_write(msg);
+ } else if(strstr(msg, "load_xmz")) {
+ loadMaster(rtosc_argument(msg,0).s);
} else if(strstr(msg, "load-part"))
loadPart(msg, master);
else
diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp
@@ -108,11 +108,10 @@ static Ports kitPorts = {
Ports &Part::Kit::ports = kitPorts;
Ports &Part::ports = partPorts;
-Part::Part(Microtonal *microtonal_, FFTwrapper *fft_, pthread_mutex_t *mutex_)
+Part::Part(Microtonal *microtonal_, FFTwrapper *fft_)
{
microtonal = microtonal_;
fft = fft_;
- mutex = mutex_;
pthread_mutex_init(&load_mutex, NULL);
partoutl = new float [synth->buffersize];
partoutr = new float [synth->buffersize];
diff --git a/src/Misc/Part.h b/src/Misc/Part.h
@@ -46,9 +46,8 @@ class Part
public:
/**Constructor
* @param microtonal_ Pointer to the microtonal object
- * @param fft_ Pointer to the FFTwrapper
- * @param mutex_ Pointer to the master pthread_mutex_t*/
- Part(Microtonal *microtonal_, FFTwrapper *fft_, pthread_mutex_t *mutex_);
+ * @param fft_ Pointer to the FFTwrapper*/
+ Part(Microtonal *microtonal_, FFTwrapper *fft_);
/**Destructor*/
~Part();
@@ -155,7 +154,6 @@ class Part
bool Pefxbypass[NUM_PART_EFX]; //if the effects are bypassed
- pthread_mutex_t *mutex;
pthread_mutex_t load_mutex;
int lastnote;
diff --git a/src/Nio/Nio.cpp b/src/Nio/Nio.cpp
@@ -122,6 +122,12 @@ void Nio::preferedSampleRate(unsigned &)
{}
#endif
+void Nio::masterSwap(Master *master)
+{
+ in->setMaster(master);
+ out->setMaster(master);
+}
+
void Nio::waveNew(class WavFile *wave)
{
out->wave->newFile(wave);
diff --git a/src/Nio/Nio.h b/src/Nio/Nio.h
@@ -33,6 +33,8 @@ namespace Nio
//Get the prefered sample rate from jack (if running)
void preferedSampleRate(unsigned &rate);
+ //Complete Master Swaps to ONLY BE CALLED FROM RT CONTEXT
+ void masterSwap(Master *master);
//Wave writing
void waveNew(class WavFile *wave);
diff --git a/src/UI/MasterUI.fl b/src/UI/MasterUI.fl
@@ -1009,7 +1009,12 @@ if (result==-10) fl_alert("Error: Could not load the file\\nbecause it is not an
}
Fl_Group simplelistitemgroup {
private xywh {125 65 215 145} box UP_FRAME
+ class Fl_Osc_Group
} {
+ Fl_Box {} {
+ xywh {0 0 0 0}
+ code0 {simplelistitemgroup->ext = "part0/";}
+ }
Fl_Button partname {
callback {if ((int)bankui->cbwig->value()!=(npart+1)){
bankui->cbwig->value(npart+1);
diff --git a/src/main.cpp b/src/main.cpp
@@ -115,10 +115,6 @@ void initprogram(void)
*/
void exitprogram()
{
- //ensure that everything has stopped with the mutex wait
- pthread_mutex_lock(&master->mutex);
- pthread_mutex_unlock(&master->mutex);
-
Nio::stop();
GUI::destroyUi(gui);