| @@ -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; | |||