zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

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:
Msrc/Misc/Master.cpp | 13++++++++++++-
Msrc/Misc/MiddleWare.cpp | 36+++++++++++++++++++++++++++++++++++-
Msrc/Misc/Part.cpp | 3+--
Msrc/Misc/Part.h | 6++----
Msrc/Nio/Nio.cpp | 6++++++
Msrc/Nio/Nio.h | 2++
Msrc/UI/MasterUI.fl | 5+++++
Msrc/main.cpp | 4----
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(&microtonal, fft, &mutex); + part[npart] = new Part(&microtonal, 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);