commit 2a655e26a6eb8a2685cbc41edfebdf9dbab4347a
parent 6a1b57fc8af7d5f20275730ed1677b0611f0c22a
Author: Johannes Lorenz <johannes89@ist-einmalig.de>
Date: Fri, 10 Jul 2015 20:07:50 +0200
Merge from Master (Release 2.5.1).
Diffstat:
31 files changed, 510 insertions(+), 177 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
project(zynaddsubfx)
-set(VERSION "2.5.0")
+set(VERSION "2.5.1")
#Include RTOSC
diff --git a/HISTORY.txt b/HISTORY.txt
@@ -1,10 +1,10 @@
-2.5.1 (25 May 2015)
+2.5.1 (4 July 2015)
- Add Colorized CMake Configuration
- Add PID option for jack
- Add OSC port option
- Add MIDI unlearn
- Add External UI Compilation
- - Add Split Pitchblend
+ - Add Split Pitchbend
- Fix No Install NTK Build
- Fix Linker Issues
- Fix Presets/Copy/Paste
diff --git a/src/Effects/EffectMgr.cpp b/src/Effects/EffectMgr.cpp
@@ -45,7 +45,7 @@ static const rtosc::Ports local_ports = {
rSelf(EffectMgr),
rPaste,
rRecurp(filterpars, "Filter Parameter for Dynamic Filter"),
- {"parameter#64::i", rProp(alias) rDoc("Parameter Accessor"), NULL,
+ {"parameter#128::i", rProp(alias) rDoc("Parameter Accessor"), NULL,
[](const char *msg, rtosc::RtData &d)
{
EffectMgr *eff = (EffectMgr*)d.obj;
@@ -54,8 +54,10 @@ static const rtosc::Ports local_ports = {
if(!rtosc_narguments(msg))
d.reply(d.loc, "i", eff->geteffectparrt(atoi(mm)));
- else
+ else {
eff->seteffectparrt(atoi(mm), rtosc_argument(msg, 0).i);
+ d.broadcast(d.loc, "i", eff->geteffectparrt(atoi(mm)));
+ }
}},
{"preset::i", rProp(alias) rDoc("Effect Preset Selector"), NULL,
[](const char *msg, rtosc::RtData &d)
@@ -63,8 +65,10 @@ static const rtosc::Ports local_ports = {
EffectMgr *eff = (EffectMgr*)d.obj;
if(!rtosc_narguments(msg))
d.reply(d.loc, "i", eff->getpreset());
- else
+ else {
eff->changepresetrt(rtosc_argument(msg, 0).i);
+ d.broadcast(d.loc, "i", eff->getpreset());
+ }
}},
{"eq-coeffs:", rProp(internal) rDoc("Get equalizer Coefficients"), NULL,
[](const char *, rtosc::RtData &d)
@@ -83,9 +87,10 @@ static const rtosc::Ports local_ports = {
{"efftype::i", rDoc("Get Effect Type"), NULL, [](const char *m, rtosc::RtData &d)
{
EffectMgr *eff = (EffectMgr*)d.obj;
- if(rtosc_narguments(m))
+ if(rtosc_narguments(m)) {
eff->changeeffectrt(rtosc_argument(m,0).i);
- else
+ d.broadcast(d.loc, "i", eff->nefx);
+ } else
d.reply(d.loc, "i", eff->nefx);
}},
{"efftype:b", rProp(internal) rDoc("Pointer swap EffectMgr"), NULL,
@@ -143,7 +148,7 @@ void EffectMgr::defaults(void)
}
//Change the effect
-void EffectMgr::changeeffectrt(int _nefx)
+void EffectMgr::changeeffectrt(int _nefx, bool avoidSmash)
{
cleanup();
if(nefx == _nefx && efx != NULL)
@@ -187,6 +192,10 @@ void EffectMgr::changeeffectrt(int _nefx)
if(efx)
filterpars = efx->filterpars;
+
+ if(!avoidSmash)
+ for(int i=0; i<128; ++i)
+ settings[i] = geteffectparrt(i);
}
void EffectMgr::changeeffect(int _nefx)
@@ -205,8 +214,8 @@ int EffectMgr::geteffect(void)
// Initialize An Effect in RT context
void EffectMgr::init(void)
{
- changeeffectrt(nefx);
- changepresetrt(preset);
+ changeeffectrt(nefx, true);
+ changepresetrt(preset, true);
for(int i=0; i<128; ++i)
seteffectparrt(i, settings[i]);
}
@@ -242,11 +251,14 @@ void EffectMgr::changepreset(unsigned char npreset)
}
// Change the preset of the current effect
-void EffectMgr::changepresetrt(unsigned char npreset)
+void EffectMgr::changepresetrt(unsigned char npreset, bool avoidSmash)
{
preset = npreset;
if(efx)
efx->setpreset(npreset);
+ if(!avoidSmash)
+ for(int i=0; i<128; ++i)
+ settings[i] = geteffectparrt(i);
}
//Change a parameter of the current effect
@@ -370,11 +382,10 @@ void EffectMgr::setdryonly(bool value)
void EffectMgr::paste(EffectMgr &e)
{
- changeeffectrt(e.nefx);
- changepresetrt(e.preset);
- for(int i=0;i<128;++i){
+ changeeffectrt(e.nefx, true);
+ changepresetrt(e.preset, true);
+ for(int i=0;i<128;++i)
seteffectparrt(e.settings[i], i);
- }
}
void EffectMgr::add2XML(XMLwrapper *xml)
diff --git a/src/Effects/EffectMgr.h b/src/Effects/EffectMgr.h
@@ -55,11 +55,11 @@ class EffectMgr:public Presets
void kill(void) REALTIME;
void cleanup(void) REALTIME;
- void changeeffectrt(int nefx_) REALTIME;
+ void changeeffectrt(int nefx_, bool avoidSmash=false) REALTIME;
void changeeffect(int nefx_) NONREALTIME;
int geteffect(void);
void changepreset(unsigned char npreset) NONREALTIME;
- void changepresetrt(unsigned char npreset) REALTIME;
+ void changepresetrt(unsigned char npreset, bool avoidSmash=false) REALTIME;
unsigned char getpreset(void);
void seteffectpar(int npar, unsigned char value) NONREALTIME;
void seteffectparrt(int npar, unsigned char value) REALTIME;
diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp
@@ -8,6 +8,7 @@
#include <rtosc/undo-history.h>
#include <rtosc/thread-link.h>
#include <rtosc/ports.h>
+#include <rtosc/typed-message.h>
#include <lo/lo.h>
#include <unistd.h>
@@ -28,6 +29,7 @@
#include "../Params/PADnoteParameters.h"
#include "../DSP/FFTwrapper.h"
#include "../Synth/OscilGen.h"
+#include "../Nio/Nio.h"
#include <string>
#include <future>
@@ -196,7 +198,7 @@ void preparePadSynth(string path, PADnoteParameters *p, rtosc::ThreadLink *uToB)
* - Load Bank *
* - Refresh List of Banks *
*****************************************************************************/
-void refreshBankView(const Bank &bank, unsigned loc, Fl_Osc_Interface *osc)
+void refreshBankView(const Bank &bank, unsigned loc, std::function<void(const char*)> cb)
{
if(loc >= BANK_SIZE)
return;
@@ -208,15 +210,12 @@ void refreshBankView(const Bank &bank, unsigned loc, Fl_Osc_Interface *osc)
errx(1, "Failure to handle bank update properly...");
- if (osc)
- osc->tryLink(response);
+ if(cb)
+ cb(response);
}
-void bankList(Bank &bank, Fl_Osc_Interface *osc)
+void bankList(Bank &bank, std::function<void(const char*)> cb)
{
- if (! osc)
- return;
-
char response[2048];
int i = 0;
@@ -224,35 +223,35 @@ void bankList(Bank &bank, Fl_Osc_Interface *osc)
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 (osc)
- osc->tryLink(response);
+ if(cb)
+ cb(response);
}
}
-void rescanForBanks(Bank &bank, Fl_Osc_Interface *osc)
+void rescanForBanks(Bank &bank, std::function<void(const char*)> cb)
{
bank.rescanforbanks();
- bankList(bank, osc);
+ bankList(bank, cb);
}
-void loadBank(Bank &bank, int pos, Fl_Osc_Interface *osc)
+void loadBank(Bank &bank, int pos, std::function<void(const char*)> cb)
{
if(bank.bankpos != pos) {
bank.bankpos = pos;
bank.loadbank(bank.banks[pos].dir);
for(int i=0; i<BANK_SIZE; ++i)
- refreshBankView(bank, i, osc);
+ refreshBankView(bank, i, cb);
}
}
-void bankPos(Bank &bank, Fl_Osc_Interface *osc)
+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(osc)
- osc->tryLink(response);
+ if(cb)
+ cb(response);
}
/*****************************************************************************
@@ -348,14 +347,14 @@ struct NonRtObjStore
{
std::string base = "/part"+to_s(i)+"/kit"+to_s(j)+"/";
for(int k=0; k<NUM_VOICES; ++k) {
- std::string nbase = base+"adpars/voice"+to_s(k)+"/";
+ std::string nbase = base+"adpars/VoicePar"+to_s(k)+"/";
if(adpars) {
auto &nobj = adpars->VoicePar[k];
- objmap[nbase+"oscil/"] = nobj.OscilSmp;
- objmap[nbase+"mod-oscil/"] = nobj.FMSmp;
+ objmap[nbase+"OscilSmp/"] = nobj.OscilSmp;
+ objmap[nbase+"FMSmp/"] = nobj.FMSmp;
} else {
- objmap[nbase+"oscil/"] = nullptr;
- objmap[nbase+"mod-oscil/"] = nullptr;
+ objmap[nbase+"OscilSmp/"] = nullptr;
+ objmap[nbase+"FMSmp/"] = nullptr;
}
}
}
@@ -366,10 +365,10 @@ struct NonRtObjStore
for(int k=0; k<NUM_VOICES; ++k) {
if(padpars) {
objmap[base+"padpars/"] = padpars;
- objmap[base+"padpars/oscil/"] = padpars->oscilgen;
+ objmap[base+"padpars/oscilgen/"] = padpars->oscilgen;
} else {
objmap[base+"padpars/"] = nullptr;
- objmap[base+"padpars/oscil/"] = nullptr;
+ objmap[base+"padpars/oscilgen/"] = nullptr;
}
}
}
@@ -427,6 +426,38 @@ struct ParamStore
PADnoteParameters *pad[NUM_MIDI_PARTS][NUM_KIT_ITEMS];
};
+//XXX perhaps move this to Nio
+//(there needs to be some standard Nio stub file for this sort of stuff)
+namespace Nio
+{
+ using std::get;
+ using rtosc::rtMsg;
+ rtosc::Ports ports = {
+ {"sink-list:", 0, 0, [](const char *msg, rtosc::RtData &d) {
+ auto list = Nio::getSinks();
+ char *ret = rtosc_splat(d.loc, list);
+ d.reply(ret);
+ delete [] ret;
+ }},
+ {"source-list:", 0, 0, [](const char *msg, rtosc::RtData &d) {
+ auto list = Nio::getSources();
+ char *ret = rtosc_splat(d.loc, list);
+ d.reply(ret);
+ delete [] ret;
+ }},
+ {"source::s", 0, 0, [](const char *msg, rtosc::RtData &d) {
+ if(rtosc_narguments(msg) == 0)
+ d.reply(d.loc, "s", Nio::getSource().c_str());
+ else if(rtMsg<const char*> m{msg})
+ Nio::setSource(get<0>(m));}},
+ {"sink::s", 0, 0, [](const char *msg, rtosc::RtData &d) {
+ if(rtosc_narguments(msg) == 0)
+ d.reply(d.loc, "s", Nio::getSink().c_str());
+ else if(rtMsg<const char*> m{msg})
+ Nio::setSink(get<0>(m));}},
+ };
+}
+
/* Implementation */
class MiddleWareImpl
{
@@ -787,6 +818,22 @@ public:
}
}
+ 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];
@@ -1181,8 +1228,8 @@ void MiddleWareImpl::kitEnable(int part, int kit, int type)
*/
void MiddleWareImpl::handleMsg(const char *msg)
{
- assert(!strstr(msg,"free"));
assert(msg && *msg && rindex(msg, '/')[1]);
+ assert(strstr(msg,"free") == NULL || strstr(rtosc_argument_string(msg), "b") == NULL);
assert(strcmp(msg, "/part0/Psysefxvol"));
assert(strcmp(msg, "/Penabled"));
assert(strcmp(msg, "part0/part0/Ppanning"));
@@ -1203,16 +1250,22 @@ void MiddleWareImpl::handleMsg(const char *msg)
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){this->bToUhandle(msg, 1);};
+
if(!strcmp(msg, "/refresh_bank") && !strcmp(rtosc_argument_string(msg), "i")) {
- refreshBankView(master->bank, rtosc_argument(msg,0).i, osc);
+ refreshBankView(master->bank, rtosc_argument(msg,0).i, bank_cb);
} else if(!strcmp(msg, "/bank-list") && !strcmp(rtosc_argument_string(msg), "")) {
- bankList(master->bank, osc);
+ bankList(master->bank, bank_cb);
} else if(!strcmp(msg, "/rescanforbanks") && !strcmp(rtosc_argument_string(msg), "")) {
- rescanForBanks(master->bank, osc);
+ rescanForBanks(master->bank, bank_cb);
} else if(!strcmp(msg, "/loadbank") && !strcmp(rtosc_argument_string(msg), "i")) {
- loadBank(master->bank, rtosc_argument(msg, 0).i, osc);
+ loadBank(master->bank, rtosc_argument(msg, 0).i, bank_cb);
} else if(!strcmp(msg, "/loadbank") && !strcmp(rtosc_argument_string(msg), "")) {
- bankPos(master->bank, osc);
+ 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/")) {
@@ -1257,6 +1310,8 @@ void MiddleWareImpl::handleMsg(const char *msg)
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);
uToB->raw_write(msg);
@@ -1382,7 +1437,7 @@ void MiddleWare::activeUrl(std::string u)
{
impl->last_url = u;
}
-
+
const SYNTH_T &MiddleWare::getSynth(void) const
{
return impl->synth;
diff --git a/src/Misc/Util.cpp b/src/Misc/Util.cpp
@@ -42,6 +42,8 @@
#include <err.h>
#endif
+#include <rtosc/rtosc.h>
+
prng_t prng_state = 0x1234;
/*
@@ -210,3 +212,21 @@ float cinterpolate(const float *data, size_t len, float pos)
const float leftness = pos - l_pos;
return data[l_pos] * leftness + data[r_pos] * (1.0f - leftness);
}
+
+char *rtosc_splat(const char *path, std::set<std::string> v)
+{
+ char argT[v.size()+1];
+ rtosc_arg_t arg[v.size()];
+ unsigned i=0;
+ for(auto vv : v) {
+ argT[i] = 's';
+ arg[i].s = vv.c_str();
+ i++;
+ }
+ argT[v.size()] = 0;
+
+ size_t len = rtosc_amessage(0, 0, path, argT, arg);
+ char *buf = new char[len];
+ rtosc_amessage(buf, len, path, argT, arg);
+ return buf;
+}
diff --git a/src/Misc/Util.h b/src/Misc/Util.h
@@ -27,6 +27,7 @@
#include <sstream>
#include <stdint.h>
#include <algorithm>
+#include <set>
using std::min;
using std::max;
@@ -146,6 +147,8 @@ static inline void nullify(T &t) {delete t; t = NULL; }
template<class T>
static inline void arrayNullify(T &t) {delete [] t; t = NULL; }
+char *rtosc_splat(const char *path, std::set<std::string>);
+
/**
* Port macros - these produce easy and regular port definitions for common
* types
diff --git a/src/Misc/XMLwrapper.cpp b/src/Misc/XMLwrapper.cpp
@@ -98,7 +98,7 @@ XMLwrapper::XMLwrapper()
{
version.Major = 2;
version.Minor = 5;
- version.Revision = 0;
+ version.Revision = 1;
minimal = true;
diff --git a/src/Output/DSSIaudiooutput.cpp b/src/Output/DSSIaudiooutput.cpp
@@ -37,6 +37,7 @@
#include <string.h>
#include <limits.h>
+using std::set;
using std::string;
using std::vector;
@@ -51,6 +52,12 @@ namespace Nio {
void waveStart(void){}
void waveStop(void){}
void waveEnd(void){}
+ bool setSource(string){return true;}
+ bool setSink(string){return true;}
+ set<string> getSources(void){return set<string>();}
+ set<string> getSinks(void){return set<string>();}
+ string getSource(void){return "";}
+ string getSink(void){return "";}
}
//
diff --git a/src/Params/EnvelopeParams.cpp b/src/Params/EnvelopeParams.cpp
@@ -34,7 +34,11 @@ using namespace rtosc;
static const rtosc::Ports localPorts = {
rSelf(EnvelopeParams),
rPaste,
+#undef rChangeCb
+#define rChangeCb if(!obj->Pfreemode) obj->converttofree();
rToggle(Pfreemode, "Complex Envelope Definitions"),
+#undef rChangeCb
+#define rChangeCb
rParamZyn(Penvpoints, rProp(internal), "Number of points in complex definition"),
rParamZyn(Penvsustain, rProp(internal), "Location of the sustain point"),
rParams(Penvdt, MAX_ENVELOPE_POINTS, "Envelope Delay Times"),
diff --git a/src/Tests/guitar-adnote.xmz b/src/Tests/guitar-adnote.xmz
@@ -2,7 +2,7 @@
<?xml version="1.0f" encoding="UTF-8"?>
<!DOCTYPE ZynAddSubFX-data>
<ZynAddSubFX-data version-major="2" version-minor="5"
-version-revision="0" ZynAddSubFX-author="Nasca Octavian Paul">
+version-revision="1" ZynAddSubFX-author="Nasca Octavian Paul">
<INFORMATION>
<par_bool name="PADsynth_used" value="yes" />
</INFORMATION>
diff --git a/src/UI/ADnoteUI.fl b/src/UI/ADnoteUI.fl
@@ -119,7 +119,7 @@ class ADvoicelistitem {open : {public Fl_Osc_Group}
class Fl_Osc_Output
}
Fl_Slider voicedetune {
- callback {//detunevalueoutput->do_callback();}
+ callback {detunevalueoutput->update();}
tooltip {Fine Detune (cents)} xywh {315 5 185 20} type {Horz Knob} box NO_BOX minimum -8192 maximum 8191 step 1
code0 {o->init("PDetune",'i');}
class Fl_Osc_Slider
@@ -253,7 +253,7 @@ o->redraw();}
class Fl_Osc_Counter
}
Fl_Slider {} {
- callback {o->oscWrite("detunevalue");}
+ callback {fmdetunevalueoutput->update();}
tooltip {Fine Detune (cents)} xywh {590 245 155 15} type {Horz Knob} box NO_BOX minimum -8192 maximum 8191 step 1
code0 {o->init("PFMDetune", 'i');}
class Fl_Osc_Slider
@@ -266,7 +266,7 @@ o->redraw();}
}
Fl_Choice {} {
label {Detune Type}
- callback {fmdetunevalueoutput->do_callback();} open
+ callback {fmdetunevalueoutput->update();} open
xywh {540 280 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10
code0 {o->add("Default");o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");}
code1 {o->init("PFMDetuneType");}
@@ -466,7 +466,7 @@ o->redraw();}
class Fl_Osc_Counter
}
Fl_Slider {} {
- callback {detunevalueoutput->do_callback();}
+ callback {detunevalueoutput->update();}
tooltip {Fine Detune (cents)} xywh {58 287 392 13} type {Horz Knob} box NO_BOX minimum -8192 maximum 8191 step 1
code0 {o->init("PDetune", 'i');}
class Fl_Osc_Slider
@@ -493,7 +493,7 @@ o->redraw();}
}
Fl_Choice {} {
label {Detune Type}
- callback {detunevalueoutput->do_callback();} open
+ callback {detunevalueoutput->update();} open
xywh {455 320 70 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10
code0 {o->add("Default");o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");}
code1 {o->init("PDetuneType");}
@@ -866,7 +866,7 @@ class ADnoteUI {open : {public PresetsUI_}
class LFOUI
} {}
Fl_Slider detune {
- callback {o->oscWrite("detunevalue");}
+ callback {detunevalueoutput->update();}
tooltip {Fine Detune (cents)} xywh {60 300 385 15} type {Horz Knob} box NO_BOX minimum -8192 maximum 8191 step 1
code0 {o->init("PDetune", 'i');}
class Fl_Osc_Slider
@@ -879,7 +879,7 @@ class ADnoteUI {open : {public PresetsUI_}
}
Fl_Choice detunetype {
label {Detune Type}
- callback {o->oscWrite("detunevalue");} open
+ callback {detunevalueoutput->update();} open
xywh {455 340 75 15} down_box BORDER_BOX labelsize 10 align 5 textfont 1 textsize 10
code0 {o->add("L35cents");o->add("L10cents");o->add("E100cents");o->add("E1200cents");}
code1 {o->init("PDetuneType",1);}
diff --git a/src/UI/BankView.cpp b/src/UI/BankView.cpp
@@ -15,8 +15,8 @@ BankList::BankList(int x,int y, int w, int h, const char *label)
void BankList::init(std::string path)
{
ext = path;
+ oscRegister("bank-list");
oscRegister(path.c_str());
- osc->createLink("/bank-list", this);
}
void BankList::OSC_raw(const char *msg)
diff --git a/src/UI/CMakeLists.txt b/src/UI/CMakeLists.txt
@@ -67,6 +67,7 @@ add_library(zynaddsubfx_gui STATIC
Fl_Osc_Output.cpp
Fl_Osc_Counter.cpp
Fl_Osc_Input.cpp
+ Fl_Osc_Numeric_Input.cpp
Fl_Osc_Value.cpp
Fl_Osc_ListView.cpp
Fl_Resonance_Graph.cpp
diff --git a/src/UI/ConfigUI.fl b/src/UI/ConfigUI.fl
@@ -29,12 +29,18 @@ decl {\#include "Fl_Osc_Counter.H"} {public local
decl {\#include "Fl_Osc_Choice.H"} {public local
}
+decl {\#include "Osc_IntModel.h"} {public local
+}
+
decl {\#include "Fl_Osc_Check.H"} {public local
}
decl {\#include "Fl_Osc_Input.H"} {public local
}
+decl {\#include "Fl_Osc_Numeric_Input.H"} {public local
+}
+
decl {\#include "Fl_Osc_ListView.H"} {public local
}
@@ -71,14 +77,14 @@ class ConfigUI {} {
Fl_Input samplerateinput {
xywh {115 50 60 20} type Int textfont 1
code0 {o->init("cfg.SampleRate");}
- class Fl_Osc_Input
+ class Fl_Osc_Numeric_Input
}
}
Fl_Input {} {
label {Buffer Size}
tooltip {Internal Sound Buffer Size (samples)} xywh {190 45 60 20} type Int labelsize 11 align 129 textfont 1
code0 {o->init("cfg.SoundBufferSize");}
- class Fl_Osc_Input
+ class Fl_Osc_Numeric_Input
}
Fl_Check_Button {} {
label {Swap Stereo }
@@ -86,11 +92,12 @@ class ConfigUI {} {
code0 {o->init("cfg.SwapStereo");}
class Fl_Osc_Check
}
- Fl_Choice {} {
+ Fl_Choice oscilsize_widget {
label OscilSize
+ callback{
+ oscilsize->updateVal((int)(o->value()+7));
+ }
tooltip {ADSynth Oscillator Size (samples)} xywh {175 80 75 20} down_box BORDER_BOX labelfont 1 labelsize 11 textsize 10
- code0 {o->init("cfg.OscilPower");}
- class Fl_Osc_Choice
} {
MenuItem {} {
label 128
@@ -279,7 +286,14 @@ activatebutton_presetdir(true);}
Function {ConfigUI(Fl_Osc_Interface *osc_)} {} {
code {
osc = osc_;
- make_window();} {}
+ make_window();
+ oscilsize = new Osc_IntModel(osc);
+ oscilsize->callback = [this](int i){
+ oscilsize_widget->value(i-7);
+ };
+ oscilsize->update("/config/cfg.OscilPower");
+
+ } {}
}
Function {activatebutton_rootdir(bool active)} {} {
code {if (active) {
@@ -308,4 +322,6 @@ activatebutton_presetdir(true);}
}
decl {class Fl_Osc_Interface *osc;} {public local
}
+ decl {class Osc_IntModel *oscilsize;} {public local
+ }
}
diff --git a/src/UI/EnvelopeFreeEdit.cpp b/src/UI/EnvelopeFreeEdit.cpp
@@ -26,7 +26,7 @@ void EnvelopeFreeEdit::init(void)
void EnvelopeFreeEdit::OSC_raw(const char *msg)
{
const char *args = rtosc_argument_string(msg);
- if(strstr(msg,"Penvpoints") && !strcmp(args, "c")) {
+ if(strstr(msg,"Penvpoints") && !strcmp(args, "i")) {
Penvpoints = rtosc_argument(msg, 0).i;
} else if(strstr(msg,"Penvdt") && !strcmp(args, "b")) {
rtosc_blob_t b = rtosc_argument(msg, 0).b;
@@ -36,7 +36,7 @@ void EnvelopeFreeEdit::OSC_raw(const char *msg)
rtosc_blob_t b = rtosc_argument(msg, 0).b;
assert(b.len == MAX_ENVELOPE_POINTS);
memcpy(Penvval, b.data, MAX_ENVELOPE_POINTS);
- } else if(strstr(msg,"Penvsustain") && !strcmp(args, "c")) {
+ } else if(strstr(msg,"Penvsustain") && !strcmp(args, "i")) {
Penvsustain = rtosc_argument(msg, 0).i;
}
redraw();
@@ -202,7 +202,10 @@ int EnvelopeFreeEdit::handle(int event)
else
Penvdt[currentpoint]=0;
- oscWrite(to_s("Penvdt")+to_s(currentpoint), "c", newdt);
+ oscWrite(to_s("Penvval")+to_s(currentpoint), "c", ny);
+ oscWrite(to_s("Penvdt")+to_s(currentpoint), "c", newdt);
+ oscWrite("Penvdt","");
+ oscWrite("Penvval","");
redraw();
if(pair)
diff --git a/src/UI/EnvelopeUI.fl b/src/UI/EnvelopeUI.fl
@@ -126,11 +126,15 @@ sustaincounter->update();
}
Fl_Check_Button freemodebutton {
label FreeMode
- callback {reinit();
+ callback {
+ o->oscWrite("Pfreemode", o->value() ? "T" : "F");
+ reinit(o->value());
freeedit->lastpoint=-1;
freeedit->redraw();}
tooltip {Enable or disable the freemode} xywh {10 155 95 20} labelsize 11
+ code0{o->init("Pfreemode");}
+ class Fl_Osc_Check
}
Fl_Check_Button forcedreleasecheck {
label frcR
@@ -503,7 +507,6 @@ envfree->redraw();}
base = base_;
ext = ext_;
Envmode = env_type;
- Pfreemode = false;
Penvsustain = false;
Penvpoints = 3;
Penvstretch = 0;
@@ -537,59 +540,60 @@ refresh();} {}
code {Fl_Osc_Group::rebase(new_base);
freemodeeditwindow->rebase(new_base+ext);} {}
}
- Function {reinit()} {open
+ Function {reinit(bool Pfreemode)} {open
} {
- code {if(Pfreemode){
- int answer=fl_choice("Disable the free mode of the Envelope?","No","Yes",NULL);
- freemodebutton->value(Pfreemode);
- if (answer==0)
- return;
-};
-
-Pfreemode = !Pfreemode;
-
-hide();
-const int winx=freemodeeditwindow->x();
-const int winy=freemodeeditwindow->y();
-
-freemodeeditwindow->hide();
-
-envwindow->hide();
-Fl_Group *par=envwindow->parent();
-par->hide();
-
-
-refresh();
-envwindow->show();
-par->redraw();
-
-par->show();
-show();
-freemodeeditwindow->position(winx,winy);
-freemodeeditwindow->show();
-
-if (Pfreemode) {
- freemodebutton->value(1);
- addpoint->show();
- deletepoint->show();
- forcedreleasecheck->show();
- sustaincounter->show();
- envstretchdial->show();
-} else{
- freemodebutton->value(0);
- addpoint->hide();
- deletepoint->hide();
- forcedreleasecheck->hide();
- sustaincounter->hide();
- envstretchdial->hide();
-};
+ code {
+ //if(!Pfreemode){
+ // int answer=fl_choice("Disable the free mode of the Envelope?","No","Yes",NULL);
+ // freemodebutton->value(Pfreemode);
+ // if (answer==0)
+ // return;
+ //};
+ freeedit->update();
+
+ hide();
+ const int winx=freemodeeditwindow->x();
+ const int winy=freemodeeditwindow->y();
+
+ bool reshow = freemodeeditwindow->visible();
+ freemodeeditwindow->hide();
+
+ envwindow->hide();
+ Fl_Group *par=envwindow->parent();
+ par->hide();
+
+
+ refresh();
+ envwindow->show();
+ par->redraw();
+
+ par->show();
+ show();
+ freemodeeditwindow->position(winx,winy);
+ if(reshow)
+ freemodeeditwindow->show();
+
+ if (Pfreemode) {
+ freemodebutton->value(1);
+ addpoint->show();
+ deletepoint->show();
+ forcedreleasecheck->show();
+ sustaincounter->show();
+ envstretchdial->show();
+ } else{
+ freemodebutton->value(0);
+ addpoint->hide();
+ deletepoint->hide();
+ forcedreleasecheck->hide();
+ sustaincounter->hide();
+ envstretchdial->hide();
+ };
} {selected
}
}
Function {refresh()} {open
} {
- code {freemodebutton->value(Pfreemode);
-
+ code {
sustaincounter->value(Penvsustain);
sustaincounter->maximum(Penvpoints-2);
@@ -598,7 +602,7 @@ if (Pfreemode) {
linearenvelopecheck->value(Plinearenvelope);
//Conditionally display widgets
- if(Pfreemode) {
+ if(freemodebutton->value()) {
freemodebutton->value(1);
addpoint->show();
deletepoint->show();
@@ -614,14 +618,14 @@ linearenvelopecheck->value(Plinearenvelope);
envstretchdial->hide();
}
- if(Pfreemode || Envmode>2)
+ if(freemodebutton->value() || Envmode>2)
linearenvelopecheck->hide();
else
linearenvelopecheck->show();
forcedreleasecheck->value(Pforcedrelease);
-if (Pfreemode==0){
+if (freemodebutton->value()==0){
addpoint->hide();
deletepoint->hide();
} else {
@@ -635,7 +639,7 @@ envADSRfilter->hide();
envASRbw->hide();
envfree->hide();
-if (Pfreemode==0){
+if (freemodebutton->value()==0){
switch(Envmode){
case 1:
case 2:
@@ -664,8 +668,6 @@ envwindow->show();} {}
}
decl {int Envmode;} {private local
}
- decl {int Pfreemode;} {private local
- }
decl {int Penvsustain;} {private local
}
decl {int Penvpoints;} {private local
diff --git a/src/UI/Fl_Osc_Numeric_Input.H b/src/UI/Fl_Osc_Numeric_Input.H
@@ -0,0 +1,17 @@
+#pragma once
+#include <FL/Fl_Input.H>
+#include "Fl_Osc_Widget.H"
+
+class Fl_Osc_Numeric_Input: public Fl_Input, public Fl_Osc_Widget
+{
+ public:
+ Fl_Osc_Numeric_Input(int X, int Y, int W, int H, const char *label = NULL);
+ virtual ~Fl_Osc_Numeric_Input(void);
+
+ //Normal Initialization
+ void init(const char *path);
+
+ virtual void OSC_value(int i) override;
+ virtual void OSC_value(float f) override;
+ static void numeric_callback(Fl_Widget *w);
+};
diff --git a/src/UI/Fl_Osc_Numeric_Input.cpp b/src/UI/Fl_Osc_Numeric_Input.cpp
@@ -0,0 +1,36 @@
+#include "Fl_Osc_Numeric_Input.H"
+
+Fl_Osc_Numeric_Input::Fl_Osc_Numeric_Input(int X, int Y, int W, int H, const char *label)
+ :Fl_Input(X,Y,W,H, label), Fl_Osc_Widget(this)
+{
+ callback(numeric_callback);
+}
+
+Fl_Osc_Numeric_Input::~Fl_Osc_Numeric_Input(void)
+{}
+
+void Fl_Osc_Numeric_Input::init(const char *path)
+{
+ ext = path;
+ oscRegister(path);
+}
+
+void Fl_Osc_Numeric_Input::OSC_value(float f)
+{
+ OSC_value((int)f);
+}
+
+void Fl_Osc_Numeric_Input::OSC_value(int i)
+{
+ char buf[128];
+ snprintf(buf, 128, "%d", i);
+ value(buf);
+}
+
+void Fl_Osc_Numeric_Input::numeric_callback(Fl_Widget *w)
+{
+ auto &ww = *(Fl_Osc_Numeric_Input *)w;
+ int x = atoi(ww.value());
+ if(x)
+ ww.oscWrite(ww.ext, "i", x);
+}
diff --git a/src/UI/Fl_Osc_Output.H b/src/UI/Fl_Osc_Output.H
@@ -2,7 +2,7 @@
#include <FL/Fl_Value_Output.H>
#include "Fl_Osc_Widget.H"
-class Fl_Osc_Output:public Fl_Value_Output, Fl_Osc_Widget
+class Fl_Osc_Output:public Fl_Value_Output, public Fl_Osc_Widget
{
public:
Fl_Osc_Output(int x, int y, int w, int h, const char *label = NULL);
@@ -19,6 +19,5 @@ class Fl_Osc_Output:public Fl_Value_Output, Fl_Osc_Widget
void cb(void);
private:
float newvalue_;
- std::string name;
std::pair<Fl_Callback*, void*> cb_data;
};
diff --git a/src/UI/Fl_Osc_Output.cpp b/src/UI/Fl_Osc_Output.cpp
@@ -19,7 +19,7 @@ Fl_Osc_Output::Fl_Osc_Output(int X, int Y, int W, int H, const char *label)
void Fl_Osc_Output::init(const char *path)
{
- name = path;
+ ext = path;
oscRegister(path);
};
@@ -51,7 +51,7 @@ void Fl_Osc_Output::OSC_value(float v)
void Fl_Osc_Output::update(void)
{
- oscWrite(name);
+ oscWrite(ext);
}
float Fl_Osc_Output::newvalue(void) const
@@ -61,5 +61,5 @@ float Fl_Osc_Output::newvalue(void) const
void Fl_Osc_Output::cb(void)
{
- oscWrite(name);
+ oscWrite(ext);
}
diff --git a/src/UI/Fl_Oscilloscope.h b/src/UI/Fl_Oscilloscope.h
@@ -54,6 +54,9 @@ class Fl_Oscilloscope : public Fl_Box, public Fl_Osc_Widget
virtual void OSC_value(unsigned N, void *data) override
{
+ if(oscilsize == 0)
+ OSC_value((int)N/4);
+
assert(N==(unsigned)(oscilsize*4));
memcpy(smps, data, N);
diff --git a/src/UI/MasterUI.fl b/src/UI/MasterUI.fl
@@ -17,7 +17,9 @@ decl {\#include <stdio.h>} {public local
decl {\#include <string.h>} {public local
}
-decl {\#include "zynaddsubfx.xpm"} {private local
+decl {\#if defined(__linux__) && ! defined(PLUGINVERSION)
+\#include "zynaddsubfx.xpm"
+\#endif} {public local
}
decl {\#include "WidgetPDial.h"} {public local
@@ -74,7 +76,7 @@ extern NSM_Client *nsm;
\#endif} {public local
}
-decl {\#if __linux__
+decl {\#if defined(__linux__) && ! defined(PLUGINVERSION)
\#include <X11/xpm.h>
\#endif} {public local
}
@@ -1480,7 +1482,7 @@ masterwindowlabel[99]='\\0';
masterwindow->label(&masterwindowlabel[0]);
simplemasterwindow->label(&masterwindowlabel[0]);} {}
}
- Function {MasterUI(int *exitprogram_, class Fl_Osc_Interface *osc_)} {open
+ Function {MasterUI(int *exitprogram_, class Fl_Osc_Interface *osc_):nioui(osc_)} {open
} {
code {exitprogram=exitprogram_;
osc=osc_;
@@ -1500,7 +1502,7 @@ configui=new ConfigUI(osc);
make_window();
fl_open_display();
-\#ifdef __linux__
+\#if defined(__linux__) && ! defined(PLUGINVERSION)
Pixmap p, mask;
XCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display),
(char**)zynaddsubfx_xpm, &p, &mask, NULL);
diff --git a/src/UI/NioUI.cpp b/src/UI/NioUI.cpp
@@ -10,49 +10,110 @@
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Text_Display.H>
+#include "Osc_SimpleListModel.h"
using namespace std;
-NioUI::NioUI()
+static void callback_fn_choice_nio(Fl_Widget *w, void *);
+class Fl_Osc_StrChoice:public Fl_Choice, public Fl_Osc_Widget
+{
+ public:
+ Fl_Osc_StrChoice(int X, int Y, int W, int H, const char *label = NULL)
+ :Fl_Choice(X,Y,W,H, label), Fl_Osc_Widget(this), cb_data(NULL, NULL)
+ {
+ Fl_Choice::callback(callback_fn_choice_nio, NULL);
+ }
+
+ virtual ~Fl_Osc_StrChoice(void) {};
+ void init(std::string path_)
+ {
+ ext = path_;
+ Fl_Osc_Pane *pane = fetch_osc_pane(this);
+ assert(pane);
+ assert(pane->osc);
+ osc = pane->osc;
+ oscRegister(path_.c_str());
+ };
+
+
+ void OSC_value(const char *S) override
+ {
+ for(int i=0; i<size()-1; ++i) {
+ printf("size = %d, i=%d, text='%s'\n", size(), i, text(i));
+ if(!strcmp(S, text(i)))
+ value(i);
+ }
+ }
+
+ //Refetch parameter information
+ void update(void)
+ {
+ assert(osc);
+ oscWrite(ext);
+ }
+ void callback(Fl_Callback *cb, void *p = NULL)
+ {
+ cb_data.first = cb;
+ cb_data.second = p;
+ }
+
+ void cb(void)
+ {
+ assert(osc);
+ if(text(value()))
+ oscWrite(ext, "s", text(value()));
+ if(cb_data.first)
+ cb_data.first(this, cb_data.second);
+ }
+ private:
+ int min;
+ std::pair<Fl_Callback*, void*> cb_data;
+};
+static void callback_fn_choice_nio(Fl_Widget *w, void *)
+{
+ ((Fl_Osc_StrChoice*)w)->cb();
+}
+
+NioUI::NioUI(Fl_Osc_Interface *osc)
:Fl_Window(200, 100, 400, 400, "New IO Controls")
{
//hm, I appear to be leaking memory
- Fl_Group *settings = new Fl_Group(0, 20, 400, 400 - 35, "Settings");
+ Fl_Osc_Group *settings = new Fl_Osc_Group(0, 20, 400, 400 - 35, "Settings");
{
- audio = new Fl_Choice(60, 80, 100, 25, "Audio");
- audio->callback(audioCallback);
- midi = new Fl_Choice(60, 100, 100, 25, "Midi");
- midi->callback(midiCallback);
+ settings->osc = osc;
+ audio = new Fl_Osc_StrChoice(60, 80, 100, 25, "Audio");
+ //audio->callback(audioCallback);
+ audio->init("/io/sink");
+ midi = new Fl_Osc_StrChoice(60, 100, 100, 25, "Midi");
+ //midi->callback(midiCallback);
+ midi->init("/io/source");
}
settings->end();
+ //Get options
+ midi_opt = new Osc_SimpleListModel(osc);
+ audio_opt = new Osc_SimpleListModel(osc);
+
+ using list_t = Osc_SimpleListModel::list_t;
+
//initialize midi list
- {
- //set<string> midiList = Nio::getSources();
- //string source = Nio::getSource();
- //int midival = 0;
- //for(set<string>::iterator itr = midiList.begin();
- // itr != midiList.end(); ++itr) {
- // midi->add(itr->c_str());
- // if(*itr == source)
- // midival = midi->size() - 2;
- //}
- //midi->value(midival);
- }
+ midi_opt->callback = [this](list_t list) {
+ printf("midi list updating...\n");
+ midi->clear();
+ for(auto io:list)
+ midi->add(io.c_str());
+ };
//initialize audio list
- {
- //set<string> audioList = Nio::getSinks();
- //string sink = Nio::getSink();
- //int audioval = 0;
- //for(set<string>::iterator itr = audioList.begin();
- // itr != audioList.end(); ++itr) {
- // audio->add(itr->c_str());
- // if(*itr == sink)
- // audioval = audio->size() - 2;
- //}
- //audio->value(audioval);
- }
+ audio_opt->callback = [this](list_t list) {
+ audio->clear();
+ for(auto io:list)
+ audio->add(io.c_str());
+ };
+
+ midi_opt->update("/io/source-list");
+ audio_opt->update("/io/sink-list");
+
resizable(this);
size_range(400, 300);
}
@@ -61,7 +122,12 @@ NioUI::~NioUI()
{}
void NioUI::refresh()
-{}
+{
+ midi_opt->update("/io/source-list");
+ audio_opt->update("/io/sink-list");
+ midi->update();
+ audio->update();
+}
void NioUI::midiCallback(Fl_Widget *c)
{
diff --git a/src/UI/NioUI.h b/src/UI/NioUI.h
@@ -7,12 +7,14 @@
class NioUI:public Fl_Window
{
public:
- NioUI();
+ NioUI(class Fl_Osc_Interface*);
~NioUI();
void refresh();
private:
- class Fl_Choice * midi;
- class Fl_Choice * audio;
+ class Fl_Osc_StrChoice * midi;
+ class Fl_Osc_StrChoice * audio;
+ class Osc_SimpleListModel * midi_opt;
+ class Osc_SimpleListModel * audio_opt;
static void midiCallback(Fl_Widget *c);
static void audioCallback(Fl_Widget *c);
};
diff --git a/src/UI/Osc_DataModel.h b/src/UI/Osc_DataModel.h
@@ -1,3 +1,4 @@
+#pragma once
#include "Fl_Osc_Widget.H"
#include <functional>
#include <vector>
@@ -7,7 +8,7 @@ class Osc_DataModel:public Fl_Osc_Widget
{
public:
Osc_DataModel(Fl_Osc_Interface *osc_)
- :Fl_Osc_Widget("", osc_), list_size(0)
+ :Fl_Osc_Widget("", osc_)
{
assert(osc);
}
@@ -15,7 +16,6 @@ class Osc_DataModel:public Fl_Osc_Widget
typedef std::string value_t;
value_t value;
std::function<void(value_t)> callback;
- unsigned list_size;
void update(std::string url)
{
diff --git a/src/UI/Osc_IntModel.h b/src/UI/Osc_IntModel.h
@@ -0,0 +1,45 @@
+#pragma once
+#include "Fl_Osc_Widget.H"
+#include <functional>
+#include <vector>
+#include <rtosc/rtosc.h>
+
+class Osc_IntModel:public Fl_Osc_Widget
+{
+ public:
+ Osc_IntModel(Fl_Osc_Interface *osc_)
+ :Fl_Osc_Widget("", osc_), value(0)
+ {
+ assert(osc);
+ }
+
+ typedef int value_t;
+ value_t value;
+ std::function<void(value_t)> callback;
+
+ void updateVal(value_t v)
+ {
+ value = v;
+ oscWrite(ext, "i", v);
+ }
+
+ void update(std::string url)
+ {
+ if(!ext.empty())
+ osc->removeLink(this);
+ ext = url;
+
+ oscRegister(ext.c_str());
+ }
+
+ //Raw messages
+ virtual void OSC_raw(const char *msg)
+ {
+ std::string args = rtosc_argument_string(msg);
+ if(args == "i") {
+ value = rtosc_argument(msg, 0).i;
+ if(callback)
+ callback(value);
+ }
+ }
+};
diff --git a/src/UI/OscilGenUI.fl b/src/UI/OscilGenUI.fl
@@ -119,7 +119,7 @@ class Oscilharmonic {: {public Fl_Group}
Fl_Slider mag {
callback {int x=64;
if (Fl::event_button3()) o->value(x);
- else x=127-(int)o->value();
+ else x=128-(int)o->value();
if (x==64) o->selection_color(0);
else o->selection_color(222);
@@ -496,12 +496,15 @@ redrawoscil();}
if (autoclearbutton->value()){
for (int i=0;i<MAX_AD_HARMONICS;i++){
h[i]->mag->value(64);
+ h[i]->mag->do_callback();
h[i]->phase->value(64);
+ h[i]->phase->do_callback();
};
harmonicshiftcounter->value(0);
h[0]->mag->value(0);
+ h[0]->mag->do_callback();
wshbutton->value(0);
wshbutton->do_callback();
fltbutton->value(0);
@@ -527,9 +530,12 @@ redrawoscil();}
for (int i=0;i<MAX_AD_HARMONICS;i++){
h[i]->mag->value(64);
+ h[i]->mag->do_callback();
h[i]->phase->value(64);
+ h[i]->phase->do_callback();
};
h[0]->mag->value(0);
+h[0]->mag->do_callback();
//for (int i=0;i<MAX_AD_HARMONICS;i++){
// if (oscil->Phmag[i]==64) h[i]->mag->selection_color(0);
diff --git a/src/UI/SUBnoteUI.fl b/src/UI/SUBnoteUI.fl
@@ -52,6 +52,20 @@ class PPSlider {: {public Fl_Slider, public Fl_Osc_Widget}
} {
code {int X=x(),Y=y(),W=w(),H=h();
+// catch any (un)learn event first
+{
+ bool middle_mouse = (event == FL_PUSH && Fl::event_state(FL_BUTTON2) && !Fl::event_shift());
+ bool ctl_click = (event == FL_PUSH && Fl::event_state(FL_BUTTON1) && Fl::event_ctrl());
+ bool shift_middle = (event == FL_PUSH && Fl::event_state(FL_BUTTON2) && Fl::event_shift());
+ if(middle_mouse || ctl_click) {
+ osc->write("/learn", "s", (loc+ext).c_str());
+ return 1;
+ } else if(shift_middle) {
+ osc->write("/unlearn", "s", (loc+ext).c_str());
+ return 1;
+ }
+}
+
if ((!Fl::event_buttons())|| (event==0)||(Fl::event_shift()==0)) return(Fl_Slider::handle(event));
if (!Fl::event_inside(X,Y,W,H)) {
@@ -100,7 +114,7 @@ class SUBnoteharmonic {: {public Fl_Osc_Group}
int x=0;
if (Fl::event_button1() || Fl::event() == FL_MOUSEWHEEL) x=127-(int)o->value();
else o->value(127-x);
- o->osc->writeValue(o->loc + "Phmag" + to_s(n), (char) x);
+ o->osc->writeValue(o->loc + o->ext, (char) x);
if (x==0) o->selection_color(0);
else o->selection_color(222);}
tooltip {harmonic's magnitude} xywh {0 15 10 135} type {Vert Knob} box FLAT_BOX selection_color 222 maximum 127 step 1 value 127
@@ -110,7 +124,7 @@ if (x==0) o->selection_color(0);
callback {int x=64;
if (Fl::event_button1() || Fl::event() == FL_MOUSEWHEEL) x=127-(int)o->value();
else o->value(x);
- o->osc->writeValue(o->loc+"Phrelbw"+to_s(n), (char) x);}
+ o->osc->writeValue(o->loc + o->ext, (char) x)};
tooltip {harmonic's bandwidth} xywh {0 157 10 130} type {Vert Knob} box FLAT_BOX selection_color 222 maximum 127 step 1 value 64
class PPSlider
}
@@ -137,17 +151,18 @@ if (Fl::event_button1() || Fl::event() == FL_MOUSEWHEEL) x=127-(int)o->value();
code {n=n_;
make_window();
harmonic->show();
-
-osc->createLink(base+"Phmag"+to_s(n), mag);
-osc->createLink(base+"Phrelbw"+to_s(n), bw);
-osc->requestValue(base+"Phmag"+to_s(n));
+mag->ext = "Phmag" + to_s(n);
+mag->oscRegister(mag->ext.c_str());
+bw->ext = "Phrelbw" + to_s(n);
+bw->oscRegister(bw->ext.c_str());
osc->requestValue(base+"Phrelbw"+to_s(n));
end();} {}
}
Function {refresh()} {} {
- code {osc->requestValue(base+"Phmag"+to_s(n));
-osc->requestValue(base+"Phrelbw"+to_s(n));} {}
+ code {// request values for the widgets
+mag->oscWrite(mag->ext);
+bw->oscWrite(bw->ext);} {}
}
Function {~SUBnoteharmonic()} {} {
code {harmonic->hide();
diff --git a/src/UI/guimain.cpp b/src/UI/guimain.cpp
@@ -328,13 +328,15 @@ class UI_Interface:public Fl_Osc_Interface
void write(string s, const char *args, ...) override
{
+ char buffer[4096];
va_list va;
va_start(va, args);
+ rtosc_vmessage(buffer, sizeof(buffer), s.c_str(), args, va);
//fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 4 + 30, 0 + 40);
////fprintf(stderr, ".");
//fprintf(stderr, "write(%s:%s)\n", s.c_str(), args);
//fprintf(stderr, "%c[%d;%d;%dm", 0x1B, 0, 7 + 30, 0 + 40);
- transmitMsg(s.c_str(), args, va);
+ transmitMsg(buffer);
va_end(va);
}
diff --git a/src/main.cpp b/src/main.cpp
@@ -424,11 +424,29 @@ int main(int argc, char *argv[])
gui = NULL;
+
+ //Capture Startup Responses
+ typedef std::vector<const char *> wait_t;
+ wait_t msg_waitlist;
+ middleware->setUiCallback([](void*v,const char*msg) {
+ wait_t &wait = *(wait_t*)v;
+ size_t len = rtosc_message_length(msg, -1);
+ char *copy = new char[len];
+ memcpy(copy, msg, len);
+ wait.push_back(copy);
+ }, &msg_waitlist);
+
if(!noui)
gui = GUI::createUi(middleware->spawnUiApi(), &Pexitprogram);
middleware->setUiCallback(GUI::raiseUi, gui);
middleware->setIdleCallback([](void*){GUI::tickUi(gui);}, NULL);
+ //Replay Startup Responses
+ for(auto msg:msg_waitlist) {
+ GUI::raiseUi(gui, msg);
+ delete [] msg;
+ }
+
if(!noui)
{
GUI::raiseUi(gui, "/show", "i", config.cfg.UserInterfaceMode);