Browse Source

Continue splitting of carla-plugin LV2 code

tags/1.9.8
falkTX 7 years ago
parent
commit
518f2557a1
17 changed files with 410 additions and 363 deletions
  1. +2
    -3
      source/backend/CarlaEngine.hpp
  2. +2
    -9
      source/backend/CarlaStandalone.cpp
  3. +5
    -5
      source/backend/engine/CarlaEngineBridge.cpp
  4. +6
    -6
      source/backend/engine/CarlaEngineData.cpp
  5. +6
    -1
      source/backend/engine/CarlaEngineInternal.cpp
  6. +5
    -4
      source/backend/engine/CarlaEngineJack.cpp
  7. +5
    -7
      source/backend/engine/CarlaEngineNative.cpp
  8. +5
    -5
      source/backend/plugin/CarlaPluginBridge.cpp
  9. +5
    -5
      source/backend/plugin/CarlaPluginJack.cpp
  10. +18
    -10
      source/backend/plugin/CarlaPluginLV2.cpp
  11. +3
    -1
      source/backend/plugin/CarlaPluginNative.cpp
  12. +1
    -1
      source/backend/plugin/CarlaPluginVST2.cpp
  13. +46
    -80
      source/bridges-plugin/CarlaBridgeLV2.cpp
  14. +2
    -2
      source/libjack/libjack.cpp
  15. +38
    -218
      source/plugin/carla-lv2.cpp
  16. +5
    -1
      source/utils/CarlaBridgeDefines.hpp
  17. +256
    -5
      source/utils/CarlaLv2Utils.hpp

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

@@ -274,6 +274,8 @@ struct CARLA_API EngineOptions {
* Engine BBT Time information.
*/
struct CARLA_API EngineTimeInfoBBT {
bool valid;

int32_t bar; //!< current bar
int32_t beat; //!< current beat-within-bar
int32_t tick; //!< current tick-within-beat
@@ -294,12 +296,9 @@ struct CARLA_API EngineTimeInfoBBT {
* Engine Time information.
*/
struct CARLA_API EngineTimeInfo {
static const uint kValidBBT = 0x1;

bool playing;
uint64_t frame;
uint64_t usecs;
uint valid;
EngineTimeInfoBBT bbt;

/*!


+ 2
- 9
source/backend/CarlaStandalone.cpp View File

@@ -788,14 +788,7 @@ uint64_t carla_get_current_transport_frame()
const CarlaTransportInfo* carla_get_transport_info()
{
static CarlaTransportInfo retInfo;

// reset
retInfo.playing = false;
retInfo.frame = 0;
retInfo.bar = 0;
retInfo.beat = 0;
retInfo.tick = 0;
retInfo.bpm = 0.0;
carla_zeroStruct(retInfo);

CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr && gStandalone.engine->isRunning(), &retInfo);

@@ -804,7 +797,7 @@ const CarlaTransportInfo* carla_get_transport_info()
retInfo.playing = timeInfo.playing;
retInfo.frame = timeInfo.frame;

if (timeInfo.valid & CB::EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
retInfo.bar = timeInfo.bbt.bar;
retInfo.beat = timeInfo.bbt.beat;


+ 5
- 5
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -1180,12 +1180,12 @@ protected:

EngineTimeInfo& timeInfo(pData->timeInfo);

timeInfo.playing = bridgeTimeInfo.playing;
timeInfo.frame = bridgeTimeInfo.frame;
timeInfo.usecs = bridgeTimeInfo.usecs;
timeInfo.valid = bridgeTimeInfo.valid;
timeInfo.playing = bridgeTimeInfo.playing;
timeInfo.frame = bridgeTimeInfo.frame;
timeInfo.usecs = bridgeTimeInfo.usecs;
timeInfo.bbt.valid = (bridgeTimeInfo.validFlags & kPluginBridgeTimeInfoValidBBT) != 0;

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
timeInfo.bbt.bar = bridgeTimeInfo.bar;
timeInfo.bbt.beat = bridgeTimeInfo.beat;


+ 6
- 6
source/backend/engine/CarlaEngineData.cpp View File

@@ -1,6 +1,6 @@
/*
* Carla Plugin Host
* Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -308,7 +308,8 @@ EngineOptions::Wine::~Wine() noexcept
// EngineTimeInfoBBT

EngineTimeInfoBBT::EngineTimeInfoBBT() noexcept
: bar(0),
: valid(false),
bar(0),
beat(0),
tick(0),
barStartTick(0.0),
@@ -324,7 +325,6 @@ EngineTimeInfo::EngineTimeInfo() noexcept
: playing(false),
frame(0),
usecs(0),
valid(0x0),
bbt() {}

void EngineTimeInfo::clear() noexcept
@@ -332,14 +332,14 @@ void EngineTimeInfo::clear() noexcept
playing = false;
frame = 0;
usecs = 0;
valid = 0x0;
carla_zeroStruct(bbt);
}

bool EngineTimeInfo::operator==(const EngineTimeInfo& timeInfo) const noexcept
{
if (timeInfo.playing != playing || timeInfo.frame != frame || timeInfo.valid != valid)
if (timeInfo.playing != playing || timeInfo.frame != frame || timeInfo.bbt.valid != bbt.valid)
return false;
if ((valid & kValidBBT) == 0)
if (! bbt.valid)
return true;
if (carla_isNotEqual(timeInfo.bbt.beatsPerMinute, bbt.beatsPerMinute))
return false;


+ 6
- 1
source/backend/engine/CarlaEngineInternal.cpp View File

@@ -175,7 +175,7 @@ void EngineInternalTime::fillEngineTimeInfo(const uint32_t newFrames) noexcept

if (needsReset)
{
timeInfo.valid = EngineTimeInfo::kValidBBT;
timeInfo.bbt.valid = true;
timeInfo.bbt.beatType = 4.0f;
timeInfo.bbt.ticksPerBeat = kTicksPerBeat;

@@ -563,6 +563,11 @@ void CarlaEngine::ProtectedData::initTime(const char* const features)
#if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
const bool linkEnabled = features != nullptr && std::strstr(features, ":link:") != nullptr;
time.enableLink(linkEnabled);
#else
return;

// unused
(void)features;
#endif
}



+ 5
- 4
source/backend/engine/CarlaEngineJack.cpp View File

@@ -1393,7 +1393,7 @@ public:

if (fClient != nullptr)
{
if ((pData->timeInfo.valid & EngineTimeInfo::kValidBBT) == 0x0)
if (! pData->timeInfo.bbt.valid)
{
// old timebase master no longer active, make ourselves master again
pData->time.setNeedsReset();
@@ -1573,7 +1573,7 @@ protected:

if (jpos.valid & JackPositionBBT)
{
pData->timeInfo.valid = EngineTimeInfo::kValidBBT;
pData->timeInfo.bbt.valid = true;
pData->timeInfo.bbt.bar = jpos.bar;
pData->timeInfo.bbt.beat = jpos.beat;
pData->timeInfo.bbt.tick = jpos.tick;
@@ -1585,13 +1585,14 @@ protected:
}
else
{
pData->timeInfo.valid = 0x0;
pData->timeInfo.bbt.valid = false;
}
}
else
{
pData->timeInfo.frame = 0;
pData->timeInfo.valid = 0x0;
pData->timeInfo.usecs = 0;
pData->timeInfo.bbt.valid = false;
}
}



+ 5
- 7
source/backend/engine/CarlaEngineNative.cpp View File

@@ -1471,15 +1471,13 @@ protected:

const NativeTimeInfo* const timeInfo(pHost->get_time_info(pHost->handle));

pData->timeInfo.playing = timeInfo->playing;
pData->timeInfo.frame = timeInfo->frame;
pData->timeInfo.usecs = timeInfo->usecs;
pData->timeInfo.valid = 0x0;
pData->timeInfo.playing = timeInfo->playing;
pData->timeInfo.frame = timeInfo->frame;
pData->timeInfo.usecs = timeInfo->usecs;
pData->timeInfo.bbt.valid = timeInfo->bbt.valid;

if (timeInfo->bbt.valid)
{
pData->timeInfo.valid |= EngineTimeInfo::kValidBBT;

pData->timeInfo.bbt.bar = timeInfo->bbt.bar;
pData->timeInfo.bbt.beat = timeInfo->bbt.beat;
pData->timeInfo.bbt.tick = timeInfo->bbt.tick;
@@ -1748,7 +1746,7 @@ protected:
if (! fUiServer.writeMessage(timeInfo.playing ? "true\n" : "false\n"))
return;

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
std::sprintf(tmpBuf, P_UINT64 ":%i:%i:%i\n", timeInfo.frame, timeInfo.bbt.bar, timeInfo.bbt.beat, timeInfo.bbt.tick);
if (! fUiServer.writeMessage(tmpBuf))


+ 5
- 5
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -1388,12 +1388,12 @@ public:
const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);

bridgeTimeInfo.playing = timeInfo.playing;
bridgeTimeInfo.frame = timeInfo.frame;
bridgeTimeInfo.usecs = timeInfo.usecs;
bridgeTimeInfo.valid = timeInfo.valid;
bridgeTimeInfo.playing = timeInfo.playing;
bridgeTimeInfo.frame = timeInfo.frame;
bridgeTimeInfo.usecs = timeInfo.usecs;
bridgeTimeInfo.validFlags = timeInfo.bbt.valid ? kPluginBridgeTimeInfoValidBBT : 0x0;

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
bridgeTimeInfo.bar = timeInfo.bbt.bar;
bridgeTimeInfo.beat = timeInfo.bbt.beat;


+ 5
- 5
source/backend/plugin/CarlaPluginJack.cpp View File

@@ -921,12 +921,12 @@ public:
const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);

bridgeTimeInfo.playing = timeInfo.playing;
bridgeTimeInfo.frame = timeInfo.frame;
bridgeTimeInfo.usecs = timeInfo.usecs;
bridgeTimeInfo.valid = timeInfo.valid;
bridgeTimeInfo.playing = timeInfo.playing;
bridgeTimeInfo.frame = timeInfo.frame;
bridgeTimeInfo.usecs = timeInfo.usecs;
bridgeTimeInfo.validFlags = timeInfo.bbt.valid ? kPluginBridgeTimeInfoValidBBT : 0x0;

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
bridgeTimeInfo.bar = timeInfo.bbt.bar;
bridgeTimeInfo.beat = timeInfo.bbt.beat;


+ 18
- 10
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -2824,6 +2824,7 @@ public:
doPostRt = true;
}
break;

case LV2_PORT_DESIGNATION_TIME_FRAME:
if (fLastTimeInfo.frame != timeInfo.frame)
{
@@ -2831,55 +2832,62 @@ public:
doPostRt = true;
}
break;

case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND:
break;

// BBT
case LV2_PORT_DESIGNATION_TIME_BAR:
if ((timeInfo.valid & EngineTimeInfo::kValidBBT) != 0 && fLastTimeInfo.bbt.bar != timeInfo.bbt.bar)
if (timeInfo.bbt.valid && fLastTimeInfo.bbt.bar != timeInfo.bbt.bar)
{
fParamBuffers[k] = static_cast<float>(timeInfo.bbt.bar - 1);
doPostRt = true;
}
break;

case LV2_PORT_DESIGNATION_TIME_BAR_BEAT:
if ((timeInfo.valid & EngineTimeInfo::kValidBBT) != 0 && (fLastTimeInfo.bbt.tick != timeInfo.bbt.tick ||
fLastTimeInfo.bbt.beat != timeInfo.bbt.beat))
if (timeInfo.bbt.valid && (fLastTimeInfo.bbt.tick != timeInfo.bbt.tick ||
fLastTimeInfo.bbt.beat != timeInfo.bbt.beat))
{
fParamBuffers[k] = static_cast<float>(static_cast<double>(timeInfo.bbt.beat) - 1.0 + (static_cast<double>(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat));
fParamBuffers[k] = static_cast<float>(static_cast<double>(timeInfo.bbt.beat) - 1.0
+ (static_cast<double>(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat));
doPostRt = true;
}
break;

case LV2_PORT_DESIGNATION_TIME_BEAT:
if ((timeInfo.valid & EngineTimeInfo::kValidBBT) != 0 && fLastTimeInfo.bbt.beat != timeInfo.bbt.beat)
if (timeInfo.bbt.valid && fLastTimeInfo.bbt.beat != timeInfo.bbt.beat)
{
fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beat - 1);
doPostRt = true;
}
break;

case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT:
if ((timeInfo.valid & EngineTimeInfo::kValidBBT) != 0 && carla_isNotEqual(fLastTimeInfo.bbt.beatType, timeInfo.bbt.beatType))
if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatType, timeInfo.bbt.beatType))
{
fParamBuffers[k] = timeInfo.bbt.beatType;
doPostRt = true;
}
break;
case LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR:
if ((timeInfo.valid & EngineTimeInfo::kValidBBT) != 0 && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerBar, timeInfo.bbt.beatsPerBar))
if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerBar, timeInfo.bbt.beatsPerBar))
{
fParamBuffers[k] = timeInfo.bbt.beatsPerBar;
doPostRt = true;
}
break;

case LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE:
if ((timeInfo.valid & EngineTimeInfo::kValidBBT) != 0 && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerMinute, timeInfo.bbt.beatsPerMinute))
if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerMinute, timeInfo.bbt.beatsPerMinute))
{
fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beatsPerMinute);
doPostRt = true;
}
break;

case LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT:
if ((timeInfo.valid & EngineTimeInfo::kValidBBT) != 0 && carla_isNotEqual(fLastTimeInfo.bbt.ticksPerBeat, timeInfo.bbt.ticksPerBeat))
if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.ticksPerBeat, timeInfo.bbt.ticksPerBeat))
{
fParamBuffers[k] = static_cast<float>(timeInfo.bbt.ticksPerBeat);
doPostRt = true;
@@ -2908,7 +2916,7 @@ public:
lv2_atom_forge_key(&fAtomForge, kUridTimeFrame);
lv2_atom_forge_long(&fAtomForge, static_cast<int64_t>(timeInfo.frame));

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
lv2_atom_forge_key(&fAtomForge, kUridTimeBar);
lv2_atom_forge_long(&fAtomForge, timeInfo.bbt.bar - 1);


+ 3
- 1
source/backend/plugin/CarlaPluginNative.cpp View File

@@ -1383,7 +1383,7 @@ public:
fTimeInfo.frame = timeInfo.frame;
fTimeInfo.usecs = timeInfo.usecs;

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
fTimeInfo.bbt.valid = true;

@@ -1399,7 +1399,9 @@ public:
fTimeInfo.bbt.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
}
else
{
fTimeInfo.bbt.valid = false;
}

// --------------------------------------------------------------------------------------------------------
// Event Input and Processing


+ 1
- 1
source/backend/plugin/CarlaPluginVST2.cpp View File

@@ -1092,7 +1092,7 @@ public:
fTimeInfo.flags |= kVstNanosValid;
}

if (timeInfo.valid & EngineTimeInfo::kValidBBT)
if (timeInfo.bbt.valid)
{
CARLA_SAFE_ASSERT_INT(timeInfo.bbt.bar > 0, timeInfo.bbt.bar);
CARLA_SAFE_ASSERT_INT(timeInfo.bbt.beat > 0, timeInfo.bbt.beat);


+ 46
- 80
source/bridges-plugin/CarlaBridgeLV2.cpp View File

@@ -29,12 +29,12 @@

#include "water/files/File.h"

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

CARLA_BACKEND_START_NAMESPACE

class CarlaEngineLV2Single : public CarlaEngine,
public Lv2PluginBaseClass
public Lv2PluginBaseClass<EngineTimeInfo>
{
public:
CarlaEngineLV2Single(const double sampleRate,
@@ -42,10 +42,8 @@ public:
const LV2_Feature* const* const features)
: Lv2PluginBaseClass(sampleRate, features),
fPlugin(nullptr),
fIsActive(false),
fIsOffline(false),
fPorts(),
fUI()
fUiName(),
fPorts()
{
CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount == 0,)
CARLA_SAFE_ASSERT_RETURN(pData->plugins[0].plugin == nullptr,);
@@ -112,7 +110,7 @@ public:
return fPlugin != nullptr;
}

// -----------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// LV2 functions

void lv2_connect_port(const uint32_t port, void* const dataLocation) noexcept
@@ -124,6 +122,8 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(! fIsActive,);

resetTimeInfo();

fPlugin->setActive(true, false, false);
fIsActive = true;
}
@@ -138,6 +138,9 @@ public:

void lv2_run(const uint32_t frames)
{
if (! lv2_pre_run(frames))
return;

fIsOffline = (fPorts.freewheel != nullptr && *fPorts.freewheel >= 0.5f);

// Check for updated parameters
@@ -174,10 +177,11 @@ public:
carla_zeroFloats(fPorts.audioOuts[i], frames);
}

lv2_post_run(frames);
fPorts.updateOutputs();
}

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

void lv2ui_instantiate(LV2UI_Write_Function writeFunction, LV2UI_Controller controller,
LV2UI_Widget* widget, const LV2_Feature* const* features)
@@ -185,9 +189,11 @@ public:
fUI.writeFunction = writeFunction;
fUI.controller = controller;

fUiName.clear();

const LV2_URID_Map* uridMap = nullptr;

// -------------------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------------------
// see if the host supports external-ui, get uridMap

for (int i=0; features[i] != nullptr; ++i)
@@ -205,12 +211,12 @@ public:

if (fUI.host != nullptr)
{
fUI.name = fUI.host->plugin_human_id;
*widget = (LV2_External_UI_Widget*)this;
fUiName = fUI.host->plugin_human_id;
*widget = (LV2_External_UI_Widget*)this;
return;
}

// -------------------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------------------
// no external-ui support, use showInterface

for (int i=0; features[i] != nullptr; ++i)
@@ -223,7 +229,7 @@ public:
{
if (options[j].key == uridMap->map(uridMap->handle, LV2_UI__windowTitle))
{
fUI.name = (const char*)options[j].value;
fUiName = (const char*)options[j].value;
break;
}
}
@@ -231,8 +237,8 @@ public:
}
}

if (fUI.name.isEmpty())
fUI.name = fPlugin->getName();
if (fUiName.isEmpty())
fUiName = fPlugin->getName();

*widget = nullptr;
}
@@ -241,48 +247,15 @@ public:
{
if (format != 0 || bufferSize != sizeof(float) || buffer == nullptr)
return;
if (portIndex >= fPorts.indexOffset || ! fUI.visible)
if (portIndex >= fPorts.indexOffset || ! fUI.isVisible)
return;

const float value(*(const float*)buffer);
fPlugin->uiParameterChange(portIndex-fPorts.indexOffset, value);
}

void lv2ui_cleanup()
{
if (fUI.visible)
handleUiHide();

fUI.writeFunction = nullptr;
fUI.controller = nullptr;
fUI.host = nullptr;
}

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

int lv2ui_idle() const
{
if (! fUI.visible)
return 1;

handleUiRun();
return 0;
}

int lv2ui_show()
{
handleUiShow();
return 0;
}

int lv2ui_hide()
{
handleUiHide();
return 0;
}

protected:
// -----------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// CarlaEngine virtual calls

bool init(const char* const clientName) override
@@ -330,7 +303,7 @@ protected:
{
case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
CARLA_SAFE_ASSERT_RETURN(value1 >= 0,);
if (fUI.writeFunction != nullptr && fUI.controller != nullptr && fUI.visible)
if (fUI.writeFunction != nullptr && fUI.controller != nullptr && fUI.isVisible)
{
fUI.writeFunction(fUI.controller,
static_cast<uint32_t>(value1)+fPorts.indexOffset,
@@ -339,7 +312,7 @@ protected:
break;

case ENGINE_CALLBACK_UI_STATE_CHANGED:
fUI.visible = value1 == 1;
fUI.isVisible = (value1 == 1);
if (fUI.host != nullptr)
fUI.host->ui_closed(fUI.controller);
break;
@@ -354,7 +327,7 @@ protected:
}
}

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

void handleUiRun() const override
{
@@ -366,23 +339,32 @@ protected:
void handleUiShow() override
{
fPlugin->showCustomUI(true);
fUI.visible = true;
fUI.isVisible = true;
}

void handleUiHide() override
{
fUI.visible = false;
fUI.isVisible = false;
fPlugin->showCustomUI(false);
}

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

void handleBufferSizeChanged(const uint32_t bufferSize) override
{
CarlaEngine::bufferSizeChanged(bufferSize);
}

void handleSampleRateChanged(const double sampleRate) override
{
CarlaEngine::sampleRateChanged(sampleRate);
}

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

private:
CarlaPlugin* fPlugin;

// Lv2 host data
bool fIsActive;
bool fIsOffline;
CarlaString fUiName;

struct Ports {
uint32_t numAudioIns;
@@ -535,22 +517,6 @@ private:
CARLA_DECLARE_NON_COPY_STRUCT(Ports);
} fPorts;

struct UI {
LV2UI_Write_Function writeFunction;
LV2UI_Controller controller;
const LV2_External_UI_Host* host;
CarlaString name;
bool visible;

UI()
: writeFunction(nullptr),
controller(nullptr),
host(nullptr),
name(),
visible(false) {}
CARLA_DECLARE_NON_COPY_STRUCT(UI)
} fUI;

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

#define handlePtr ((CarlaEngineLV2Single*)handle)
@@ -569,7 +535,7 @@ CARLA_BACKEND_END_NAMESPACE

using CarlaBackend::CarlaEngineLV2Single;

// ---------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// LV2 DSP functions

static LV2_Handle lv2_instantiate(const LV2_Descriptor* lv2Descriptor, double sampleRate, const char* bundlePath, const LV2_Feature* const* features)
@@ -624,7 +590,7 @@ static const void* lv2_extension_data(const char* uri)

#undef instancePtr

// ---------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// LV2 UI functions

static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char*, const char*,
@@ -703,7 +669,7 @@ static const void* lv2ui_extension_data(const char* uri)

#undef uiPtr

// ---------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Startup code

CARLA_EXPORT
@@ -762,4 +728,4 @@ const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
return (index == 0) ? &lv2UiExtDesc : nullptr;
}

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

+ 2
- 2
source/libjack/libjack.cpp View File

@@ -596,7 +596,7 @@ bool CarlaJackAppClient::handleRtData()
fServer.position.frame = bridgeTimeInfo.frame;
fServer.position.usecs = bridgeTimeInfo.usecs;

if (bridgeTimeInfo.valid & 0x1 /* kValidBBT */)
if (bridgeTimeInfo.validFlags & kPluginBridgeTimeInfoValidBBT)
{
fServer.position.valid = JackPositionBBT;

@@ -613,7 +613,7 @@ bool CarlaJackAppClient::handleRtData()
}
else
{
fServer.position.valid = static_cast<jack_position_bits_t>(0);
fServer.position.valid = static_cast<jack_position_bits_t>(0x0);
}

int numClientOutputsProcessed = 0;


+ 38
- 218
source/plugin/carla-lv2.cpp View File

@@ -25,7 +25,7 @@
// -----------------------------------------------------------------------
// LV2 descriptor functions

class NativePlugin : public Lv2PluginBaseClass
class NativePlugin : public Lv2PluginBaseClass<NativeTimeInfo>
{
public:
static const uint32_t kMaxMidiEvents = 512;
@@ -42,9 +42,6 @@ public:
fProgramDesc({0, 0, nullptr}),
#endif
fMidiEventCount(0),
fTimeInfo(),
fLastPositionData(),
fUI(),
fPorts()
{
carla_zeroStruct(fHost);
@@ -82,6 +79,12 @@ public:
delete[] fHost.resourceDir;
fHost.resourceDir = nullptr;
}

if (fHost.uiName != nullptr)
{
delete[] fHost.uiName;
fHost.uiName = nullptr;
}
}

bool init()
@@ -96,7 +99,6 @@ public:
}

carla_zeroStructs(fMidiEvents, kMaxMidiEvents);
carla_zeroStruct(fTimeInfo);

fHandle = fDescriptor->instantiate(&fHost);
CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);
@@ -128,17 +130,7 @@ public:
if (fDescriptor->activate != nullptr)
fDescriptor->activate(fHandle);

carla_zeroStruct(fTimeInfo);

// hosts may not send all values, resulting on some invalid data
fTimeInfo.bbt.bar = 1;
fTimeInfo.bbt.beat = 1;
fTimeInfo.bbt.tick = 0;
fTimeInfo.bbt.barStartTick = 0;
fTimeInfo.bbt.beatsPerBar = 4;
fTimeInfo.bbt.beatType = 4;
fTimeInfo.bbt.ticksPerBeat = 960.0;
fTimeInfo.bbt.beatsPerMinute = 120.0;
resetTimeInfo();
}

void lv2_deactivate()
@@ -157,6 +149,9 @@ public:

void lv2_run(const uint32_t frames)
{
if (! lv2_pre_run(frames))
return;

fIsOffline = (fPorts.freewheel != nullptr && *fPorts.freewheel >= 0.5f);

// cache midi events and time information first
@@ -484,130 +479,12 @@ public:
const_cast<float**>(fPorts.audioIns), fPorts.audioOuts, frames,
fMidiEvents, fMidiEventCount);

// update timePos for next callback
if (carla_isNotZero(fLastPositionData.speed))
{
if (fLastPositionData.speed > 0.0)
{
// playing forwards
fLastPositionData.frame += frames;
}
else
{
// playing backwards
if (frames >= fLastPositionData.frame)
fLastPositionData.frame = 0;
else
fLastPositionData.frame -= frames;
}

fTimeInfo.frame = fLastPositionData.frame;

if (fTimeInfo.bbt.valid)
{
const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed;
const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute;
const double addedBarBeats = double(frames) / framesPerBeat;

if (fLastPositionData.barBeat >= 0.0f)
{
fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+static_cast<float>(addedBarBeats),
fLastPositionData.beatsPerBar);

const double rest = std::fmod(fLastPositionData.barBeat, 1.0f);
fTimeInfo.bbt.beat = static_cast<int32_t>(fLastPositionData.barBeat-rest+1.0);
fTimeInfo.bbt.tick = static_cast<int32_t>(rest*fTimeInfo.bbt.ticksPerBeat+0.5);

if (fLastPositionData.bar_f >= 0.0f)
{
fLastPositionData.bar_f += std::floor((fLastPositionData.barBeat+static_cast<float>(addedBarBeats))/
fLastPositionData.beatsPerBar);

if (fLastPositionData.bar_f <= 0.0f)
{
fLastPositionData.bar = 0;
fLastPositionData.bar_f = 0.0f;
}
else
{
fLastPositionData.bar = static_cast<int32_t>(fLastPositionData.bar_f+0.5f);
}

fTimeInfo.bbt.bar = fLastPositionData.bar + 1;

fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat*
fTimeInfo.bbt.beatsPerBar*
(fTimeInfo.bbt.bar-1);
}
}
}
}

lv2_post_run(frames);
updateParameterOutputs();
}

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

uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) const
{
// currently unused
return LV2_OPTIONS_SUCCESS;
}

uint32_t lv2_set_options(const LV2_Options_Option* const options)
{
for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
{
if (options[i].type == fURIs.atomInt)
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

fBufferSize = static_cast<uint32_t>(value);

if (fDescriptor->dispatcher != nullptr)
fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, value, nullptr, 0.0f);
}
else
carla_stderr("Host changed nominalBlockLength but with wrong value type");
}
else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength) && ! fUsingNominal)
{
if (options[i].type == fURIs.atomInt)
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

fBufferSize = static_cast<uint32_t>(value);

if (fDescriptor->dispatcher != nullptr)
fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, value, nullptr, 0.0f);
}
else
carla_stderr("Host changed maxBlockLength but with wrong value type");
}
else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate))
{
if (options[i].type == fURIs.atomDouble)
{
const double value(*(const double*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0.0);

fSampleRate = value;

if (fDescriptor->dispatcher != nullptr)
fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, (float)fSampleRate);
}
else
carla_stderr("Host changed sampleRate but with wrong value type");
}
}

return LV2_OPTIONS_SUCCESS;
}

const LV2_Program_Descriptor* lv2_get_program(const uint32_t index)
{
if (fDescriptor->category == NATIVE_PLUGIN_CATEGORY_SYNTH)
@@ -696,6 +573,12 @@ public:
fUI.controller = controller;
fUI.isEmbed = isEmbed;

if (fHost.uiName != nullptr)
{
delete[] fHost.uiName;
fHost.uiName = nullptr;
}

#ifdef CARLA_OS_LINUX
// ---------------------------------------------------------------
// show embed UI if needed
@@ -810,22 +693,6 @@ public:
fDescriptor->ui_set_parameter_value(fHandle, portIndex-fUI.portOffset, value);
}

void lv2ui_cleanup()
{
if (fUI.isVisible)
handleUiHide();

fUI.host = nullptr;
fUI.writeFunction = nullptr;
fUI.controller = nullptr;

if (fHost.uiName != nullptr)
{
delete[] fHost.uiName;
fHost.uiName = nullptr;
}
}

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

void lv2ui_select_program(uint32_t bank, uint32_t program) const
@@ -838,30 +705,7 @@ public:
fDescriptor->ui_set_midi_program(fHandle, 0, bank, program);
}

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

int lv2ui_idle() const
{
if (! fUI.isVisible)
return 1;

handleUiRun();
return 0;
}

int lv2ui_show()
{
handleUiShow();
return 0;
}

int lv2ui_hide()
{
handleUiHide();
return 0;
}

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

protected:
void handleUiRun() const override
@@ -886,7 +730,25 @@ protected:
fUI.isVisible = false;
}

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

void handleBufferSizeChanged(const uint32_t bufferSize) override
{
if (fDescriptor->dispatcher == nullptr)
return;

fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, bufferSize, nullptr, 0.0f);
}

void handleSampleRateChanged(const double sampleRate) override
{
if (fDescriptor->dispatcher == nullptr)
return;

fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, (float)sampleRate);
}

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

bool handleWriteMidiEvent(const NativeMidiEvent* const event)
{
@@ -1010,48 +872,6 @@ private:

uint32_t fMidiEventCount;
NativeMidiEvent fMidiEvents[kMaxMidiEvents];
NativeTimeInfo fTimeInfo;

struct Lv2PositionData {
int32_t bar;
float bar_f;
float barBeat;
uint32_t beatUnit;
float beatsPerBar;
double beatsPerMinute;
uint64_t frame;
double speed;
double ticksPerBeat;

Lv2PositionData()
: bar(-1),
bar_f(-1.0f),
barBeat(-1.0f),
beatUnit(0),
beatsPerBar(0.0f),
beatsPerMinute(-1.0),
frame(0),
speed(0.0),
ticksPerBeat(-1.0) {}

} fLastPositionData;

struct UI {
const LV2_External_UI_Host* host;
LV2UI_Write_Function writeFunction;
LV2UI_Controller controller;
uint32_t portOffset;
bool isEmbed;
bool isVisible;

UI()
: host(nullptr),
writeFunction(nullptr),
controller(nullptr),
portOffset(0),
isEmbed(false),
isVisible(false) {}
} fUI;

struct Ports {
// need to save current state


+ 5
- 1
source/utils/CarlaBridgeDefines.hpp View File

@@ -114,6 +114,10 @@ enum PluginBridgePortType {
kPluginBridgePortTypeCount
};

enum PluginBridgeTimeInfoFlags {
kPluginBridgeTimeInfoValidBBT = 0x1
};

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

struct BridgeSemaphore {
@@ -132,7 +136,7 @@ struct BridgeTimeInfo {
uint64_t playing;
uint64_t frame;
uint64_t usecs;
uint32_t valid;
uint32_t validFlags;
// bbt
int32_t bar, beat, tick;
float beatsPerBar, beatType;


+ 256
- 5
source/utils/CarlaLv2Utils.hpp View File

@@ -525,6 +525,7 @@ public:
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Weffc++"
#endif
template<class TimeInfoStruct>
class Lv2PluginBaseClass : public LV2_External_UI_Widget_Compat
{
#if defined(__clang__)
@@ -534,11 +535,16 @@ class Lv2PluginBaseClass : public LV2_External_UI_Widget_Compat
#endif
public:
Lv2PluginBaseClass(const double sampleRate, const LV2_Feature* const* const features)
: fIsOffline(false),
: fIsActive(false),
fIsOffline(false),
fUsingNominal(false),
fBufferSize(0),
fSampleRate(sampleRate),
fUsingNominal(false),
fUridMap(nullptr)
fUridMap(nullptr),
fTimeInfo(),
fLastPositionData(),
fURIs(),
fUI()
{
run = extui_run;
show = extui_show;
@@ -620,6 +626,9 @@ public:

fUridMap = uridMap;
fURIs.map(uridMap);

carla_zeroStruct(fTimeInfo);
carla_zeroStruct(fLastPositionData);
}

virtual ~Lv2PluginBaseClass()
@@ -631,20 +640,245 @@ public:
return fUridMap != nullptr && fBufferSize != 0;
}

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

bool lv2_pre_run(const uint32_t /*frames*/)
{
return true;
}

void lv2_post_run(const uint32_t frames)
{
// update timePos for next callback

if (carla_isZero(fLastPositionData.speed))
return;

if (fLastPositionData.speed > 0.0)
{
// playing forwards
fLastPositionData.frame += frames;
}
else
{
// playing backwards
if (frames >= fLastPositionData.frame)
fLastPositionData.frame = 0;
else
fLastPositionData.frame -= frames;
}

fTimeInfo.frame = fLastPositionData.frame;

if (fTimeInfo.bbt.valid)
{
const double beatsPerMinute = fLastPositionData.beatsPerMinute * fLastPositionData.speed;
const double framesPerBeat = 60.0 * fSampleRate / beatsPerMinute;
const double addedBarBeats = double(frames) / framesPerBeat;

if (fLastPositionData.barBeat >= 0.0f)
{
fLastPositionData.barBeat = std::fmod(fLastPositionData.barBeat+static_cast<float>(addedBarBeats),
fLastPositionData.beatsPerBar);

const double rest = std::fmod(fLastPositionData.barBeat, 1.0f);
fTimeInfo.bbt.beat = static_cast<int32_t>(fLastPositionData.barBeat-rest+1.0);
fTimeInfo.bbt.tick = static_cast<int32_t>(rest*fTimeInfo.bbt.ticksPerBeat+0.5);

if (fLastPositionData.bar_f >= 0.0f)
{
fLastPositionData.bar_f += std::floor((fLastPositionData.barBeat+static_cast<float>(addedBarBeats))/
fLastPositionData.beatsPerBar);

if (fLastPositionData.bar_f <= 0.0f)
{
fLastPositionData.bar = 0;
fLastPositionData.bar_f = 0.0f;
}
else
{
fLastPositionData.bar = static_cast<int32_t>(fLastPositionData.bar_f+0.5f);
}

fTimeInfo.bbt.bar = fLastPositionData.bar + 1;

fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat *
fTimeInfo.bbt.beatsPerBar *
(fTimeInfo.bbt.bar-1);
}
}
}
}

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

uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) const
{
// currently unused
return LV2_OPTIONS_SUCCESS;
}

uint32_t lv2_set_options(const LV2_Options_Option* const options)
{
for (int i=0; options[i].key != 0; ++i)
{
if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
{
if (options[i].type == fURIs.atomInt)
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

const uint32_t newBufferSize = static_cast<uint32_t>(value);

if (fBufferSize != newBufferSize)
{
fBufferSize = newBufferSize;
handleBufferSizeChanged(newBufferSize);
}
}
else
{
carla_stderr("Host changed nominalBlockLength but with wrong value type");
}
}
else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength) && ! fUsingNominal)
{
if (options[i].type == fURIs.atomInt)
{
const int value(*(const int*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0);

const uint32_t newBufferSize = static_cast<uint32_t>(value);

if (fBufferSize != newBufferSize)
{
fBufferSize = newBufferSize;
handleBufferSizeChanged(newBufferSize);
}
}
else
{
carla_stderr("Host changed maxBlockLength but with wrong value type");
}
}
else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_PARAMETERS__sampleRate))
{
if (options[i].type == fURIs.atomFloat)
{
const double value(*(const float*)options[i].value);
CARLA_SAFE_ASSERT_CONTINUE(value > 0.0);

if (carla_isNotEqual(fSampleRate, value))
{
fSampleRate = value;
handleSampleRateChanged(value);
}
}
else
{
carla_stderr("Host changed sampleRate but with wrong value type");
}
}
}

return LV2_OPTIONS_SUCCESS;
}

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

int lv2ui_idle() const
{
if (! fUI.isVisible)
return 1;

handleUiRun();
return 0;
}

int lv2ui_show()
{
handleUiShow();
return 0;
}

int lv2ui_hide()
{
handleUiHide();
return 0;
}

void lv2ui_cleanup()
{
if (fUI.isVisible)
handleUiHide();

fUI.host = nullptr;
fUI.writeFunction = nullptr;
fUI.controller = nullptr;
}

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

protected:
virtual void handleUiRun() const = 0;
virtual void handleUiShow() = 0;
virtual void handleUiHide() = 0;

virtual void handleBufferSizeChanged(const uint32_t bufferSize) = 0;
virtual void handleSampleRateChanged(const double sampleRate) = 0;

// LV2 host data
bool fIsOffline;
bool fIsActive : 1;
bool fIsOffline : 1;
bool fUsingNominal : 1;
uint32_t fBufferSize;
double fSampleRate;
bool fUsingNominal;

// LV2 host features
const LV2_URID_Map* fUridMap;

// Time info stuff
TimeInfoStruct fTimeInfo;

struct Lv2PositionData {
int32_t bar;
float bar_f;
float barBeat;
uint32_t beatUnit;
float beatsPerBar;
double beatsPerMinute;
uint64_t frame;
double speed;
double ticksPerBeat;

Lv2PositionData()
: bar(-1),
bar_f(-1.0f),
barBeat(-1.0f),
beatUnit(0),
beatsPerBar(0.0f),
beatsPerMinute(-1.0),
frame(0),
speed(0.0),
ticksPerBeat(-1.0) {}
} fLastPositionData;

void resetTimeInfo()
{
carla_zeroStruct(fLastPositionData);
carla_zeroStruct(fTimeInfo);

// hosts may not send all values, resulting on some invalid data
fTimeInfo.bbt.bar = 1;
fTimeInfo.bbt.beat = 1;
fTimeInfo.bbt.beatsPerBar = 4;
fTimeInfo.bbt.beatType = 4;
fTimeInfo.bbt.ticksPerBeat = fLastPositionData.ticksPerBeat = 960.0;
fTimeInfo.bbt.beatsPerMinute = fLastPositionData.beatsPerMinute = 120.0;
}

// Rest of host<->plugin support
struct URIDs {
LV2_URID atomBlank;
LV2_URID atomObject;
@@ -708,6 +942,23 @@ protected:
}
} fURIs;

struct UI {
const LV2_External_UI_Host* host;
LV2UI_Write_Function writeFunction;
LV2UI_Controller controller;
uint32_t portOffset;
bool isEmbed;
bool isVisible;

UI()
: host(nullptr),
writeFunction(nullptr),
controller(nullptr),
portOffset(0),
isEmbed(false),
isVisible(false) {}
} fUI;

private:
// ----------------------------------------------------------------------------------------------------------------



Loading…
Cancel
Save