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. * Engine BBT Time information.
*/ */
struct CARLA_API EngineTimeInfoBBT { struct CARLA_API EngineTimeInfoBBT {
bool valid;

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

bool playing; bool playing;
uint64_t frame; uint64_t frame;
uint64_t usecs; uint64_t usecs;
uint valid;
EngineTimeInfoBBT bbt; 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() const CarlaTransportInfo* carla_get_transport_info()
{ {
static CarlaTransportInfo retInfo; 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); 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.playing = timeInfo.playing;
retInfo.frame = timeInfo.frame; retInfo.frame = timeInfo.frame;


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


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

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


EngineTimeInfo& timeInfo(pData->timeInfo); 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.bar = bridgeTimeInfo.bar;
timeInfo.bbt.beat = bridgeTimeInfo.beat; timeInfo.bbt.beat = bridgeTimeInfo.beat;


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

@@ -1,6 +1,6 @@
/* /*
* Carla Plugin Host * 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@@ -308,7 +308,8 @@ EngineOptions::Wine::~Wine() noexcept
// EngineTimeInfoBBT // EngineTimeInfoBBT


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


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


bool EngineTimeInfo::operator==(const EngineTimeInfo& timeInfo) const noexcept 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; return false;
if ((valid & kValidBBT) == 0)
if (! bbt.valid)
return true; return true;
if (carla_isNotEqual(timeInfo.bbt.beatsPerMinute, bbt.beatsPerMinute)) if (carla_isNotEqual(timeInfo.bbt.beatsPerMinute, bbt.beatsPerMinute))
return false; 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) if (needsReset)
{ {
timeInfo.valid = EngineTimeInfo::kValidBBT;
timeInfo.bbt.valid = true;
timeInfo.bbt.beatType = 4.0f; timeInfo.bbt.beatType = 4.0f;
timeInfo.bbt.ticksPerBeat = kTicksPerBeat; timeInfo.bbt.ticksPerBeat = kTicksPerBeat;


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

// unused
(void)features;
#endif #endif
} }




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

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


if (fClient != nullptr) 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 // old timebase master no longer active, make ourselves master again
pData->time.setNeedsReset(); pData->time.setNeedsReset();
@@ -1573,7 +1573,7 @@ protected:


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

pData->timeInfo.bbt.bar = timeInfo->bbt.bar; pData->timeInfo.bbt.bar = timeInfo->bbt.bar;
pData->timeInfo.bbt.beat = timeInfo->bbt.beat; pData->timeInfo.bbt.beat = timeInfo->bbt.beat;
pData->timeInfo.bbt.tick = timeInfo->bbt.tick; pData->timeInfo.bbt.tick = timeInfo->bbt.tick;
@@ -1748,7 +1746,7 @@ protected:
if (! fUiServer.writeMessage(timeInfo.playing ? "true\n" : "false\n")) if (! fUiServer.writeMessage(timeInfo.playing ? "true\n" : "false\n"))
return; 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); std::sprintf(tmpBuf, P_UINT64 ":%i:%i:%i\n", timeInfo.frame, timeInfo.bbt.bar, timeInfo.bbt.beat, timeInfo.bbt.tick);
if (! fUiServer.writeMessage(tmpBuf)) if (! fUiServer.writeMessage(tmpBuf))


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

@@ -1388,12 +1388,12 @@ public:
const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); 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.bar = timeInfo.bbt.bar;
bridgeTimeInfo.beat = timeInfo.bbt.beat; 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()); const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); 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.bar = timeInfo.bbt.bar;
bridgeTimeInfo.beat = timeInfo.bbt.beat; bridgeTimeInfo.beat = timeInfo.bbt.beat;


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

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

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

case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND: case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND:
break; break;


// BBT // BBT
case LV2_PORT_DESIGNATION_TIME_BAR: 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); fParamBuffers[k] = static_cast<float>(timeInfo.bbt.bar - 1);
doPostRt = true; doPostRt = true;
} }
break; break;

case LV2_PORT_DESIGNATION_TIME_BAR_BEAT: 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; doPostRt = true;
} }
break; break;

case LV2_PORT_DESIGNATION_TIME_BEAT: 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); fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beat - 1);
doPostRt = true; doPostRt = true;
} }
break; break;

case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT: 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; fParamBuffers[k] = timeInfo.bbt.beatType;
doPostRt = true; doPostRt = true;
} }
break; break;
case LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR: 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; fParamBuffers[k] = timeInfo.bbt.beatsPerBar;
doPostRt = true; doPostRt = true;
} }
break; break;

case LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE: 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); fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beatsPerMinute);
doPostRt = true; doPostRt = true;
} }
break; break;

case LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT: 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); fParamBuffers[k] = static_cast<float>(timeInfo.bbt.ticksPerBeat);
doPostRt = true; doPostRt = true;
@@ -2908,7 +2916,7 @@ public:
lv2_atom_forge_key(&fAtomForge, kUridTimeFrame); lv2_atom_forge_key(&fAtomForge, kUridTimeFrame);
lv2_atom_forge_long(&fAtomForge, static_cast<int64_t>(timeInfo.frame)); 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_key(&fAtomForge, kUridTimeBar);
lv2_atom_forge_long(&fAtomForge, timeInfo.bbt.bar - 1); 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.frame = timeInfo.frame;
fTimeInfo.usecs = timeInfo.usecs; fTimeInfo.usecs = timeInfo.usecs;


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


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


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


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

@@ -1092,7 +1092,7 @@ public:
fTimeInfo.flags |= kVstNanosValid; 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.bar > 0, timeInfo.bbt.bar);
CARLA_SAFE_ASSERT_INT(timeInfo.bbt.beat > 0, timeInfo.bbt.beat); 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" #include "water/files/File.h"


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


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


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


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


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


resetTimeInfo();

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


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

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


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


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


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


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


fUiName.clear();

const LV2_URID_Map* uridMap = nullptr; const LV2_URID_Map* uridMap = nullptr;


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


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


if (fUI.host != nullptr) 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; return;
} }


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


for (int i=0; features[i] != nullptr; ++i) for (int i=0; features[i] != nullptr; ++i)
@@ -223,7 +229,7 @@ public:
{ {
if (options[j].key == uridMap->map(uridMap->handle, LV2_UI__windowTitle)) 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; break;
} }
} }
@@ -231,8 +237,8 @@ public:
} }
} }


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


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


const float value(*(const float*)buffer); const float value(*(const float*)buffer);
fPlugin->uiParameterChange(portIndex-fPorts.indexOffset, value); 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: protected:
// -----------------------------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------------------
// CarlaEngine virtual calls // CarlaEngine virtual calls


bool init(const char* const clientName) override bool init(const char* const clientName) override
@@ -330,7 +303,7 @@ protected:
{ {
case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED:
CARLA_SAFE_ASSERT_RETURN(value1 >= 0,); 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, fUI.writeFunction(fUI.controller,
static_cast<uint32_t>(value1)+fPorts.indexOffset, static_cast<uint32_t>(value1)+fPorts.indexOffset,
@@ -339,7 +312,7 @@ protected:
break; break;


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


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


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


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


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

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

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

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


private: private:
CarlaPlugin* fPlugin; CarlaPlugin* fPlugin;

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


struct Ports { struct Ports {
uint32_t numAudioIns; uint32_t numAudioIns;
@@ -535,22 +517,6 @@ private:
CARLA_DECLARE_NON_COPY_STRUCT(Ports); CARLA_DECLARE_NON_COPY_STRUCT(Ports);
} fPorts; } 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) #define handlePtr ((CarlaEngineLV2Single*)handle)
@@ -569,7 +535,7 @@ CARLA_BACKEND_END_NAMESPACE


using CarlaBackend::CarlaEngineLV2Single; using CarlaBackend::CarlaEngineLV2Single;


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


static LV2_Handle lv2_instantiate(const LV2_Descriptor* lv2Descriptor, double sampleRate, const char* bundlePath, const LV2_Feature* const* features) 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 #undef instancePtr


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


static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char*, const char*, 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 #undef uiPtr


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


CARLA_EXPORT CARLA_EXPORT
@@ -762,4 +728,4 @@ const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
return (index == 0) ? &lv2UiExtDesc : nullptr; 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.frame = bridgeTimeInfo.frame;
fServer.position.usecs = bridgeTimeInfo.usecs; fServer.position.usecs = bridgeTimeInfo.usecs;


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


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


int numClientOutputsProcessed = 0; int numClientOutputsProcessed = 0;


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

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


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

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


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


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


fHandle = fDescriptor->instantiate(&fHost); fHandle = fDescriptor->instantiate(&fHost);
CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);
@@ -128,17 +130,7 @@ public:
if (fDescriptor->activate != nullptr) if (fDescriptor->activate != nullptr)
fDescriptor->activate(fHandle); 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() void lv2_deactivate()
@@ -157,6 +149,9 @@ public:


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

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


// cache midi events and time information first // cache midi events and time information first
@@ -484,130 +479,12 @@ public:
const_cast<float**>(fPorts.audioIns), fPorts.audioOuts, frames, const_cast<float**>(fPorts.audioIns), fPorts.audioOuts, frames,
fMidiEvents, fMidiEventCount); 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(); 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) const LV2_Program_Descriptor* lv2_get_program(const uint32_t index)
{ {
if (fDescriptor->category == NATIVE_PLUGIN_CATEGORY_SYNTH) if (fDescriptor->category == NATIVE_PLUGIN_CATEGORY_SYNTH)
@@ -696,6 +573,12 @@ public:
fUI.controller = controller; fUI.controller = controller;
fUI.isEmbed = isEmbed; fUI.isEmbed = isEmbed;


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

#ifdef CARLA_OS_LINUX #ifdef CARLA_OS_LINUX
// --------------------------------------------------------------- // ---------------------------------------------------------------
// show embed UI if needed // show embed UI if needed
@@ -810,22 +693,6 @@ public:
fDescriptor->ui_set_parameter_value(fHandle, portIndex-fUI.portOffset, value); 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 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); 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: protected:
void handleUiRun() const override void handleUiRun() const override
@@ -886,7 +730,25 @@ protected:
fUI.isVisible = false; 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) bool handleWriteMidiEvent(const NativeMidiEvent* const event)
{ {
@@ -1010,48 +872,6 @@ private:


uint32_t fMidiEventCount; uint32_t fMidiEventCount;
NativeMidiEvent fMidiEvents[kMaxMidiEvents]; 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 { struct Ports {
// need to save current state // need to save current state


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

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


enum PluginBridgeTimeInfoFlags {
kPluginBridgeTimeInfoValidBBT = 0x1
};

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


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


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

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


fUridMap = uridMap; fUridMap = uridMap;
fURIs.map(uridMap); fURIs.map(uridMap);

carla_zeroStruct(fTimeInfo);
carla_zeroStruct(fLastPositionData);
} }


virtual ~Lv2PluginBaseClass() virtual ~Lv2PluginBaseClass()
@@ -631,20 +640,245 @@ public:
return fUridMap != nullptr && fBufferSize != 0; 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: protected:
virtual void handleUiRun() const = 0; virtual void handleUiRun() const = 0;
virtual void handleUiShow() = 0; virtual void handleUiShow() = 0;
virtual void handleUiHide() = 0; virtual void handleUiHide() = 0;


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

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


// LV2 host features // LV2 host features
const LV2_URID_Map* fUridMap; 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 { struct URIDs {
LV2_URID atomBlank; LV2_URID atomBlank;
LV2_URID atomObject; LV2_URID atomObject;
@@ -708,6 +942,23 @@ protected:
} }
} fURIs; } 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: private:
// ---------------------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------------------




Loading…
Cancel
Save