@@ -208,6 +208,13 @@ protected: | |||
pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f); | |||
} | |||
void hostGiveIdle() const | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,); | |||
pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f); | |||
} | |||
// ------------------------------------------------------------------- | |||
// Plugin parameter calls | |||
@@ -440,22 +440,37 @@ protected: | |||
{ | |||
fParameters[index] = (value >= 0.5f) ? 1.0f : 0.0f; | |||
fMiddleWare->transmitMsg("/echo", "ss", "OSC_URL", ""); | |||
fMiddleWare->activeUrl(""); | |||
char msg[24]; | |||
std::sprintf(msg, "/part%i/Penabled", index-kParamPart01Enabled); | |||
fMiddleWare->transmitMsg(msg, (value >= 0.5f) ? "T" : "F"); | |||
} | |||
else if (index <= kParamPart16Volume) | |||
{ | |||
if (carla_compareFloats(fParameters[index], value)) | |||
return; | |||
fParameters[index] = std::round(carla_fixValue(0.0f, 127.0f, value)); | |||
fMiddleWare->transmitMsg("/echo", "ss", "OSC_URL", ""); | |||
fMiddleWare->activeUrl(""); | |||
char msg[24]; | |||
std::sprintf(msg, "/part%i/Pvolume", index-kParamPart01Volume); | |||
fMiddleWare->transmitMsg(msg, "i", static_cast<int>(fParameters[index])); | |||
} | |||
else if (index <= kParamPart16Panning) | |||
{ | |||
if (carla_compareFloats(fParameters[index], value)) | |||
return; | |||
fParameters[index] = std::round(carla_fixValue(0.0f, 127.0f, value)); | |||
fMiddleWare->transmitMsg("/echo", "ss", "OSC_URL", ""); | |||
fMiddleWare->activeUrl(""); | |||
char msg[24]; | |||
std::sprintf(msg, "/part%i/Ppanning", index-kParamPart01Panning); | |||
fMiddleWare->transmitMsg(msg, "i", static_cast<int>(fParameters[index])); | |||
@@ -530,6 +545,7 @@ protected: | |||
FloatVectorOperations::clear(outBuffer[1], static_cast<int>(frames)); | |||
return; | |||
} | |||
fMutex.lock(); | |||
} | |||
@@ -654,7 +670,7 @@ protected: | |||
const CarlaMutexLocker cml(fMutex); | |||
fMaster->putalldata(const_cast<char*>(data), 0); | |||
fMaster->putalldata(data); | |||
fMaster->applyparameters(); | |||
fMiddleWare->updateResources(fMaster); | |||
@@ -737,10 +753,17 @@ private: | |||
{ | |||
fMiddleWare = new MiddleWare(fSynth); | |||
fMaster = fMiddleWare->spawnMaster(); | |||
fMiddleWare->setIdleCallback(_idleCallback, this); | |||
fMiddleWare->setUiCallback(__uiCallback, this); | |||
fMiddleWare->setMasterChangedCallback(_masterChangedCallback, this); | |||
} | |||
void _setMasterParameters() | |||
{ | |||
fMiddleWare->transmitMsg("/echo", "ss", "OSC_URL", ""); | |||
fMiddleWare->activeUrl(""); | |||
for (int i=kParamPart16Enabled+1; --i>=kParamPart01Enabled;) | |||
{ | |||
char msg[24]; | |||
@@ -780,6 +803,71 @@ private: | |||
fMiddleWare = nullptr; | |||
} | |||
void _uiCallback(const char* const msg) | |||
{ | |||
if (std::strncmp(msg, "/part", 5) != 0) | |||
return; | |||
const char* msgtmp = msg; | |||
msgtmp += 5; | |||
CARLA_SAFE_ASSERT_RETURN( msgtmp[0] >= '0' && msgtmp[0] <= '9',); | |||
CARLA_SAFE_ASSERT_RETURN((msgtmp[1] >= '0' && msgtmp[1] <= '9') || msgtmp[1] == '/',); | |||
char partnstr[3] = { '\0', '\0', '\0' }; | |||
partnstr[0] = msgtmp[0]; | |||
++msgtmp; | |||
if (msgtmp[0] >= '0' && msgtmp[0] <= '9') | |||
{ | |||
partnstr[1] = msgtmp[0]; | |||
++msgtmp; | |||
} | |||
const int partn = std::atoi(partnstr); | |||
++msgtmp; | |||
/**/ if (std::strcmp(msgtmp, "Penabled") == 0) | |||
{ | |||
const int index = kParamPart01Enabled+partn; | |||
const bool enbl = rtosc_argument(msg,0).T; | |||
fParameters[index] = enbl ? 1.0f : 0.0f; | |||
uiParameterChanged(kParamPart01Enabled+partn, enbl ? 1.0f : 0.0f); | |||
} | |||
else if (std::strcmp(msgtmp, "Pvolume") == 0) | |||
{ | |||
const int index = kParamPart01Volume+partn; | |||
const int value = rtosc_argument(msg,0).i; | |||
fParameters[index] = value; | |||
uiParameterChanged(kParamPart01Volume+partn, value); | |||
} | |||
else if (std::strcmp(msgtmp, "Ppanning") == 0) | |||
{ | |||
const int index = kParamPart01Panning+partn; | |||
const int value = rtosc_argument(msg,0).i; | |||
fParameters[index] = value; | |||
uiParameterChanged(kParamPart01Panning+partn, value); | |||
} | |||
} | |||
static void _idleCallback(void* ptr) | |||
{ | |||
((ZynAddSubFxPlugin*)ptr)->hostGiveIdle(); | |||
} | |||
static void __uiCallback(void* ptr, const char* msg) | |||
{ | |||
((ZynAddSubFxPlugin*)ptr)->_uiCallback(msg); | |||
} | |||
static void _masterChangedCallback(void* ptr, Master* m) | |||
{ | |||
((ZynAddSubFxPlugin*)ptr)->fMaster = m; | |||
} | |||
// ------------------------------------------------------------------- | |||
public: | |||
@@ -109,6 +109,17 @@ public: | |||
protected: | |||
bool msgReceived(const char* const msg) noexcept override | |||
{ | |||
if (std::strcmp(msg, "control") == 0) | |||
{ | |||
uint index; | |||
float value; | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||
CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); | |||
// TODO | |||
return true; | |||
} | |||
if (std::strcmp(msg, "show") == 0) | |||
{ | |||
try { | |||
@@ -999,7 +999,7 @@ int Master::getalldata(char **data) | |||
return strlen(*data) + 1; | |||
} | |||
void Master::putalldata(char *data, int /*size*/) | |||
void Master::putalldata(const char *data) | |||
{ | |||
XMLwrapper *xml = new XMLwrapper(); | |||
if(!xml->putXMLdata(data)) { | |||
@@ -78,11 +78,11 @@ class Master | |||
void getfromXML(XMLwrapper *xml); | |||
/**get all data to a newly allocated array (used for VST) | |||
/**get all data to a newly allocated array (used for plugin) | |||
* @return the datasize*/ | |||
int getalldata(char **data) NONREALTIME; | |||
/**put all data from the *data array to zynaddsubfx parameters (used for VST)*/ | |||
void putalldata(char *data, int size); | |||
/**put all data from the *data array to zynaddsubfx parameters (used for plugin)*/ | |||
void putalldata(const char *data); | |||
//Midi IN | |||
void noteOn(char chan, char note, char velocity); | |||
@@ -636,7 +636,7 @@ public: | |||
//Load the part | |||
if(idle) { | |||
while(alloc.wait_for(std::chrono::seconds(0)) != std::future_status::ready) { | |||
idle(); | |||
idle(idle_ptr); | |||
} | |||
} | |||
@@ -686,6 +686,9 @@ public: | |||
master = m; | |||
if (mastercb) | |||
mastercb(mastercb_ptr, m); | |||
//Give it to the backend and wait for the old part to return for | |||
//deallocation | |||
uToB->write("/load-master", "b", sizeof(Master*), &m); | |||
@@ -809,7 +812,13 @@ public: | |||
ParamStore kits; | |||
//Callback When Waiting on async events | |||
void(*idle)(void); | |||
void(*idle)(void*); | |||
void* idle_ptr; | |||
//Callback When Master changes | |||
void(*mastercb)(void*,Master*); | |||
void* mastercb_ptr; | |||
//General UI callback | |||
cb_t cb; | |||
//UI handle | |||
@@ -852,6 +861,9 @@ MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_, int prefered_port | |||
//dummy callback for starters | |||
cb = [](void*, const char*){}; | |||
idle = 0; | |||
idle_ptr = 0; | |||
mastercb = 0; | |||
mastercb_ptr = 0; | |||
the_bToU = bToU; | |||
master = new Master(synth); | |||
@@ -996,7 +1008,24 @@ void MiddleWareImpl::bToUhandle(const char *rtmsg, bool dummy) | |||
broadcast = true; | |||
} else if(broadcast) { | |||
broadcast = false; | |||
#ifdef CARLA_VERSION_STRING | |||
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); | |||
if(curr_url != "GUI") { | |||
lo_message msg = lo_message_deserialise((void*)rtmsg, | |||
rtosc_message_length(rtmsg, bToU->buffer_size()), NULL); | |||
@@ -1007,6 +1036,7 @@ void MiddleWareImpl::bToUhandle(const char *rtmsg, bool dummy) | |||
lo_send_message(addr, rtmsg, msg); | |||
} | |||
} | |||
#endif | |||
} else if((dummy?last_url:curr_url) == "GUI" || !strcmp(rtmsg, "/close-ui")) { | |||
cb(ui, rtmsg); | |||
} else{ | |||
@@ -1270,15 +1300,22 @@ void MiddleWare::doReadOnlyOp(std::function<void()> fn) | |||
impl->doReadOnlyOp(fn); | |||
} | |||
void MiddleWare::setUiCallback(void(*cb)(void*,const char *),void *ui) | |||
void MiddleWare::setUiCallback(void(*cb)(void*,const char *), void *ui) | |||
{ | |||
impl->cb = cb; | |||
impl->ui = ui; | |||
} | |||
void MiddleWare::setIdleCallback(void(*cb)(void)) | |||
void MiddleWare::setIdleCallback(void(*cb)(void*), void *ptr) | |||
{ | |||
impl->idle = cb; | |||
impl->idle_ptr = ptr; | |||
} | |||
void MiddleWare::setMasterChangedCallback(void(*cb)(void*,Master*), void *ptr) | |||
{ | |||
impl->idle = cb; | |||
impl->mastercb = cb; | |||
impl->mastercb_ptr = ptr; | |||
} | |||
void MiddleWare::transmitMsg(const char *msg) | |||
@@ -18,7 +18,9 @@ class MiddleWare | |||
//Set callback to push UI events to | |||
void setUiCallback(void(*cb)(void*,const char *),void *ui); | |||
//Set callback to run while busy | |||
void setIdleCallback(void(*cb)(void)); | |||
void setIdleCallback(void(*cb)(void*),void *ptr); | |||
//Set callback to run when master changed | |||
void setMasterChangedCallback(void(*cb)(void*,Master*),void *ptr); | |||
//Handle events | |||
void tick(void); | |||
//Do A Readonly Operation (For Parameter Copy) | |||
@@ -220,10 +220,14 @@ rtosc::Ports uiPorts::ports = { | |||
ui->do_load_master(a0.s); | |||
} END | |||
BEGIN("vu-meter:bb") { | |||
#ifdef DEBUG | |||
printf("Vu meter handler...\n"); | |||
#endif | |||
if(a0.b.len == sizeof(vuData) && | |||
a1.b.len == sizeof(float)*NUM_MIDI_PARTS) { | |||
#ifdef DEBUG | |||
printf("Normal behavior...\n"); | |||
#endif | |||
//Refresh the primary VU meters | |||
ui->simplemastervu->update((vuData*)a0.b.data); | |||
ui->mastervu->update((vuData*)a0.b.data); | |||
@@ -245,7 +249,9 @@ void GUI::raiseUi(ui_handle_t gui, const char *message) | |||
return; | |||
MasterUI *mui = (MasterUI*)gui; | |||
mui->osc->tryLink(message); | |||
#ifdef DEBUG | |||
printf("got message for UI '%s:%s'\n", message, rtosc_argument_string(message)); | |||
#endif | |||
char buffer[1024]; | |||
memset(buffer, 0, sizeof(buffer)); | |||
rtosc::RtData d; | |||