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