Browse Source

More of the same

tags/1.9.4
falkTX 11 years ago
parent
commit
0c7399716b
10 changed files with 886 additions and 70 deletions
  1. +2
    -0
      source/backend/CarlaEngine.hpp
  2. +6
    -0
      source/backend/engine/CarlaEngine.cpp
  3. +1
    -1
      source/backend/engine/CarlaEngineJack.cpp
  4. +20
    -16
      source/backend/engine/CarlaEngineThread.cpp
  5. +1
    -0
      source/backend/plugin/DssiPlugin.cpp
  6. +805
    -9
      source/backend/plugin/Lv2Plugin.cpp
  7. +2
    -1
      source/bridges/CarlaBridgeToolkitGtk.cpp
  8. +19
    -11
      source/bridges/CarlaBridgeUI-LV2.cpp
  9. +25
    -25
      source/bridges/Makefile
  10. +5
    -7
      source/modules/lv2_rdf.hpp

+ 2
- 0
source/backend/CarlaEngine.hpp View File

@@ -1044,6 +1044,7 @@ protected:
*/
void setPluginPeaks(const unsigned int pluginId, float const inPeaks[2], float const outPeaks[2]) noexcept;

#ifndef BUILD_BRIDGE
// -------------------------------------------------------------------
// Patchbay stuff

@@ -1060,6 +1061,7 @@ protected:
*/
virtual const char* const* getPatchbayConnections() const;
virtual void restorePatchbayConnection(const char* const sourcePort, const char* const targetPort);
#endif

// -------------------------------------------------------------------



+ 6
- 0
source/backend/engine/CarlaEngine.cpp View File

@@ -1386,6 +1386,7 @@ bool CarlaEngine::loadProject(const char* const filename)
return true;
}

#ifndef BUILD_BRIDGE
// now connections
for (QDomNode node = xmlNode.firstChild(); ! node.isNull(); node = node.nextSibling())
{
@@ -1418,6 +1419,7 @@ bool CarlaEngine::loadProject(const char* const filename)
break;
}
}
#endif

return true;
}
@@ -1467,6 +1469,7 @@ bool CarlaEngine::saveProject(const char* const filename)
}
}

#ifndef BUILD_BRIDGE
if (const char* const* patchbayConns = getPatchbayConnections())
{
if (! firstPlugin)
@@ -1493,6 +1496,7 @@ bool CarlaEngine::saveProject(const char* const filename)

out << " </Patchbay>\n";
}
#endif

out << "</CARLA-PROJECT>\n";

@@ -2039,6 +2043,7 @@ void CarlaEngine::setPluginPeaks(const unsigned int pluginId, float const inPeak
pluginData.outsPeak[1] = outPeaks[1];
}

#ifndef BUILD_BRIDGE
// -----------------------------------------------------------------------
// Patchbay stuff

@@ -2119,6 +2124,7 @@ void CarlaEngine::restorePatchbayConnection(const char* const connSource, const
patchbayConnect(targetPort, sourcePort);
}
}
#endif

// -----------------------------------------------------------------------
// Bridge/Controller OSC stuff


+ 1
- 1
source/backend/engine/CarlaEngineJack.cpp View File

@@ -979,7 +979,6 @@ public:
} catch(...) {}
}
}
#endif

// -------------------------------------------------------------------
// Patchbay stuff
@@ -1047,6 +1046,7 @@ public:
jackbridge_connect(fClient, connSource, connTarget);
}
}
#endif

// -------------------------------------------------------------------



+ 20
- 16
source/backend/engine/CarlaEngineThread.cpp View File

@@ -44,7 +44,7 @@ void CarlaEngineThread::run()
CARLA_ASSERT(fEngine->isRunning());
carla_debug("CarlaEngineThread::run()");

bool oscRegisted, needsSingleThread;
bool hasUi, oscRegisted, needsSingleThread;
float value;

for (; fEngine->isRunning() && ! shouldExit();)
@@ -62,6 +62,7 @@ void CarlaEngineThread::run()
CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr && plugin->isEnabled());
CARLA_SAFE_ASSERT_UINT2(i == plugin->getId(), i, plugin->getId());

hasUi = (plugin->getHints() & PLUGIN_HAS_CUSTOM_UI);
needsSingleThread = (plugin->getHints() & PLUGIN_NEEDS_SINGLE_THREAD);

// -----------------------------------------------------------
@@ -72,28 +73,31 @@ void CarlaEngineThread::run()
if (! needsSingleThread)
plugin->postRtEventsRun();

// -------------------------------------------------------
// Update parameter outputs

for (uint32_t j=0, pcount=plugin->getParameterCount(); j < pcount; ++j)
if (hasUi || oscRegisted)
{
if (! plugin->isParameterOutput(j))
continue;
// ---------------------------------------------------
// Update parameter outputs

for (uint32_t j=0, pcount=plugin->getParameterCount(); j < pcount; ++j)
{
if (! plugin->isParameterOutput(j))
continue;

value = plugin->getParameterValue(j);
value = plugin->getParameterValue(j);

// Update UI
if (! needsSingleThread)
plugin->uiParameterChange(j, value);
// Update UI
if (hasUi && ! needsSingleThread)
plugin->uiParameterChange(j, value);

// Update OSC engine client
if (oscRegisted)
{
// Update OSC engine client
if (oscRegisted)
{
#ifdef BUILD_BRIDGE
fEngine->oscSend_bridge_parameter_value(j, value);
fEngine->oscSend_bridge_parameter_value(j, value);
#else
fEngine->oscSend_control_set_parameter_value(i, static_cast<int32_t>(j), value);
fEngine->oscSend_control_set_parameter_value(i, static_cast<int32_t>(j), value);
#endif
}
}
}



+ 1
- 0
source/backend/plugin/DssiPlugin.cpp View File

@@ -372,6 +372,7 @@ public:
{
if (yesNo)
{
pData->osc.data.free();
pData->osc.thread.start();
}
else


+ 805
- 9
source/backend/plugin/Lv2Plugin.cpp View File

@@ -234,6 +234,43 @@ public:
{
carla_debug("Lv2Plugin::~Lv2Plugin()");

// close UI
if (fUi.type != UI::TYPE_NULL)
{
showCustomUI(false);

if (fUi.type == UI::TYPE_OSC)
{
pData->osc.thread.stop(static_cast<int>(pData->engine->getOptions().uiBridgesTimeout * 2));
}
else
{
if (fFeatures[kFeatureIdUiDataAccess] != nullptr && fFeatures[kFeatureIdUiDataAccess]->data != nullptr)
delete (LV2_Extension_Data_Feature*)fFeatures[kFeatureIdUiDataAccess]->data;

if (fFeatures[kFeatureIdUiPortMap] != nullptr && fFeatures[kFeatureIdUiPortMap]->data != nullptr)
delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;

if (fFeatures[kFeatureIdUiResize] != nullptr && fFeatures[kFeatureIdUiResize]->data != nullptr)
delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;

if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr)
{
const LV2_External_UI_Host* const uiHost((const LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data);

if (uiHost->plugin_human_id != nullptr)
delete[] uiHost->plugin_human_id;

delete uiHost;
}

fUi.descriptor = nullptr;
pData->uiLibClose();
}

fUi.rdfDescriptor = nullptr;
}

pData->singleMutex.lock();
pData->masterMutex.lock();

@@ -741,7 +778,111 @@ public:
// -------------------------------------------------------------------
// Set ui stuff

// nothing
void showCustomUI(const bool yesNo) override
{
CARLA_SAFE_ASSERT_RETURN(fUi.type != UI::TYPE_NULL,);

if (fUi.type == UI::TYPE_OSC)
{
if (yesNo)
{
pData->osc.data.free();
pData->osc.thread.start();
}
else
{
if (pData->osc.data.target != nullptr)
{
osc_send_hide(pData->osc.data);
osc_send_quit(pData->osc.data);
pData->osc.data.free();
}

pData->osc.thread.stop(static_cast<int>(pData->engine->getOptions().uiBridgesTimeout * 2));
}
return;
}

// take some precautions
CARLA_SAFE_ASSERT_RETURN(fUi.descriptor != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fUi.rdfDescriptor != nullptr,);

if (yesNo)
{
CARLA_SAFE_ASSERT_RETURN(fUi.descriptor->instantiate != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fUi.descriptor->cleanup != nullptr,);
}
else
{
if (fUi.handle == nullptr)
return;
}

if (fUi.type == UI::TYPE_EXTERNAL)
{
if (yesNo)
{
if (fUi.handle == nullptr)
{
fUi.widget = nullptr;
fUi.handle = fUi.descriptor->instantiate(fUi.descriptor, fRdfDescriptor->URI, fUi.rdfDescriptor->Bundle,
carla_lv2_ui_write_function, this, &fUi.widget, fFeatures);
}

CARLA_SAFE_ASSERT(fUi.handle != nullptr);
CARLA_SAFE_ASSERT(fUi.widget != nullptr);

if (fUi.handle == nullptr || fUi.widget == nullptr)
{
fUi.widget = nullptr;

if (fUi.handle != nullptr)
{
fUi.descriptor->cleanup(fUi.handle);
fUi.handle = nullptr;
}

pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0.0f, "Plugin refused to open its own UI");
return;
}

updateUi();

LV2_EXTERNAL_UI_SHOW((LV2_External_UI_Widget*)fUi.widget);
}
else
{
CARLA_SAFE_ASSERT(fUi.widget != nullptr);

if (fUi.widget != nullptr)
LV2_EXTERNAL_UI_HIDE((LV2_External_UI_Widget*)fUi.widget);

fUi.descriptor->cleanup(fUi.handle);
fUi.handle = nullptr;
fUi.widget = nullptr;
}
}
else // means TYPE_EMBED
{
}
}

void idle() override
{
if (fUi.handle != nullptr && fUi.descriptor != nullptr)
{
if (fUi.type == UI::TYPE_EXTERNAL && fUi.widget != nullptr)
LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget*)fUi.widget);

if (fExt.uiidle != nullptr && fExt.uiidle->idle(fUi.handle) != 0)
{
showCustomUI(false);
pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
}
}

CarlaPlugin::idle();
}

// -------------------------------------------------------------------
// Plugin state
@@ -1187,6 +1328,14 @@ public:
if (isRealtimeSafe())
pData->hints |= PLUGIN_IS_RTSAFE;

if (fUi.type != UI::TYPE_NULL)
{
pData->hints |= PLUGIN_HAS_CUSTOM_UI;

if (fUi.type == UI::TYPE_EMBED)
pData->hints |= PLUGIN_NEEDS_SINGLE_THREAD;
}

if (LV2_IS_GENERATOR(fRdfDescriptor->Type[0], fRdfDescriptor->Type[1]))
pData->hints |= PLUGIN_IS_SYNTH;

@@ -1776,6 +1925,118 @@ public:
carla_debug("Lv2Plugin::clearBuffers() - end");
}

// -------------------------------------------------------------------
// Post-poned UI Stuff

void uiParameterChange(const uint32_t index, const float value) noexcept override
{
CARLA_SAFE_ASSERT_RETURN(fUi.type != UI::TYPE_NULL,);
CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);

if (fUi.type == UI::TYPE_OSC)
{
if (pData->osc.data.target != nullptr)
osc_send_control(pData->osc.data, pData->param.data[index].rindex, value);
}
else
{
if (fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->port_event != nullptr)
{
CARLA_SAFE_ASSERT_RETURN(pData->param.data[index].rindex >= 0,);
fUi.descriptor->port_event(fUi.handle, static_cast<uint32_t>(pData->param.data[index].rindex), sizeof(float), 0, &value);
}
}
}

void uiMidiProgramChange(const uint32_t index) noexcept override
{
CARLA_SAFE_ASSERT_RETURN(fUi.type != UI::TYPE_NULL,);
CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);

if (fUi.type == UI::TYPE_OSC)
{
if (pData->osc.data.target != nullptr)
osc_send_midi_program(pData->osc.data, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
}
else
{
if (fExt.uiprograms != nullptr && fExt.uiprograms->select_program != nullptr)
fExt.uiprograms->select_program(fUi.handle, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
}
}

void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
{
CARLA_SAFE_ASSERT_RETURN(fUi.type != UI::TYPE_NULL,);
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);

if (fUi.type == UI::TYPE_OSC)
{
if (pData->osc.data.target != nullptr)
{
uint8_t midiData[4] = { 0 };
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_ON + channel);
midiData[2] = note;
midiData[3] = velo;
osc_send_midi(pData->osc.data, midiData);
}
}
else
{
#if 0
if (fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr)
{
LV2_Atom_MidiEvent midiEv;
midiEv.event.time.frames = 0;
midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
midiEv.event.body.size = 3;
midiEv.data[0] = MIDI_STATUS_NOTE_OFF + channel;
midiEv.data[1] = note;
midiEv.data[2] = velo;

fUi.descriptor->port_event(fUi.handle, fEventsIn.ctrl->rindex, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
}
#endif
}
}

void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
{
CARLA_SAFE_ASSERT_RETURN(fUi.type != UI::TYPE_NULL,);
CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);

if (fUi.type == UI::TYPE_OSC)
{
if (pData->osc.data.target != nullptr)
{
uint8_t midiData[4] = { 0 };
midiData[1] = static_cast<uint8_t>(MIDI_STATUS_NOTE_OFF + channel);
midiData[2] = note;
osc_send_midi(pData->osc.data, midiData);
}
}
else
{
#if 0
if (fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr)
{
LV2_Atom_MidiEvent midiEv;
midiEv.event.time.frames = 0;
midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
midiEv.event.body.size = 3;
midiEv.data[0] = MIDI_STATUS_NOTE_OFF + channel;
midiEv.data[1] = note;
midiEv.data[2] = 0;

fUi.descriptor->port_event(fUi.handle, fEventsIn.ctrl->rindex, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
}
#endif
}
}

// -------------------------------------------------------------------

bool isRealtimeSafe() const noexcept
@@ -1812,6 +2073,9 @@ public:

const LV2_RDF_UI* const rdfUi(&fRdfDescriptor->UIs[uiId]);

if (std::strstr(rdfUi->URI, "http://calf.sourceforge.net/plugins/gui/") != nullptr)
return false;

for (uint32_t i=0; i < rdfUi->FeatureCount; ++i)
{
if (std::strcmp(rdfUi->Features[i].URI, LV2_INSTANCE_ACCESS_URI) == 0)
@@ -1838,11 +2102,66 @@ public:
return true;
}

const char* getUiBridgeBinary(const LV2_Property type) const
{
CarlaString bridgeBinary(pData->engine->getOptions().binaryDir);

if (bridgeBinary.isEmpty())
return nullptr;

// test for local build
if (bridgeBinary.endsWith("/source/backend/"))
bridgeBinary += "../bridges/";

switch (type)
{
case LV2_UI_GTK2:
bridgeBinary += "carla-bridge-lv2-gtk2";
break;
case LV2_UI_GTK3:
bridgeBinary += "carla-bridge-lv2-gtk3";
break;
case LV2_UI_QT4:
bridgeBinary += "carla-bridge-lv2-qt4";
break;
case LV2_UI_QT5:
bridgeBinary += "carla-bridge-lv2-qt5";
break;
case LV2_UI_COCOA:
bridgeBinary += "carla-bridge-lv2-cocoa";
break;
case LV2_UI_WINDOWS:
bridgeBinary += "carla-bridge-lv2-windows";
break;
case LV2_UI_X11:
bridgeBinary += "carla-bridge-lv2-x11";
break;
case LV2_UI_EXTERNAL:
case LV2_UI_OLD_EXTERNAL:
bridgeBinary += "carla-bridge-lv2-external";
break;
default:
return nullptr;
}

#ifdef CARLA_OS_WIN
bridgeBinary += ".exe";
#endif

QFile file(bridgeBinary.getBuffer());

if (! file.exists())
return nullptr;

return bridgeBinary.dup();
}

// -------------------------------------------------------------------

void recheckExtensions()
{
CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr,);
carla_debug("Lv2Plugin::recheckExtensions()");

fExt.options = nullptr;
fExt.programs = nullptr;
@@ -1898,6 +2217,7 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(fUi.handle != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fUi.descriptor != nullptr,);
carla_debug("Lv2Plugin::updateUi()");

fExt.uiidle = nullptr;
fExt.uiprograms = nullptr;
@@ -1952,10 +2272,8 @@ public:

fCustomURIDs.append(carla_strdup(uri));

#if 0
if (fUi.type == PLUGIN_UI_OSC && kData->osc.data.target != nullptr)
osc_send_lv2_urid_map(&kData->osc.data, urid, uri);
#endif
if (fUi.type == UI::TYPE_OSC && pData->osc.data.target != nullptr)
osc_send_lv2_urid_map(pData->osc.data, urid, uri);

return urid;
}
@@ -2010,7 +2328,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_STATE_ERR_NO_PROPERTY);
CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL, LV2_STATE_ERR_BAD_TYPE);
CARLA_SAFE_ASSERT_RETURN(flags & LV2_STATE_IS_POD, LV2_STATE_ERR_BAD_FLAGS);
carla_debug("Lv2Plugin::handleStateStore(%i, %p, " P_SIZE ", %i, %i)", key, value, size, type, flags);
carla_debug("Lv2Plugin::handleStateStore(%i:\"%s\", %p, " P_SIZE ", %i:\"%s\", %i)", key, carla_lv2_urid_unmap(this, key), value, size, type, carla_lv2_urid_unmap(this, type), flags);

const char* const skey(carla_lv2_urid_unmap(this, key));
const char* const stype(carla_lv2_urid_unmap(this, type));
@@ -2135,6 +2453,126 @@ public:

// -------------------------------------------------------------------

void handleExternalUiClosed()
{
CARLA_SAFE_ASSERT_RETURN(fUi.type == UI::TYPE_EXTERNAL,);
carla_debug("Lv2Plugin::handleExternalUiClosed()");

if (fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->cleanup != nullptr)
fUi.descriptor->cleanup(fUi.handle);

fUi.handle = nullptr;
fUi.widget = nullptr;
pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
}

// -------------------------------------------------------------------

uint32_t handleUiPortMap(const char* const symbol) const noexcept
{
CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX);
carla_debug("Lv2Plugin::handleUiPortMap(\"%s\")", symbol);

for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
{
if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
return i;
}

return LV2UI_INVALID_PORT_INDEX;
}

int handleUiResize(const int width, const int height)
{
CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
carla_debug("Lv2Plugin::handleUiResize(%i, %i)", width, height);

return 0;
}

void handleUiWrite(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer)
{
CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);
carla_debug("Lv2Plugin::handleUiWrite(%i, %i, %i:\"%s\", %p)", rindex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);

switch (format)
{
case 0:
CARLA_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),);

for (uint32_t i=0; i < pData->param.count; ++i)
{
if (pData->param.data[i].rindex == static_cast<int32_t>(rindex))
{
const float value(*(const float*)buffer);

if (fParamBuffers[i] != value)
setParameterValue(i, value, false, true, true);
break;
}
}
break;

case CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM:
case CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT:
//fAtomQueueIn.put(rindex, (const LV2_Atom*)buffer);
break;

default:
carla_stdout("Lv2Plugin::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format", rindex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
break;
}
}

// -------------------------------------------------------------------

void handleLilvSetPortValue(const char* const portSymbol, const void* const value, const uint32_t size, const uint32_t type)
{
CARLA_SAFE_ASSERT_RETURN(portSymbol != nullptr && portSymbol[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
CARLA_SAFE_ASSERT_RETURN(size > 0,);
CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL,);
carla_debug("Lv2Plugin::handleLilvSetPortValue(\"%s\", %p, %i, %i:\"%s\")", portSymbol, value, size, type, carla_lv2_urid_unmap(this, type));

int32_t rindex = -1;

for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
{
if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, portSymbol) == 0)
{
rindex = static_cast<int32_t>(i);
break;
}
}

CARLA_SAFE_ASSERT_RETURN(rindex >= 0,);

switch (type)
{
case CARLA_URI_MAP_ID_ATOM_FLOAT:
CARLA_SAFE_ASSERT_RETURN(size == sizeof(float),);

for (uint32_t i=0; i < pData->param.count; ++i)
{
if (pData->param.data[i].rindex == rindex)
{
const float valuef(*(const float*)value);
setParameterValue(i, valuef, true, true, true);
break;
}
}
break;

default:
carla_stdout("Lv2Plugin::handleLilvSetPortValue(\"%s\", %p, %i, %i:\"%s\") - unknown type", portSymbol, value, size, type, carla_lv2_urid_unmap(this, type));
break;
}
}

// -------------------------------------------------------------------

public:
bool init(const char* const bundle, const char* const name, const char* const uri)
{
@@ -2454,12 +2892,315 @@ public:
// ---------------------------------------------------------------
// gui stuff

if (fRdfDescriptor->UICount == 0)
return true;
if (fRdfDescriptor->UICount != 0)
initUi();

return true;
}

// -------------------------------------------------------------------

void initUi()
{
// ---------------------------------------------------------------
// find more appropriate ui

return true;
int eQt4, eQt5, eGtk2, eGtk3, eCocoa, eWindows, eX11, eExt, iCocoa, iWindows, iX11, iExt, iFinal;
eQt4 = eQt5 = eGtk2 = eGtk3 = eCocoa = eWindows = eX11 = eExt = iCocoa = iWindows = iX11 = iExt = iFinal = -1;

#ifdef BUILD_BRIDGE
const bool preferUiBridges(false);
#else
const bool preferUiBridges(pData->engine->getOptions().preferUiBridges && (pData->hints & PLUGIN_IS_BRIDGE) == 0);
#endif

for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
{
CARLA_SAFE_ASSERT_CONTINUE(fRdfDescriptor->UIs[i].URI != nullptr);

const int ii(static_cast<int>(i));

switch (fRdfDescriptor->UIs[i].Type)
{
case LV2_UI_QT4:
if (isUiBridgeable(i))
eQt4 = ii;
break;
case LV2_UI_QT5:
if (isUiBridgeable(i))
eQt5 = ii;
break;
case LV2_UI_GTK2:
if (isUiBridgeable(i))
eGtk2 = ii;
break;
case LV2_UI_GTK3:
if (isUiBridgeable(i))
eGtk3 = ii;
break;
#if defined(CARLA_OS_HAIKU)
#elif defined(CARLA_OS_MAC)
case LV2_UI_COCOA:
if (isUiBridgeable(i) && preferUiBridges)
eCocoa = ii;
iCocoa = ii;
break;
#elif defined(CARLA_OS_WIN)
case LV2_UI_WINDOWS:
if (isUiBridgeable(i) && preferUiBridges)
eWindows = ii;
iWindows = ii;
break;
#else
case LV2_UI_X11:
if (isUiBridgeable(i) && preferUiBridges)
eX11 = ii;
iX11 = ii;
break;
#endif
case LV2_UI_EXTERNAL:
case LV2_UI_OLD_EXTERNAL:
if (isUiBridgeable(i))
eExt = ii;
iExt = ii;
break;
default:
break;
}
}

if (eQt4 >= 0)
iFinal = eQt4;
else if (eQt5 >= 0)
iFinal = eQt5;
else if (eGtk2 >= 0)
iFinal = eGtk2;
else if (eGtk3 >= 0)
iFinal = eGtk3;
else if (eCocoa >= 0)
iFinal = eCocoa;
else if (eWindows >= 0)
iFinal = eWindows;
else if (eX11 >= 0)
iFinal = eX11;
//else if (eExt >= 0) // TODO
// iFinal = eExt;
else if (iCocoa >= 0)
iFinal = iCocoa;
else if (iWindows >= 0)
iFinal = iWindows;
else if (iX11 >= 0)
iFinal = iX11;
else if (iExt >= 0)
iFinal = iExt;

if (iFinal < 0)
{
carla_stderr("Failed to find an appropriate LV2 UI for this plugin");
return;
}

fUi.rdfDescriptor = &fRdfDescriptor->UIs[iFinal];

// ---------------------------------------------------------------
// check supported ui features

bool canContinue = true;

for (uint32_t i=0; i < fUi.rdfDescriptor->FeatureCount; ++i)
{
if (! is_lv2_ui_feature_supported(fUi.rdfDescriptor->Features[i].URI))
{
carla_stderr("Plugin UI requires a feature that is not supported:\n%s", fUi.rdfDescriptor->Features[i].URI);

if (LV2_IS_FEATURE_REQUIRED(fUi.rdfDescriptor->Features[i].Type))
{
canContinue = false;
break;
}
}
}

if (! canContinue)
{
fUi.rdfDescriptor = nullptr;
return;
}

// ---------------------------------------------------------------
// initialize ui according to type

const LV2_Property uiType(fUi.rdfDescriptor->Type);

if (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3 || iFinal == eCocoa || iFinal == eWindows || iFinal == eX11 || iFinal == eExt)
{
// -----------------------------------------------------------
// initialize ui bridge

if (const char* const bridgeBinary = getUiBridgeBinary(uiType))
{
carla_stdout("Will use OSC-Bridge UI, binary: \"%s\"", bridgeBinary);
fUi.type = UI::TYPE_OSC;
pData->osc.thread.setOscData(bridgeBinary, fDescriptor->URI, fUi.rdfDescriptor->URI);
delete[] bridgeBinary;
return;
}
}

// ---------------------------------------------------------------
// open UI DLL

if (! pData->uiLibOpen(fUi.rdfDescriptor->Binary))
{
carla_stderr2("Could not load UI library, error was:\n%s", pData->libError(fUi.rdfDescriptor->Binary));
fUi.rdfDescriptor = nullptr;
return;
}

// ---------------------------------------------------------------
// get UI DLL main entry

LV2UI_DescriptorFunction uiDescFn = (LV2UI_DescriptorFunction)pData->uiLibSymbol("lv2ui_descriptor");

if (uiDescFn == nullptr)
{
carla_stderr2("Could not find the LV2UI Descriptor in the UI library");
pData->uiLibClose();
fUi.rdfDescriptor = nullptr;
return;
}

// ---------------------------------------------------------------
// get UI descriptor that matches UI URI

uint32_t i = 0;
while ((fUi.descriptor = uiDescFn(i++)))
{
if (std::strcmp(fUi.descriptor->URI, fUi.rdfDescriptor->URI) == 0)
break;
}

if (fUi.descriptor == nullptr)
{
carla_stderr2("Could not find the requested GUI in the plugin UI library");
pData->uiLibClose();
fUi.rdfDescriptor = nullptr;
return;
}

// ---------------------------------------------------------------
// check if ui is usable

switch (uiType)
{
case LV2_UI_QT4:
carla_stdout("Will use LV2 Qt4 UI, NOT!");
break;
case LV2_UI_QT5:
carla_stdout("Will use LV2 Qt5 UI, NOT!");
break;
case LV2_UI_GTK2:
carla_stdout("Will use LV2 Gtk2 UI, NOT!");
break;
case LV2_UI_GTK3:
carla_stdout("Will use LV2 Gtk3 UI, NOT!");
break;
#if defined(CARLA_OS_HAIKU)
#elif defined(CARLA_OS_MAC)
case LV2_UI_COCOA:
carla_stdout("Will use LV2 Cocoa UI");
fUi.type = UI::TYPE_EMBED;
break;
#elif defined(CARLA_OS_WIN)
case LV2_UI_WINDOWS:
carla_stdout("Will use LV2 Windows UI");
fUi.type = UI::TYPE_EMBED;
break;
#else
case LV2_UI_X11:
carla_stdout("Will use LV2 X11 UI");
fUi.type = UI::TYPE_EMBED;
break;
#endif
case LV2_UI_EXTERNAL:
case LV2_UI_OLD_EXTERNAL:
carla_stdout("Will use LV2 External UI");
fUi.type = UI::TYPE_EXTERNAL;
break;
}

if (fUi.type == UI::TYPE_NULL)
{
pData->uiLibClose();
fUi.descriptor = nullptr;
fUi.rdfDescriptor = nullptr;
return;
}

// ---------------------------------------------------------------
// initialize ui features (part 1)

QString guiTitle(QString("%1 (GUI)").arg(pData->name));

LV2_Extension_Data_Feature* const uiDataFt = new LV2_Extension_Data_Feature;
uiDataFt->data_access = fDescriptor->extension_data;

LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
uiPortMapFt->handle = this;
uiPortMapFt->port_index = carla_lv2_ui_port_map;

LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
uiResizeFt->handle = this;
uiResizeFt->ui_resize = carla_lv2_ui_resize;

LV2_External_UI_Host* const uiExternalHostFt = new LV2_External_UI_Host;
uiExternalHostFt->ui_closed = carla_lv2_external_ui_closed;
uiExternalHostFt->plugin_human_id = carla_strdup(guiTitle.toUtf8().constData());

// ---------------------------------------------------------------
// initialize ui features (part 2)

for (uint32_t j=kFeatureCountPlugin; j < kFeatureCountAll; ++j)
fFeatures[j] = new LV2_Feature;

fFeatures[kFeatureIdUiDataAccess]->URI = LV2_DATA_ACCESS_URI;
fFeatures[kFeatureIdUiDataAccess]->data = uiDataFt;

fFeatures[kFeatureIdUiInstanceAccess]->URI = LV2_INSTANCE_ACCESS_URI;
fFeatures[kFeatureIdUiInstanceAccess]->data = fHandle;

fFeatures[kFeatureIdUiIdle]->URI = LV2_UI__idle;
fFeatures[kFeatureIdUiIdle]->data = nullptr;

fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
fFeatures[kFeatureIdUiFixedSize]->data = nullptr;

fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
fFeatures[kFeatureIdUiMakeResident]->data = nullptr;

fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;

fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
fFeatures[kFeatureIdUiParent]->data = nullptr;

fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;

fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;

fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
fFeatures[kFeatureIdUiResize]->data = uiResizeFt;

fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
fFeatures[kFeatureIdUiTouch]->data = nullptr;

fFeatures[kFeatureIdExternalUi]->URI = LV2_EXTERNAL_UI__Host;
fFeatures[kFeatureIdExternalUi]->data = uiExternalHostFt;

fFeatures[kFeatureIdExternalUiOld]->URI = LV2_EXTERNAL_UI_DEPRECATED_URI;
fFeatures[kFeatureIdExternalUiOld]->data = uiExternalHostFt;
}

// -------------------------------------------------------------------
@@ -2924,6 +3665,61 @@ private:
return ((Lv2Plugin*)handle)->handleWorkerRespond(size, data);
}

// -------------------------------------------------------------------
// External UI Feature

static void carla_lv2_external_ui_closed(LV2UI_Controller controller)
{
CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
carla_debug("carla_lv2_external_ui_closed(%p)", controller);

((Lv2Plugin*)controller)->handleExternalUiClosed();
}

// -------------------------------------------------------------------
// UI Port-Map Feature

static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
{
CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX);
carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);

return ((Lv2Plugin*)handle)->handleUiPortMap(symbol);
}

// -------------------------------------------------------------------
// UI Resize Feature

static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
{
CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1);
carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);

return ((Lv2Plugin*)handle)->handleUiResize(width, height);
}

// -------------------------------------------------------------------
// UI Extension

static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
{
CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);

((Lv2Plugin*)controller)->handleUiWrite(port_index, buffer_size, format, buffer);
}

// -------------------------------------------------------------------
// Lilv State

static void carla_lilv_set_port_value(const char* port_symbol, void* user_data, const void* value, uint32_t size, uint32_t type)
{
CARLA_SAFE_ASSERT_RETURN(user_data != nullptr,);
carla_debug("carla_lilv_set_port_value(\"%s\", %p, %p, %i, %i", port_symbol, user_data, value, size, type);

((Lv2Plugin*)user_data)->handleLilvSetPortValue(port_symbol, value, size, type);
}

// -------------------------------------------------------------------

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Lv2Plugin)


+ 2
- 1
source/bridges/CarlaBridgeToolkitGtk.cpp View File

@@ -142,7 +142,8 @@ public:
gtk_widget_destroy(fWindow);
fWindow = nullptr;

gtk_main_quit();
if (gtk_main_level() != 0)
gtk_main_quit();
}
}



+ 19
- 11
source/bridges/CarlaBridgeUI-LV2.cpp View File

@@ -18,7 +18,7 @@
#include "CarlaBridgeClient.hpp"
#include "CarlaLv2Utils.hpp"
#include "CarlaMIDI.h"
#include "RtList.hpp"
#include "LinkedList.hpp"

#include <QtCore/QDir>

@@ -26,11 +26,6 @@ extern "C" {
#include "rtmempool/rtmempool-lv2.h"
}

// -----------------------------------------------------
// Our LV2 World class object

Lv2WorldClass gLv2World;

// -----------------------------------------------------

CARLA_BRIDGE_START_NAMESPACE
@@ -330,9 +325,9 @@ public:
}
}

for (NonRtList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
{
const char*& uri(*it);
const char*& uri(it.getValue());

if (uri != nullptr)
{
@@ -357,7 +352,9 @@ public:
// -----------------------------------------------------------------
// get plugin from lv2_rdf (lilv)

gLv2World.init();
Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());

lv2World.load_all(); // FIXME
fRdfDescriptor = lv2_rdf_new(pluginURI, false);

if (fRdfDescriptor == nullptr)
@@ -376,13 +373,19 @@ public:
}

if (fRdfUiDescriptor == nullptr)
{
carla_stderr("Failed to find requested UI");
return false;
}

// -----------------------------------------------------------------
// open DLL

if (! uiLibOpen(fRdfUiDescriptor->Binary))
{
carla_stderr("Failed to load UI binary, error was:\n%s", uiLibError());
return false;
}

// -----------------------------------------------------------------
// get DLL main entry
@@ -403,7 +406,10 @@ public:
}

if (fDescriptor == nullptr)
{
carla_stderr("Failed to find UI descriptor");
return false;
}

// -----------------------------------------------------------
// initialize UI
@@ -415,7 +421,10 @@ public:
fHandle = fDescriptor->instantiate(fDescriptor, pluginURI, fRdfUiDescriptor->Bundle, carla_lv2_ui_write_function, this, &fWidget, fFeatures);

if (fHandle == nullptr)
{
carla_stderr("Failed to init UI");
return false;
}

// -----------------------------------------------------------
// check if not resizable
@@ -689,7 +698,7 @@ private:
Lv2PluginOptions fOptions;

bool fIsResizable;
NonRtList<const char*> fCustomURIDs;
LinkedList<const char*> fCustomURIDs;

struct Extensions {
const LV2_Options_Interface* options;
@@ -1180,7 +1189,6 @@ int main(int argc, char* argv[])
}
else
{
carla_stderr("Failed to load LV2 UI");
ret = 1;
}



+ 25
- 25
source/bridges/Makefile View File

@@ -31,8 +31,8 @@ LINK_PLUGIN_FLAGS += -lpthread
endif

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_PLUGIN_FLAGS += -DWANT_LADSPA
# -DWANT_DSSI -DWANT_LV2 -DWANT_VST
BUILD_PLUGIN_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2
# -DWANT_VST
# ifeq ($(CARLA_VESTIGE_HEADER),true)
# BUILD_PLUGIN_FLAGS += -DVESTIGE_HEADER
# endif
@@ -125,11 +125,11 @@ ifeq ($(CARLA_VESTIGE_HEADER),true)
BUILD_UI_VST_FLAGS += -DVESTIGE_HEADER
endif

BUILD_UI_LV2_GTK2_FLAGS = $(BUILD_UI_LV2_FLAGS) -DBRIDGE_GTK2 -DBRIDGE_LV2_GTK2 $(shell pkg-config --cflags gtk+-2.0 Qt5Core)
LINK_UI_LV2_GTK2_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs gtk+-2.0 Qt5Core)
BUILD_UI_LV2_GTK2_FLAGS = $(BUILD_UI_LV2_FLAGS) -DBRIDGE_GTK2 -DBRIDGE_LV2_GTK2 $(shell pkg-config --cflags gtk+-2.0 QtCore)
LINK_UI_LV2_GTK2_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs gtk+-2.0 QtCore)

BUILD_UI_LV2_GTK3_FLAGS = $(BUILD_UI_LV2_FLAGS) -DBRIDGE_GTK3 -DBRIDGE_LV2_GTK3 $(shell pkg-config --cflags gtk+-3.0 Qt5Core)
LINK_UI_LV2_GTK3_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs gtk+-3.0 Qt5Core)
BUILD_UI_LV2_GTK3_FLAGS = $(BUILD_UI_LV2_FLAGS) -DBRIDGE_GTK3 -DBRIDGE_LV2_GTK3 $(shell pkg-config --cflags gtk+-3.0 QtCore)
LINK_UI_LV2_GTK3_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs gtk+-3.0 QtCore)

BUILD_UI_LV2_QT4_FLAGS = $(BUILD_UI_LV2_FLAGS) -DBRIDGE_QT4 -DBRIDGE_LV2_QT4 $(shell pkg-config --cflags QtCore QtGui)
LINK_UI_LV2_QT4_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs QtCore QtGui)
@@ -159,23 +159,23 @@ LINK_UI_VST_X11_FLAGS = $(LINK_UI_FLAGS) $(QT5_UI_LIBS)

TARGETS = native

# ifeq ($(CARLA_PLUGIN_SUPPORT),true)
# ifeq ($(HAVE_GTK2),true)
# TARGETS += ui_lv2-gtk2
# endif
# ifeq ($(HAVE_GTK3),true)
# TARGETS += ui_lv2-gtk3
# endif
# ifeq ($(HAVE_QT4),true)
# TARGETS += ui_lv2-qt4
# else
# ifeq ($(HAVE_QT5),true)
# TARGETS += ui_lv2-qt5
# endif
# endif
ifeq ($(CARLA_PLUGIN_SUPPORT),true)
ifeq ($(HAVE_GTK2),true)
TARGETS += ui_lv2-gtk2
endif
ifeq ($(HAVE_GTK3),true)
TARGETS += ui_lv2-gtk3
endif
ifeq ($(HAVE_QT4),true)
TARGETS += ui_lv2-qt4
else
ifeq ($(HAVE_QT5),true)
TARGETS += ui_lv2-qt5
endif
endif
# TARGETS += ui_lv2-x11
# TARGETS += ui_vst-x11
# endif
endif

ifeq ($(WIN32),true)
TARGETS = carla-bridge-win32.exe
@@ -424,10 +424,10 @@ endif
# ../modules/dgl.a
# endif

# ifeq ($(CARLA_PLUGIN_SUPPORT),true)
# OBJS_NATIVE += \
# ../modules/lilv.a
# endif
ifeq ($(CARLA_PLUGIN_SUPPORT),true)
OBJS_NATIVE += \
../modules/lilv.a
endif

carla-bridge-native: $(FILES) $(OBJS_NATIVE)
$(CXX) $(OBJS_NATIVE) $(NATIVE_LINK_FLAGS) -o $@


+ 5
- 7
source/modules/lv2_rdf.hpp View File

@@ -212,18 +212,16 @@ typedef uint32_t LV2_Property;
#define LV2_UI_GTK3 2
#define LV2_UI_QT4 3
#define LV2_UI_QT5 4
#define LV2_UI_NTK 5
#define LV2_UI_COCOA 6
#define LV2_UI_WINDOWS 7
#define LV2_UI_X11 8
#define LV2_UI_EXTERNAL 9
#define LV2_UI_OLD_EXTERNAL 10
#define LV2_UI_COCOA 5
#define LV2_UI_WINDOWS 6
#define LV2_UI_X11 7
#define LV2_UI_EXTERNAL 8
#define LV2_UI_OLD_EXTERNAL 9

#define LV2_IS_UI_GTK2(x) ((x) == LV2_UI_GTK2)
#define LV2_IS_UI_GTK3(x) ((x) == LV2_UI_GTK3)
#define LV2_IS_UI_QT4(x) ((x) == LV2_UI_QT4)
#define LV2_IS_UI_QT5(x) ((x) == LV2_UI_QT5)
#define LV2_IS_UI_NTK(x) ((x) == LV2_UI_NTK)
#define LV2_IS_UI_COCOA(x) ((x) == LV2_UI_COCOA)
#define LV2_IS_UI_WINDOWS(x) ((x) == LV2_UI_WINDOWS)
#define LV2_IS_UI_X11(x) ((x) == LV2_UI_X11)


Loading…
Cancel
Save