Browse Source

Implement JACK timebase master; Cleanup

tags/1.9.7b
falkTX 7 years ago
parent
commit
b10f6aadbf
5 changed files with 126 additions and 57 deletions
  1. +3
    -3
      source/backend/engine/CarlaEngine.cpp
  2. +77
    -24
      source/backend/engine/CarlaEngineInternal.cpp
  3. +6
    -4
      source/backend/engine/CarlaEngineInternal.hpp
  4. +39
    -25
      source/backend/engine/CarlaEngineJack.cpp
  5. +1
    -1
      source/backend/engine/CarlaEngineNative.cpp

+ 3
- 3
source/backend/engine/CarlaEngine.cpp View File

@@ -1343,19 +1343,19 @@ void CarlaEngine::setFileCallback(const FileCallbackFunc func, void* const ptr)

void CarlaEngine::transportPlay() noexcept
{
pData->time.playing = true;
pData->timeInfo.playing = true;
pData->time.fillEngineTimeInfo(pData->timeInfo, 0);
}

void CarlaEngine::transportPause() noexcept
{
pData->time.playing = false;
pData->timeInfo.playing = false;
pData->time.fillEngineTimeInfo(pData->timeInfo, 0);
}

void CarlaEngine::transportRelocate(const uint64_t frame) noexcept
{
pData->time.frame = frame;
pData->timeInfo.frame = frame;
pData->time.fillEngineTimeInfo(pData->timeInfo, 0);
}



+ 77
- 24
source/backend/engine/CarlaEngineInternal.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
@@ -18,6 +18,8 @@
#include "CarlaEngineInternal.hpp"
#include "CarlaPlugin.hpp"

#include "jackbridge/JackBridge.hpp"

CARLA_BACKEND_START_NAMESPACE

// -----------------------------------------------------------------------
@@ -60,16 +62,15 @@ void EngineInternalEvents::clear() noexcept
static const float kTicksPerBeat = 1920.0f;

EngineInternalTime::EngineInternalTime() noexcept
: playing(false),
frame(0),
bpm(120.0),
: bpm(120.0),
sampleRate(0.0),
tick(0.0),
#ifdef BUILD_BRIDGE
tick(0.0) {}
needsReset(true) {}
#else
tick(0.0),
hylia(nullptr),
hylia_enabled(0)
needsReset(true),
hylia_enabled(false),
hylia(nullptr)
{
carla_zeroStruct(hylia_time);
}
@@ -86,11 +87,9 @@ void EngineInternalTime::fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t
{
CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),);

info.playing = playing;
info.frame = frame;
info.usecs = 0;
info.usecs = 0;

if (newFrames == 0)
if (newFrames == 0 || needsReset)
{
info.valid = EngineTimeInfo::kValidBBT;
info.bbt.beatsPerBar = 4.0f;
@@ -101,20 +100,17 @@ void EngineInternalTime::fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t
double abs_beat, abs_tick;

#if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
if (hylia_enabled > 0 && hylia_time.bpm > 0.0)
if (hylia_enabled && hylia_time.beats >= 0.0)
{
const double beats = hylia_time.beats;

if (beats < 0.0)
return;

abs_beat = std::floor(beats);
abs_tick = beats * kTicksPerBeat;
}
else
#endif
{
const double min = frame / (sampleRate * 60.0);
const double min = info.frame / (sampleRate * 60.0);
abs_tick = min * bpm * kTicksPerBeat;
abs_beat = abs_tick / kTicksPerBeat;
}
@@ -143,6 +139,64 @@ void EngineInternalTime::fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t
}

info.bbt.tick = (int)(tick + 0.5);
needsReset = false;
}

void EngineInternalTime::fillJackTimeInfo(jack_position_t* const pos, const uint32_t newFrames) noexcept
{
CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),);

if (newFrames == 0 || needsReset)
{
pos->valid = JackPositionBBT;
pos->beats_per_bar = 4.0f;
pos->beat_type = 4.0f;
pos->ticks_per_beat = kTicksPerBeat;
pos->beats_per_minute = bpm;

double abs_beat, abs_tick;

#if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
if (hylia_enabled && hylia_time.beats >= 0.0)
{
const double beats = hylia_time.beats;

abs_beat = std::floor(beats);
abs_tick = beats * kTicksPerBeat;
}
else
#endif
{
const double min = pos->frame / (sampleRate * 60.0);
abs_tick = min * bpm * kTicksPerBeat;
abs_beat = abs_tick / kTicksPerBeat;
}

pos->bar = abs_beat / pos->beats_per_bar;
pos->beat = abs_beat - (pos->bar * pos->beats_per_bar) + 1;
tick = abs_tick - (abs_beat * kTicksPerBeat);
pos->bar_start_tick = pos->bar * pos->beats_per_bar * kTicksPerBeat;
pos->bar++;
}
else
{
tick += newFrames * kTicksPerBeat * bpm / (sampleRate * 60);

while (tick >= kTicksPerBeat)
{
tick -= kTicksPerBeat;

if (++pos->beat > pos->beats_per_bar)
{
pos->beat = 1;
++pos->bar;
pos->bar_start_tick += pos->beats_per_bar * pos->ticks_per_beat;
}
}
}

pos->tick = (int)(tick + 0.5);
needsReset = false;
}

// -----------------------------------------------------------------------
@@ -339,11 +393,10 @@ void CarlaEngine::ProtectedData::close()

void CarlaEngine::ProtectedData::initTime()
{
time.playing = false;
time.frame = 0;
time.bpm = 120.0;
time.sampleRate = sampleRate;
time.tick = 0.0;
time.needsReset = true;
time.fillEngineTimeInfo(timeInfo, 0);

#if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
@@ -451,15 +504,15 @@ PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const ui
bufferSize(bufSize)
{
#if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
if (pData->time.hylia_enabled > 0)
if (pData->time.hylia_enabled)
{
hylia_process(pData->time.hylia, bufferSize, &pData->time.hylia_time);
const double new_bpm = pData->time.hylia_time.bpm;

if (new_bpm > 0.0 && (pData->time.bpm != new_bpm || ++pData->time.hylia_enabled > 50))
if (new_bpm > 0.0 && pData->time.bpm != new_bpm)
{
pData->time.bpm = new_bpm;
pData->time.hylia_enabled = 1;
pData->time.needsReset = true;

if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
pData->time.fillEngineTimeInfo(pData->timeInfo, 0);
@@ -472,9 +525,9 @@ PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
{
pData->doNextPluginAction(true);

if (pData->time.playing && pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
if (pData->timeInfo.playing && pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
{
pData->time.frame += bufferSize;
pData->timeInfo.frame += bufferSize;
pData->time.fillEngineTimeInfo(pData->timeInfo, bufferSize);
}
}


+ 6
- 4
source/backend/engine/CarlaEngineInternal.hpp 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
@@ -27,6 +27,8 @@
// FIXME only use CARLA_PREVENT_HEAP_ALLOCATION for structs
// maybe separate macro

typedef struct _jack_position jack_position_t;

CARLA_BACKEND_START_NAMESPACE

// -----------------------------------------------------------------------
@@ -112,15 +114,14 @@ private:
// InternalTime

struct EngineInternalTime {
bool playing;
uint64_t frame;
double bpm;
double sampleRate;
double tick;
bool needsReset;

#ifndef BUILD_BRIDGE
bool hylia_enabled;
hylia_t* hylia;
int hylia_enabled;
hylia_time_info_t hylia_time;
#endif

@@ -128,6 +129,7 @@ struct EngineInternalTime {
~EngineInternalTime() noexcept;

void fillEngineTimeInfo(EngineTimeInfo& info, const uint32_t newFrames) noexcept;
void fillJackTimeInfo(jack_position_t* const pos, const uint32_t newFrames) noexcept;

CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalTime)
};


+ 39
- 25
source/backend/engine/CarlaEngineJack.cpp View File

@@ -811,8 +811,6 @@ public:
CarlaThread("CarlaEngineJackCallbacks"),
#endif
fClient(nullptr),
fTransportPos(),
fTransportState(JackTransportStopped),
fExternalPatchbay(true),
fFreewheel(false),
#ifdef BUILD_BRIDGE
@@ -837,8 +835,6 @@ public:

// FIXME: Always enable JACK transport for now
pData->options.transportMode = ENGINE_TRANSPORT_MODE_JACK;

carla_zeroStruct(fTransportPos);
}

~CarlaEngineJack() noexcept override
@@ -895,11 +891,8 @@ public:
carla_debug("CarlaEngineJack::init(\"%s\")", clientName);

fFreewheel = false;
fTransportState = JackTransportStopped;
fExternalPatchbay = true;

carla_zeroStruct(fTransportPos);

CarlaString truncatedClientName(clientName);
truncatedClientName.truncate(getMaxClientNameSize());

@@ -961,6 +954,7 @@ public:
jackbridge_set_freewheel_callback(fClient, carla_jack_freewheel_callback, this);
jackbridge_set_latency_callback(fClient, carla_jack_latency_callback, this);
jackbridge_set_process_callback(fClient, carla_jack_process_callback, this);
jackbridge_set_timebase_callback(fClient, true, carla_jack_timebase_callback, this);
jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback, this);

if (pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
@@ -1378,6 +1372,13 @@ public:

if (fClient != nullptr)
{
if ((pData->timeInfo.valid & EngineTimeInfo::kValidBBT) == 0x0)
{
// old timebase master no longer active, make ourselves master again
pData->time.needsReset = true;
jackbridge_set_timebase_callback(fClient, true, carla_jack_timebase_callback, this);
}

try {
jackbridge_transport_start(fClient);
} catch(...) {}
@@ -1511,28 +1512,30 @@ protected:
if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK)
return;

fTransportPos.unique_1 = fTransportPos.unique_2 + 1; // invalidate
jack_position_t jpos;

fTransportState = jackbridge_transport_query(fClient, &fTransportPos);
// invalidate
jpos.unique_1 = 1;
jpos.unique_2 = 2;

pData->timeInfo.playing = (fTransportState == JackTransportRolling);
pData->timeInfo.playing = (jackbridge_transport_query(fClient, &jpos) == JackTransportRolling);

if (fTransportPos.unique_1 == fTransportPos.unique_2)
if (jpos.unique_1 == jpos.unique_2)
{
pData->timeInfo.frame = fTransportPos.frame;
pData->timeInfo.usecs = fTransportPos.usecs;
pData->timeInfo.frame = jpos.frame;
pData->timeInfo.usecs = jpos.usecs;

if (fTransportPos.valid & JackPositionBBT)
if (jpos.valid & JackPositionBBT)
{
pData->timeInfo.valid = EngineTimeInfo::kValidBBT;
pData->timeInfo.bbt.bar = fTransportPos.bar;
pData->timeInfo.bbt.beat = fTransportPos.beat;
pData->timeInfo.bbt.tick = fTransportPos.tick;
pData->timeInfo.bbt.barStartTick = fTransportPos.bar_start_tick;
pData->timeInfo.bbt.beatsPerBar = fTransportPos.beats_per_bar;
pData->timeInfo.bbt.beatType = fTransportPos.beat_type;
pData->timeInfo.bbt.ticksPerBeat = fTransportPos.ticks_per_beat;
pData->timeInfo.bbt.beatsPerMinute = fTransportPos.beats_per_minute;
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
{
@@ -1722,6 +1725,14 @@ protected:
}

#ifndef BUILD_BRIDGE
void handleJackTimebaseCallback(jack_nframes_t nframes, jack_position_t* const pos, const int new_pos)
{
if (new_pos)
nframes = 0;

pData->time.fillJackTimeInfo(pos, nframes);
}

void handleJackClientRegistrationCallback(const char* const name, const bool reg)
{
CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',);
@@ -1955,9 +1966,7 @@ protected:
// -------------------------------------------------------------------

private:
jack_client_t* fClient;
jack_position_t fTransportPos;
uint32_t fTransportState;
jack_client_t* fClient;
bool fExternalPatchbay;
bool fFreewheel;

@@ -2421,6 +2430,11 @@ private:
}

#ifndef BUILD_BRIDGE
static void JACKBRIDGE_API carla_jack_timebase_callback(jack_transport_state_t, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg) __attribute__((annotate("realtime")))
{
handlePtr->handleJackTimebaseCallback(nframes, pos, new_pos);
}

static void JACKBRIDGE_API carla_jack_client_registration_callback(const char* name, int reg, void* arg)
{
PostPonedJackEvent ev;


+ 1
- 1
source/backend/engine/CarlaEngineNative.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


Loading…
Cancel
Save