diff --git a/source/backend/CarlaEngine.hpp b/source/backend/CarlaEngine.hpp index d530511ec..e93313087 100644 --- a/source/backend/CarlaEngine.hpp +++ b/source/backend/CarlaEngine.hpp @@ -291,6 +291,7 @@ struct CARLA_API EngineTimeInfoBBT { #ifndef DOXYGEN EngineTimeInfoBBT() noexcept; + EngineTimeInfoBBT(const EngineTimeInfoBBT&) noexcept; #endif }; @@ -310,6 +311,8 @@ struct CARLA_API EngineTimeInfo { #ifndef DOXYGEN EngineTimeInfo() noexcept; + EngineTimeInfo(const EngineTimeInfo&) noexcept; + EngineTimeInfo& operator=(const EngineTimeInfo&) noexcept; // quick operator, doesn't check all values bool operator==(const EngineTimeInfo& timeInfo) const noexcept; @@ -922,7 +925,7 @@ public: /*! * Get the current Time information (read-only). */ - const EngineTimeInfo& getTimeInfo() const noexcept; + virtual EngineTimeInfo getTimeInfo() const noexcept; // ------------------------------------------------------------------- // Information (peaks) diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index 252bdf14b..c4e34c26a 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -1127,7 +1127,7 @@ const EngineOptions& CarlaEngine::getOptions() const noexcept return pData->options; } -const EngineTimeInfo& CarlaEngine::getTimeInfo() const noexcept +EngineTimeInfo CarlaEngine::getTimeInfo() const noexcept { return pData->timeInfo; } diff --git a/source/backend/engine/CarlaEngineData.cpp b/source/backend/engine/CarlaEngineData.cpp index 1e8c0524c..4e87c424e 100644 --- a/source/backend/engine/CarlaEngineData.cpp +++ b/source/backend/engine/CarlaEngineData.cpp @@ -304,6 +304,17 @@ EngineTimeInfoBBT::EngineTimeInfoBBT() noexcept ticksPerBeat(0.0), beatsPerMinute(0.0) {} +EngineTimeInfoBBT::EngineTimeInfoBBT(const EngineTimeInfoBBT& bbt) noexcept + : valid(bbt.valid), + bar(bbt.bar), + beat(bbt.beat), + tick(bbt.tick), + barStartTick(bbt.barStartTick), + beatsPerBar(bbt.beatsPerBar), + beatType(bbt.beatType), + ticksPerBeat(bbt.ticksPerBeat), + beatsPerMinute(bbt.beatsPerMinute) {} + // ----------------------------------------------------------------------- // EngineTimeInfo @@ -321,6 +332,30 @@ void EngineTimeInfo::clear() noexcept carla_zeroStruct(bbt); } +EngineTimeInfo::EngineTimeInfo(const EngineTimeInfo& info) noexcept + : playing(info.playing), + frame(info.frame), + usecs(info.usecs), + bbt(info.bbt) {} + +EngineTimeInfo& EngineTimeInfo::operator=(const EngineTimeInfo& info) noexcept +{ + playing = info.playing; + frame = info.frame; + usecs = info.usecs; + bbt.valid = info.bbt.valid; + bbt.bar = info.bbt.bar; + bbt.tick = info.bbt.tick; + bbt.tick = info.bbt.tick; + bbt.barStartTick = info.bbt.barStartTick; + bbt.beatsPerBar = info.bbt.beatsPerBar; + bbt.beatType = info.bbt.beatType; + bbt.ticksPerBeat = info.bbt.ticksPerBeat; + bbt.beatsPerMinute = info.bbt.beatsPerMinute; + + return *this; +} + bool EngineTimeInfo::operator==(const EngineTimeInfo& timeInfo) const noexcept { if (timeInfo.playing != playing || timeInfo.frame != frame || timeInfo.bbt.valid != bbt.valid) diff --git a/source/backend/engine/CarlaEngineInternal.cpp b/source/backend/engine/CarlaEngineInternal.cpp index 748ee1dfe..2c4e84b76 100644 --- a/source/backend/engine/CarlaEngineInternal.cpp +++ b/source/backend/engine/CarlaEngineInternal.cpp @@ -176,10 +176,11 @@ void EngineInternalTime::fillEngineTimeInfo(const uint32_t newFrames) noexcept double ticktmp; - timeInfo.usecs = 0; - if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) + { + timeInfo.usecs = 0; timeInfo.frame = nextFrame; + } if (needsReset) { @@ -256,74 +257,19 @@ void EngineInternalTime::fillJackTimeInfo(jack_position_t* const pos, const uint { CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),); CARLA_SAFE_ASSERT_RETURN(newFrames > 0,); - - double ticktmp; - - if (needsReset) - { - pos->valid = JackPositionBBT; - pos->beat_type = 4.0f; - pos->ticks_per_beat = kTicksPerBeat; - - double abs_beat, abs_tick; - -#if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE) - if (hylia.enabled) - { - if (hylia.timeInfo.beat >= 0.0) - { - abs_beat = hylia.timeInfo.beat; - abs_tick = abs_beat * kTicksPerBeat; - } - else - { - abs_beat = 0.0; - abs_tick = 0.0; - timeInfo.playing = false; - } - } - else -#endif - { - const double min = static_cast(pos->frame) / (sampleRate * 60.0); - abs_beat = min * beatsPerMinute; - abs_tick = abs_beat * kTicksPerBeat; - } - - const double bar = std::floor(abs_beat / beatsPerBar); - const double beat = std::floor(std::fmod(abs_beat, beatsPerBar)); - - pos->bar = static_cast(bar) + 1; - pos->beat = static_cast(beat) + 1; - pos->bar_start_tick = ((bar * beatsPerBar) + beat) * kTicksPerBeat; - - ticktmp = abs_tick - pos->bar_start_tick; - } - else if (timeInfo.playing) - { - ticktmp = tick + (newFrames * kTicksPerBeat * beatsPerMinute / (sampleRate * 60.0)); - - while (ticktmp >= kTicksPerBeat) - { - ticktmp -= kTicksPerBeat; - - if (++pos->beat > beatsPerBar) - { - ++pos->bar; - pos->beat = 1; - pos->bar_start_tick += beatsPerBar * kTicksPerBeat; - } - } - } - else - { - ticktmp = tick; - } - - pos->beats_per_bar = static_cast(beatsPerBar); + CARLA_SAFE_ASSERT(transportMode == ENGINE_TRANSPORT_MODE_JACK); + + fillEngineTimeInfo(newFrames); + + pos->valid = JackPositionBBT; + pos->bar = timeInfo.bbt.bar; + pos->beat = timeInfo.bbt.beat; + pos->tick = static_cast(tick + 0.5); + pos->bar_start_tick = timeInfo.bbt.barStartTick; + pos->beats_per_bar = timeInfo.bbt.beatsPerBar; + pos->beat_type = timeInfo.bbt.beatType; + pos->ticks_per_beat = kTicksPerBeat; pos->beats_per_minute = beatsPerMinute; - pos->tick = ticktmp; - tick = ticktmp; } void EngineInternalTime::preProcess(const uint32_t numFrames) diff --git a/source/backend/engine/CarlaEngineJack.cpp b/source/backend/engine/CarlaEngineJack.cpp index 14343c245..99f33d0c9 100644 --- a/source/backend/engine/CarlaEngineJack.cpp +++ b/source/backend/engine/CarlaEngineJack.cpp @@ -811,6 +811,7 @@ public: fIsRunning(false) #else fTimebaseMaster(false), + fTimebaseRolling(false), fUsedGroups(), fUsedPorts(), fUsedConnections(), @@ -950,6 +951,8 @@ public: jackbridge_set_process_callback(fClient, carla_jack_process_callback, this); jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback, this); + fTimebaseRolling = false; + if (opts.transportMode == ENGINE_TRANSPORT_MODE_JACK) fTimebaseMaster = jackbridge_set_timebase_callback(fClient, true, carla_jack_timebase_callback, this); else @@ -1086,6 +1089,55 @@ public: return "JACK"; } + EngineTimeInfo getTimeInfo() const noexcept override + { + if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) + return CarlaEngine::getTimeInfo(); + if (pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS) + return CarlaEngine::getTimeInfo(); + + jack_position_t jpos; + + // invalidate + jpos.unique_1 = 1; + jpos.unique_2 = 2; + + EngineTimeInfo timeInfo; + const bool playing = jackbridge_transport_query(fClient, &jpos) == JackTransportRolling; + + if (jpos.unique_1 != jpos.unique_2) + { + timeInfo.playing = false; + timeInfo.frame = 0; + timeInfo.usecs = 0; + timeInfo.bbt.valid = false; + return timeInfo; + } + + timeInfo.playing = playing; + timeInfo.frame = jpos.frame; + timeInfo.usecs = jpos.usecs; + + if (jpos.valid & JackPositionBBT) + { + timeInfo.bbt.valid = true; + timeInfo.bbt.bar = jpos.bar; + timeInfo.bbt.beat = jpos.beat; + timeInfo.bbt.tick = jpos.tick; + timeInfo.bbt.barStartTick = jpos.bar_start_tick; + timeInfo.bbt.beatsPerBar = jpos.beats_per_bar; + timeInfo.bbt.beatType = jpos.beat_type; + timeInfo.bbt.ticksPerBeat = jpos.ticks_per_beat; + timeInfo.bbt.beatsPerMinute = jpos.beats_per_minute; + } + else + { + timeInfo.bbt.valid = false; + } + + return timeInfo; + } + #ifndef BUILD_BRIDGE void setOption(const EngineOption option, const int value, const char* const valueStr) noexcept override { @@ -1392,7 +1444,7 @@ public: void transportPlay() noexcept override { - if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) + if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) return CarlaEngine::transportPlay(); if (fClient != nullptr) @@ -1412,7 +1464,7 @@ public: void transportPause() noexcept override { - if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) + if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) return CarlaEngine::transportPause(); if (fClient != nullptr) @@ -1425,9 +1477,10 @@ public: void transportBPM(const double bpm) noexcept override { - CarlaEngine::transportBPM(bpm); + if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK || fTimebaseMaster) + return CarlaEngine::transportBPM(bpm); - if (fClient == nullptr || fTimebaseMaster) + if (fClient == nullptr) return; jack_position_t jpos; @@ -1450,7 +1503,7 @@ public: void transportRelocate(const uint64_t frame) noexcept override { - if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL) + if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) return CarlaEngine::transportRelocate(frame); if (fClient != nullptr) @@ -1557,57 +1610,12 @@ protected: offlineModeChanged(isFreewheel); } - void saveTransportInfo() - { - if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK) - return; - - jack_position_t jpos; - - // invalidate - jpos.unique_1 = 1; - jpos.unique_2 = 2; - - pData->timeInfo.playing = (jackbridge_transport_query(fClient, &jpos) == JackTransportRolling); - - if (jpos.unique_1 == jpos.unique_2) - { - pData->timeInfo.frame = jpos.frame; - pData->timeInfo.usecs = jpos.usecs; - - if (jpos.valid & JackPositionBBT) - { - pData->timeInfo.bbt.valid = true; - pData->timeInfo.bbt.bar = jpos.bar; - pData->timeInfo.bbt.beat = jpos.beat; - pData->timeInfo.bbt.tick = jpos.tick; - pData->timeInfo.bbt.barStartTick = jpos.bar_start_tick; - pData->timeInfo.bbt.beatsPerBar = jpos.beats_per_bar; - pData->timeInfo.bbt.beatType = jpos.beat_type; - pData->timeInfo.bbt.ticksPerBeat = jpos.ticks_per_beat; - pData->timeInfo.bbt.beatsPerMinute = jpos.beats_per_minute; - } - else - { - pData->timeInfo.bbt.valid = false; - } - } - else - { - pData->timeInfo.frame = 0; - pData->timeInfo.usecs = 0; - pData->timeInfo.bbt.valid = false; - } - } - void handleJackProcessCallback(const uint32_t nframes) { const PendingRtEventsRunner prt(this, nframes); CARLA_SAFE_ASSERT_RETURN(nframes == pData->bufferSize,); - saveTransportInfo(); - #ifdef BUILD_BRIDGE CarlaPlugin* const plugin(pData->plugins[0].plugin); @@ -1783,6 +1791,18 @@ protected: } } } + + if (fTimebaseMaster) + { + const bool playing = jackbridge_transport_query(fClient, nullptr) == JackTransportRolling; + + if (fTimebaseRolling != playing) + { + carla_stdout("state changed SAVE %i", playing); + fTimebaseRolling = playing; + pData->timeInfo.playing = playing; + } + } #endif // ! BUILD_BRIDGE } @@ -1797,6 +1817,9 @@ protected: if (new_pos) pData->time.setNeedsReset(); + pData->timeInfo.playing = fTimebaseRolling; + pData->timeInfo.frame = pos->frame; + pData->timeInfo.usecs = pos->usecs; pData->time.fillJackTimeInfo(pos, nframes); } @@ -2055,6 +2078,8 @@ private: jack_port_t* fRackPorts[kRackPortCount]; bool fTimebaseMaster; + bool fTimebaseRolling; + PatchbayGroupList fUsedGroups; PatchbayPortList fUsedPorts; PatchbayConnectionList fUsedConnections; @@ -2486,15 +2511,15 @@ private: handlePtr->handleJackFreewheelCallback(bool(starting)); } - static int JACKBRIDGE_API carla_jack_process_callback(jack_nframes_t nframes, void* arg) __attribute__((annotate("realtime"))) + static void JACKBRIDGE_API carla_jack_latency_callback(jack_latency_callback_mode_t mode, void* arg) { - handlePtr->handleJackProcessCallback(nframes); - return 0; + handlePtr->handleJackLatencyCallback(mode); } - static void JACKBRIDGE_API carla_jack_latency_callback(jack_latency_callback_mode_t mode, void* arg) + static int JACKBRIDGE_API carla_jack_process_callback(jack_nframes_t nframes, void* arg) __attribute__((annotate("realtime"))) { - handlePtr->handleJackLatencyCallback(mode); + handlePtr->handleJackProcessCallback(nframes); + return 0; } #ifndef BUILD_BRIDGE @@ -2567,7 +2592,6 @@ private: if (plugin->tryLock(engine->fFreewheel)) { plugin->initBuffers(); - engine->saveTransportInfo(); engine->processPlugin(plugin, nframes); plugin->unlock(); } diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index 5b7bc504f..3817dc33f 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -1467,7 +1467,7 @@ public: // -------------------------------------------------------------------------------------------------------- // TimeInfo - const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); + const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); bridgeTimeInfo.playing = timeInfo.playing; diff --git a/source/backend/plugin/CarlaPluginJack.cpp b/source/backend/plugin/CarlaPluginJack.cpp index a01dd2b1a..777f26047 100644 --- a/source/backend/plugin/CarlaPluginJack.cpp +++ b/source/backend/plugin/CarlaPluginJack.cpp @@ -940,7 +940,7 @@ public: // -------------------------------------------------------------------------------------------------------- // TimeInfo - const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); + const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo); bridgeTimeInfo.playing = timeInfo.playing; diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index 964c96143..a77d96454 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -2779,7 +2779,7 @@ public: // -------------------------------------------------------------------------------------------------------- // TimeInfo - const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); + const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); if (fFirstActive || fLastTimeInfo != timeInfo) { diff --git a/source/backend/plugin/CarlaPluginNative.cpp b/source/backend/plugin/CarlaPluginNative.cpp index 4b34f2378..7f08b4348 100644 --- a/source/backend/plugin/CarlaPluginNative.cpp +++ b/source/backend/plugin/CarlaPluginNative.cpp @@ -1537,7 +1537,7 @@ public: // -------------------------------------------------------------------------------------------------------- // Set TimeInfo - const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); + const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); fTimeInfo.playing = timeInfo.playing; fTimeInfo.frame = timeInfo.frame; @@ -1563,6 +1563,39 @@ public: fTimeInfo.bbt.valid = false; } +#if 0 + // This test code has proven to be quite useful + // So I am leaving it behind, I might need it again.. + if (pData->id == 1) + { + static int64_t last_frame = timeInfo.frame; + static int64_t last_dev_frame = 0; + static double last_val = timeInfo.bbt.barStartTick + ((timeInfo.bbt.beat-1) * timeInfo.bbt.ticksPerBeat) + timeInfo.bbt.tick; + static double last_dev_val = 0.0; + + int64_t cur_frame = timeInfo.frame; + int64_t cur_dev_frame = cur_frame - last_frame; + + double cur_val = timeInfo.bbt.barStartTick + ((timeInfo.bbt.beat-1) * timeInfo.bbt.ticksPerBeat) + timeInfo.bbt.tick; + double cur_dev_val = cur_val - last_val; + + if (std::abs(last_dev_val - cur_dev_val) >= 0.0001 || last_dev_frame != cur_dev_frame) + { + carla_stdout("currently %u at %u => %f : DEV1: %li : DEV2: %f", + frames, + timeInfo.frame, + cur_val, + cur_dev_frame, + cur_dev_val); + } + + last_val = cur_val; + last_dev_val = cur_dev_val; + last_frame = cur_frame; + last_dev_frame = cur_dev_frame; + } +#endif + // -------------------------------------------------------------------------------------------------------- // Event Input and Processing diff --git a/source/backend/plugin/CarlaPluginVST2.cpp b/source/backend/plugin/CarlaPluginVST2.cpp index e2a7284cb..ec5a47066 100644 --- a/source/backend/plugin/CarlaPluginVST2.cpp +++ b/source/backend/plugin/CarlaPluginVST2.cpp @@ -1121,7 +1121,7 @@ public: // -------------------------------------------------------------------------------------------------------- // Set TimeInfo - const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo()); + const EngineTimeInfo timeInfo(pData->engine->getTimeInfo()); fTimeInfo.flags = kVstTransportChanged;