Browse Source

Rework some of libjack to better support multiple clients

tags/1.9.8
falkTX 7 years ago
parent
commit
81e2c528cc
9 changed files with 485 additions and 540 deletions
  1. +289
    -180
      source/libjack/libjack.cpp
  2. +72
    -72
      source/libjack/libjack.hpp
  3. +1
    -5
      source/libjack/libjack_base.cpp
  4. +43
    -77
      source/libjack/libjack_callbacks.cpp
  5. +13
    -88
      source/libjack/libjack_client.cpp
  6. +27
    -59
      source/libjack/libjack_ports.cpp
  7. +8
    -23
      source/libjack/libjack_server-control.cpp
  8. +2
    -7
      source/libjack/libjack_time.cpp
  9. +30
    -29
      source/libjack/libjack_transport.cpp

+ 289
- 180
source/libjack/libjack.cpp View File

@@ -28,71 +28,119 @@ CARLA_BACKEND_START_NAMESPACE

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

CarlaJackClient::CarlaJackClient()
: Thread("CarlaJackClient"),
fState(),
fIsValid(false),
fIsOffline(false),
fFirstIdle(true),
fLastPingTime(-1),
fAudioIns(0),
fAudioOuts(0)
class CarlaJackAppClient : public juce::Thread
{
carla_debug("CarlaJackClient::CarlaJackClient(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
public:
JackServerState fServer;
LinkedList<JackClientState*> fClients;

CarlaJackAppClient()
: Thread("CarlaJackAppClient"),
fServer(),
fIsValid(false),
fIsOffline(false),
fLastPingTime(-1),
fAudioIns(0),
fAudioOuts(0)
{
carla_debug("CarlaJackAppClient::CarlaJackAppClient()");

const char* const shmIds(std::getenv("CARLA_SHM_IDS"));
CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && std::strlen(shmIds) == 6*4,);
const char* const shmIds(std::getenv("CARLA_SHM_IDS"));
CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && std::strlen(shmIds) == 6*4,);

std::memcpy(fBaseNameAudioPool, shmIds+6*0, 6);
std::memcpy(fBaseNameRtClientControl, shmIds+6*1, 6);
std::memcpy(fBaseNameNonRtClientControl, shmIds+6*2, 6);
std::memcpy(fBaseNameNonRtServerControl, shmIds+6*3, 6);
std::memcpy(fBaseNameAudioPool, shmIds+6*0, 6);
std::memcpy(fBaseNameRtClientControl, shmIds+6*1, 6);
std::memcpy(fBaseNameNonRtClientControl, shmIds+6*2, 6);
std::memcpy(fBaseNameNonRtServerControl, shmIds+6*3, 6);

fBaseNameAudioPool[6] = '\0';
fBaseNameRtClientControl[6] = '\0';
fBaseNameNonRtClientControl[6] = '\0';
fBaseNameNonRtServerControl[6] = '\0';
fBaseNameAudioPool[6] = '\0';
fBaseNameRtClientControl[6] = '\0';
fBaseNameNonRtClientControl[6] = '\0';
fBaseNameNonRtServerControl[6] = '\0';

startThread(10);
}
startThread(10);
}

CarlaJackClient::~CarlaJackClient() noexcept
{
carla_debug("CarlaJackClient::~CarlaJackClient()");
~CarlaJackAppClient() noexcept override
{
carla_debug("CarlaJackAppClient::~CarlaJackAppClient()");

carla_debug("CarlaEnginePlugin::close()");
fLastPingTime = -1;

stopThread(5000);
clear();

const CarlaMutexLocker cms(fRealtimeThreadMutex);

for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
{
JackClientState* const jclient(it.getValue(nullptr));
CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);

delete jclient;
}

fClients.clear();
}

carla_debug("CarlaEnginePlugin::close()");
fLastPingTime = -1;
void clear() noexcept;
bool isValid() const noexcept;

stopThread(5000);
clear();
void activate();
void handleNonRtData();

for (LinkedList<JackPortState*>::Itenerator it = fState.audioIns.begin2(); it.valid(); it.next())
JackClientState* addClient(const char* const name)
{
if (JackPortState* const jport = it.getValue(nullptr))
delete jport;
JackClientState* const jclient(new JackClientState(fServer, name));

const CarlaMutexLocker cms(fRealtimeThreadMutex);
fClients.append(jclient);
return jclient;
}

for (LinkedList<JackPortState*>::Itenerator it = fState.audioOuts.begin2(); it.valid(); it.next())
bool removeClient(JackClientState* const jclient)
{
if (JackPortState* const jport = it.getValue(nullptr))
delete jport;
{
const CarlaMutexLocker cms(fRealtimeThreadMutex);
CARLA_SAFE_ASSERT_RETURN(fClients.removeOne(jclient), false);
}

delete jclient;
return true;
}

fState.audioIns.clear();
fState.audioOuts.clear();
}
// -------------------------------------------------------------------

bool CarlaJackClient::initIfNeeded(const char* const clientName)
{
carla_debug("CarlaJackClient::initIfNeeded(\"%s\")", clientName);
protected:
void run() override;

if (fState.name == nullptr)
fState.name = strdup(clientName);
private:
BridgeAudioPool fShmAudioPool;
BridgeRtClientControl fShmRtClientControl;
BridgeNonRtClientControl fShmNonRtClientControl;
BridgeNonRtServerControl fShmNonRtServerControl;

return fIsValid;
}
char fBaseNameAudioPool[6+1];
char fBaseNameRtClientControl[6+1];
char fBaseNameNonRtClientControl[6+1];
char fBaseNameNonRtServerControl[6+1];

bool fIsValid;
bool fIsOffline;
int64_t fLastPingTime;

uint32_t fAudioIns;
uint32_t fAudioOuts;

CarlaMutex fRealtimeThreadMutex;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaJackAppClient)
};

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

void CarlaJackClient::clear() noexcept
void CarlaJackAppClient::clear() noexcept
{
fShmAudioPool.clear();
fShmRtClientControl.clear();
@@ -100,36 +148,19 @@ void CarlaJackClient::clear() noexcept
fShmNonRtServerControl.clear();
}

bool CarlaJackClient::isValid() const noexcept
bool CarlaJackAppClient::isValid() const noexcept
{
return fIsValid;
}

void CarlaJackClient::activate()
void CarlaJackAppClient::activate()
{
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
const bool wasFirstIdle(fFirstIdle);

if (wasFirstIdle)
{
fFirstIdle = false;
fLastPingTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPingTime > 0);

if (fState.audioIns.count() == 0 && fState.audioOuts.count() == 0)
{
carla_stderr("Create 2 ins, 2 outs prematurely for the client");
fState.audioIns.append(new JackPortState(fState.name, "in_1", 0, JackPortIsOutput, false));
fState.audioIns.append(new JackPortState(fState.name, "in_2", 1, JackPortIsOutput, false));
fState.fakeIns = 2;

fState.audioOuts.append(new JackPortState(fState.name, "out_1", 0, JackPortIsInput, false));
fState.audioOuts.append(new JackPortState(fState.name, "out_2", 1, JackPortIsInput, false));
fState.fakeOuts = 2;

fState.prematurelyActivated = true;
}

char bufStr[STR_MAX+1];
uint32_t bufStrSize;

@@ -151,7 +182,7 @@ void CarlaJackClient::activate()
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo2);

carla_zeroChars(bufStr, STR_MAX);
std::strncpy(bufStr, fState.name, 64);
std::strncpy(bufStr, "Jack App", 64);
bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
@@ -173,8 +204,8 @@ void CarlaJackClient::activate()

// kPluginBridgeNonRtServerAudioCount
{
const uint32_t aIns = fState.audioIns.count();
const uint32_t aOuts = fState.audioOuts.count();
const uint32_t aIns = 2; //fClient.audioIns.count();
const uint32_t aOuts = 2; //fClient.audioOuts.count();

// uint/ins, uint/outs
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerAudioCount);
@@ -182,42 +213,47 @@ void CarlaJackClient::activate()
fShmNonRtServerControl.writeUInt(aOuts);
fShmNonRtServerControl.commitWrite();


// kPluginBridgeNonRtServerPortName
for (uint32_t i=0; i<aIns; ++i)
{
const JackPortState* const jport(fState.audioIns.getAt(i, nullptr));
CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);
//const JackPortState* const jport(fClient.audioIns.getAt(i, nullptr));
//CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);

const char* const portName(jport->name);
CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');
//const char* const portName(jport->name);
//CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');

std::snprintf(bufStr, 64, "in_%i", i+1);

// byte/type, uint/index, uint/size, str[] (name)
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
fShmNonRtServerControl.writeByte(kPluginBridgePortAudioInput);
fShmNonRtServerControl.writeUInt(i);

bufStrSize = static_cast<uint32_t>(std::strlen(portName));
bufStrSize = static_cast<uint32_t>(std::strlen(bufStr));
fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(portName, bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
}

// kPluginBridgeNonRtServerPortName
for (uint32_t i=0; i<aOuts; ++i)
{
const JackPortState* const jport(fState.audioOuts.getAt(i, nullptr));
CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);
//const JackPortState* const jport(fClient.audioOuts.getAt(i, nullptr));
//CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);

//const char* const portName(jport->name);
//CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');

const char* const portName(jport->name);
CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');
std::snprintf(bufStr, 64, "out_%i", i+1);

// byte/type, uint/index, uint/size, str[] (name)
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
fShmNonRtServerControl.writeByte(kPluginBridgePortAudioOutput);
fShmNonRtServerControl.writeUInt(i);

bufStrSize = static_cast<uint32_t>(std::strlen(portName));
bufStrSize = static_cast<uint32_t>(std::strlen(bufStr));
fShmNonRtServerControl.writeUInt(bufStrSize);
fShmNonRtServerControl.writeCustomData(portName, bufStrSize);
fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
}
}

@@ -225,8 +261,8 @@ void CarlaJackClient::activate()

// kPluginBridgeNonRtServerMidiCount
{
const uint32_t mIns = fState.midiIns.count();
const uint32_t mOuts = fState.midiOuts.count();
const uint32_t mIns = 0; // fClient.midiIns.count();
const uint32_t mOuts = 0; // fClient.midiOuts.count();

// uint/ins, uint/outs
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiCount);
@@ -243,43 +279,15 @@ void CarlaJackClient::activate()
fShmNonRtServerControl.waitIfDataIsReachingLimit();

// must be static
fAudioIns = fState.audioIns.count();
fAudioOuts = fState.audioOuts.count();
fAudioIns = 2; //fClient.audioIns.count();
fAudioOuts = 2; //fClient.audioOuts.count();

carla_stdout("Carla Jack Client Ready!");
fLastPingTime = Time::currentTimeMillis();
}

fState.activated = true;
}

void CarlaJackClient::deactivate()
{
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);

fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
fShmNonRtServerControl.commitWrite();

fState.activated = false;
fState.prematurelyActivated = false;

for (LinkedList<JackPortState*>::Itenerator it = fState.audioIns.begin2(); it.valid(); it.next())
{
if (JackPortState* const jport = it.getValue(nullptr))
delete jport;
}

for (LinkedList<JackPortState*>::Itenerator it = fState.audioOuts.begin2(); it.valid(); it.next())
{
if (JackPortState* const jport = it.getValue(nullptr))
delete jport;
}

fState.audioIns.clear();
fState.audioOuts.clear();
}

void CarlaJackClient::handleNonRtData()
void CarlaJackAppClient::handleNonRtData()
{
for (; fShmNonRtClientControl.isDataAvailableForReading();)
{
@@ -295,7 +303,7 @@ void CarlaJackClient::handleNonRtData()
continue;
++shownNull;
}
carla_stdout("CarlaJackClient::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode));
carla_stdout("CarlaJackAppClient::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode));
}
// #endif

@@ -387,9 +395,9 @@ void CarlaJackClient::handleNonRtData()
}
}

void CarlaJackClient::run()
void CarlaJackAppClient::run()
{
carla_stderr("CarlaJackClient run START");
carla_stderr("CarlaJackAppClient run START");

if (! fShmAudioPool.attachClient(fBaseNameAudioPool))
{
@@ -455,21 +463,21 @@ void CarlaJackClient::run()

if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData))
{
carla_stderr2("CarlaJackClient: data size mismatch");
carla_stderr2("CarlaJackAppClient: data size mismatch");
return;
}

opcode = fShmNonRtClientControl.readOpcode();
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetBufferSize, opcode);
fState.bufferSize = fShmNonRtClientControl.readUInt();
fServer.bufferSize = fShmNonRtClientControl.readUInt();

opcode = fShmNonRtClientControl.readOpcode();
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode);
fState.sampleRate = fShmNonRtClientControl.readDouble();
fServer.sampleRate = fShmNonRtClientControl.readDouble();

if (fState.bufferSize == 0 || carla_isZero(fState.sampleRate))
if (fServer.bufferSize == 0 || carla_isZero(fServer.sampleRate))
{
carla_stderr2("CarlaJackClient: invalid empty state");
carla_stderr2("CarlaJackAppClient: invalid empty state");
return;
}

@@ -483,6 +491,8 @@ void CarlaJackClient::run()

fIsValid = true;

activate();

#ifdef __SSE2_MATH__
// Set FTZ and DAZ flags
_mm_setcsr(_mm_getcsr() | 0x8040);
@@ -505,7 +515,7 @@ void CarlaJackClient::run()
//#ifdef DEBUG
if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent)
{
carla_stdout("CarlaJackClientRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
carla_stdout("CarlaJackAppClientRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
}
//#endif

@@ -541,73 +551,102 @@ void CarlaJackClient::run()

if (cmtl.wasLocked())
{
float* fdata = fShmAudioPool.data;
// tranport for all clients
const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);

if (fState.process == nullptr || ! fState.activated)
fServer.playing = bridgeTimeInfo.playing;
fServer.position.frame = bridgeTimeInfo.frame;
fServer.position.usecs = bridgeTimeInfo.usecs;

if (bridgeTimeInfo.valid & 0x1 /* kValidBBT */)
{
for (uint32_t i=0; i<fAudioIns; ++i)
fdata += fState.bufferSize*fAudioIns;
fServer.position.valid = JackPositionBBT;

if (fAudioOuts > 0)
carla_zeroFloats(fdata, fState.bufferSize*fAudioOuts);
fServer.position.bar = bridgeTimeInfo.bar;
fServer.position.beat = bridgeTimeInfo.beat;
fServer.position.tick = bridgeTimeInfo.tick;

if (! fState.activated)
{
fShmRtClientControl.data->procFlags = 1;
}
fServer.position.beats_per_bar = bridgeTimeInfo.beatsPerBar;
fServer.position.beat_type = bridgeTimeInfo.beatType;

fServer.position.ticks_per_beat = bridgeTimeInfo.ticksPerBeat;
fServer.position.beats_per_minute = bridgeTimeInfo.beatsPerMinute;
fServer.position.bar_start_tick = bridgeTimeInfo.barStartTick;
}
else
{
const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
fServer.position.valid = static_cast<jack_position_bits_t>(0);
}

uint32_t i = 0;
for (LinkedList<JackPortState*>::Itenerator it = fState.audioIns.begin2(); it.valid(); it.next())
{
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioIns);
if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fState.bufferSize;
}
float* fdata = fShmAudioPool.data;

i=0;
for (LinkedList<JackPortState*>::Itenerator it = fState.audioOuts.begin2(); it.valid(); it.next())
{
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioOuts);
if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fState.bufferSize;
}
if (JackClientState* const jclient = fClients.getFirst(nullptr))
//for (LinkedList<JackClientState*>::Itenerator it = fClients.begin2(); it.valid(); it.next())
{
//JackClientState* const jclient(it.getValue(nullptr));
//CARLA_SAFE_ASSERT_CONTINUE(jclient != nullptr);

fState.playing = bridgeTimeInfo.playing;
fState.position.frame = bridgeTimeInfo.frame;
fState.position.usecs = bridgeTimeInfo.usecs;
const CarlaMutexTryLocker cmtl2(jclient->mutex);

if (bridgeTimeInfo.valid & 0x1 /* kValidBBT */)
if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
{
fState.position.valid = JackPositionBBT;
if (fAudioIns > 0)
fdata += fServer.bufferSize*fAudioIns;

fState.position.bar = bridgeTimeInfo.bar;
fState.position.beat = bridgeTimeInfo.beat;
fState.position.tick = bridgeTimeInfo.tick;
if (fAudioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fAudioOuts);

fState.position.beats_per_bar = bridgeTimeInfo.beatsPerBar;
fState.position.beat_type = bridgeTimeInfo.beatType;

fState.position.ticks_per_beat = bridgeTimeInfo.ticksPerBeat;
fState.position.beats_per_minute = bridgeTimeInfo.beatsPerMinute;
fState.position.bar_start_tick = bridgeTimeInfo.barStartTick;
if (jclient->deactivated)
{
fShmRtClientControl.data->procFlags = 1;
}
}
else
{
fState.position.valid = static_cast<jack_position_bits_t>(0);
uint32_t i;

i = 0;
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioIns.begin2(); it.valid(); it.next())
{
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioIns);
if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fServer.bufferSize;
}
for (; i++ < fAudioIns;)
fdata += fServer.bufferSize;

i = 0;
for (LinkedList<JackPortState*>::Itenerator it = jclient->audioOuts.begin2(); it.valid(); it.next())
{
CARLA_SAFE_ASSERT_BREAK(i++ < fAudioOuts);
if (JackPortState* const jport = it.getValue(nullptr))
jport->buffer = fdata;
fdata += fServer.bufferSize;
}
for (; i++ < fAudioOuts;)
{
//carla_stderr("clearing buffer %i", i);

carla_zeroFloats(fdata, fServer.bufferSize);
fdata += fServer.bufferSize;
}

jclient->processCb(fServer.bufferSize, jclient->processCbPtr);
}
}
else
{
if (fAudioIns > 0)
fdata += fServer.bufferSize*fAudioIns;

fState.process(fState.bufferSize, fState.processPtr);
if (fAudioOuts > 0)
carla_zeroFloats(fdata, fServer.bufferSize*fAudioOuts);
}
}
else
{
carla_stderr2("CarlaJackClient: fRealtimeThreadMutex tryLock failed");
carla_stderr2("CarlaJackAppClient: fRealtimeThreadMutex tryLock failed");
}

carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);
@@ -626,7 +665,7 @@ void CarlaJackClient::run()

if (quitReceived)
{
carla_stderr("CarlaJackClient run END - quit by carla");
carla_stderr("CarlaJackAppClient run END - quit by carla");

::kill(::getpid(), SIGTERM);
}
@@ -638,29 +677,99 @@ void CarlaJackClient::run()
bool activated;

{
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
activated = fState.activated;
const CarlaMutexLocker cms(fRealtimeThreadMutex);

if (activated)
if (JackClientState* const jclient = fClients.getLast(nullptr))
{
carla_stderr("CarlaJackClient run END - quit error");

fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
fShmNonRtServerControl.writeUInt(messageSize);
fShmNonRtServerControl.writeCustomData(message, messageSize);
fShmNonRtServerControl.commitWrite();
const CarlaMutexLocker cms(jclient->mutex);
activated = jclient->activated;
}
else
{
carla_stderr("CarlaJackClient run END - quit itself");
activated = true;
}
}

if (activated && fState.shutdown != nullptr)
fState.shutdown(fState.shutdownPtr);
if (activated)
{
carla_stderr("CarlaJackAppClient run END - quit error");

const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
fShmNonRtServerControl.writeUInt(messageSize);
fShmNonRtServerControl.writeCustomData(message, messageSize);
fShmNonRtServerControl.commitWrite();
}
else
{
carla_stderr("CarlaJackAppClient run END - quit itself");

const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
fShmNonRtServerControl.commitWrite();
}

/*
if (activated)
{
// TODO infoShutdown
if (fClient.shutdownCb != nullptr)
fClient.shutdownCb(fClient.shutdownCbPtr);
}
*/
}
}

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

static CarlaJackAppClient gClient;

CARLA_EXPORT
jack_client_t* jack_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...)
{
if (status != nullptr)
*status = JackNameNotUnique;

if (options & JackUseExactName)
return nullptr;

if (JackClientState* const client = gClient.addClient(client_name))
return (jack_client_t*)client;

if (status != nullptr)
*status = JackServerError;

return nullptr;
}

CARLA_EXPORT
jack_client_t* jack_client_new(const char* client_name)
{
return jack_client_open(client_name, JackNullOption, nullptr);
}

CARLA_EXPORT
int jack_client_close(jack_client_t* client)
{
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

gClient.removeClient(jclient);
return 0;
}

CARLA_EXPORT
pthread_t jack_client_thread_id(jack_client_t* client)
{
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

CarlaJackAppClient* const jackAppPtr = jclient->server.jackAppPtr;
CARLA_SAFE_ASSERT_RETURN(jackAppPtr != nullptr, 0);

return (pthread_t)jackAppPtr->getThreadId();
}

CARLA_BACKEND_END_NAMESPACE

// --------------------------------------------------------------------------------------------------------------------
@@ -676,7 +785,7 @@ CARLA_BACKEND_USE_NAMESPACE
CARLA_EXPORT
int jack_client_real_time_priority(jack_client_t*)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);
carla_stdout("CarlaJackAppClient :: %s", __FUNCTION__);

return -1;
}


+ 72
- 72
source/libjack/libjack.hpp View File

@@ -55,6 +55,10 @@ CARLA_BACKEND_START_NAMESPACE

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

class CarlaJackAppClient;
struct JackClientState;
struct JackServerState;

struct JackPortState {
char* name;
char* fullname;
@@ -94,104 +98,100 @@ struct JackPortState {
};

struct JackClientState {
const JackServerState& server;
CarlaMutex mutex;

bool activated;
bool prematurelyActivated;
bool deactivated; // activated once, then deactivated

char* name;

uint32_t bufferSize;
double sampleRate;

bool playing;
jack_position_t position;

LinkedList<JackPortState*> audioIns;
LinkedList<JackPortState*> audioOuts;
uint32_t fakeIns, fakeOuts;

LinkedList<JackPortState> midiIns;
LinkedList<JackPortState> midiOuts;

JackProcessCallback process;
void* processPtr;
JackShutdownCallback shutdownCb;
void* shutdownCbPtr;

JackShutdownCallback shutdown;
void* shutdownPtr;
JackInfoShutdownCallback infoShutdownCb;
void* infoShutdownCbPtr;

JackClientState()
: activated(false),
prematurelyActivated(false),
name(nullptr),
bufferSize(0),
sampleRate(0.0),
playing(false),
JackProcessCallback processCb;
void* processCbPtr;

JackBufferSizeCallback bufferSizeCb;
void* bufferSizeCbPtr;

JackSampleRateCallback sampleRateCb;
void* sampleRateCbPtr;

JackSyncCallback syncCb;
void* syncCbPtr;

JackClientState(const JackServerState& s, const char* const n)
: server(s),
activated(false),
deactivated(false),
name(strdup(n)),
audioIns(),
audioOuts(),
fakeIns(0),
fakeOuts(0),
midiIns(),
midiOuts(),
process(nullptr),
processPtr(nullptr),
shutdown(nullptr),
shutdownPtr(nullptr)
{
carla_zeroStruct(position);
}
shutdownCb(nullptr),
shutdownCbPtr(nullptr),
infoShutdownCb(nullptr),
infoShutdownCbPtr(nullptr),
processCb(nullptr),
processCbPtr(nullptr),
bufferSizeCb(nullptr),
bufferSizeCbPtr(nullptr),
sampleRateCb(nullptr),
sampleRateCbPtr(nullptr),
syncCb(nullptr),
syncCbPtr(nullptr) {}

~JackClientState()
{
free(name);
}
};

// TODO JackServerState, with only bufsize, srate and tranport
// TODO add JackServerState ptr to JackClientState
// TODO each client gets its own JackClientState struct

class CarlaJackClient : public juce::Thread
{
public:
JackClientState fState;

CarlaJackClient();
~CarlaJackClient() noexcept override;
const CarlaMutexLocker cms(mutex);

bool initIfNeeded(const char* const clientName);
void clear() noexcept;
bool isValid() const noexcept;
for (LinkedList<JackPortState*>::Itenerator it = audioIns.begin2(); it.valid(); it.next())
{
if (JackPortState* const jport = it.getValue(nullptr))
delete jport;
}

void activate();
void deactivate();
void handleNonRtData();
for (LinkedList<JackPortState*>::Itenerator it = audioOuts.begin2(); it.valid(); it.next())
{
if (JackPortState* const jport = it.getValue(nullptr))
delete jport;
}

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

protected:
void run() override;

private:
BridgeAudioPool fShmAudioPool;
BridgeRtClientControl fShmRtClientControl;
BridgeNonRtClientControl fShmNonRtClientControl;
BridgeNonRtServerControl fShmNonRtServerControl;
free(name);
name = nullptr;

char fBaseNameAudioPool[6+1];
char fBaseNameRtClientControl[6+1];
char fBaseNameNonRtClientControl[6+1];
char fBaseNameNonRtServerControl[6+1];
audioIns.clear();
audioOuts.clear();
}
};

bool fIsValid;
bool fIsOffline;
bool fFirstIdle;
int64_t fLastPingTime;
struct JackServerState {
CarlaJackAppClient* jackAppPtr;

uint32_t fAudioIns;
uint32_t fAudioOuts;
uint32_t bufferSize;
double sampleRate;

CarlaMutex fRealtimeThreadMutex;
bool playing;
jack_position_t position;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaJackClient)
JackServerState()
: jackAppPtr(nullptr),
bufferSize(0),
sampleRate(0.0),
playing(false)
{
carla_zeroStruct(position);
}
};

CARLA_BACKEND_END_NAMESPACE


+ 1
- 5
source/libjack/libjack_base.cpp View File

@@ -42,9 +42,7 @@ const char* jack_get_version_string(void)
CARLA_EXPORT
int jack_is_realtime(jack_client_t*)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

return 0;
return 1;
}

// --------------------------------------------------------------------------------------------------------------------
@@ -52,8 +50,6 @@ int jack_is_realtime(jack_client_t*)
CARLA_EXPORT
void jack_free(void* ptr)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

free(ptr);
}



+ 43
- 77
source/libjack/libjack_callbacks.cpp View File

@@ -31,133 +31,99 @@ int jack_set_thread_init_callback(jack_client_t*, JackThreadInitCallback, void*)
CARLA_EXPORT
void jack_on_shutdown(jack_client_t* client, JackShutdownCallback callback, void* arg)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr,);

JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated,);
const CarlaMutexLocker cms(jclient->mutex);

jstate.shutdown = callback;
jstate.shutdownPtr = arg;
jclient->shutdownCb = callback;
jclient->shutdownCbPtr = arg;
}

// void jack_on_info_shutdown (jack_client_t *client,
// JackInfoShutdownCallback shutdown_callback, void *arg) JACK_WEAK_EXPORT;

CARLA_EXPORT
int jack_set_process_callback(jack_client_t* client, JackProcessCallback callback, void* arg)
void jack_on_info_shutdown(jack_client_t* client, JackInfoShutdownCallback callback, void* arg)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr,);

jstate.process = callback;
jstate.processPtr = arg;
const CarlaMutexLocker cms(jclient->mutex);

return 0;
jclient->infoShutdownCb = callback;
jclient->infoShutdownCbPtr = arg;
}

// int jack_set_freewheel_callback (jack_client_t *client,
// JackFreewheelCallback freewheel_callback,
// void *arg) JACK_OPTIONAL_WEAK_EXPORT;

CARLA_EXPORT
int jack_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCallback /*callback*/, void* /*arg*/)
int jack_set_process_callback(jack_client_t* client, JackProcessCallback callback, void* arg)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);

// TODO
const CarlaMutexLocker cms(jclient->mutex);

jclient->processCb = callback;
jclient->processCbPtr = arg;
return 0;
}

CARLA_EXPORT
int jack_set_sample_rate_callback(jack_client_t* client, JackSampleRateCallback /*callback*/, void* /*arg*/)
int jack_set_freewheel_callback(jack_client_t*, JackFreewheelCallback, void*)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);

// TODO

return 0;
}

CARLA_EXPORT
int jack_set_client_registration_callback(jack_client_t* client, JackClientRegistrationCallback, void*)
int jack_set_buffer_size_callback(jack_client_t* client, JackBufferSizeCallback callback, void* arg)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

const CarlaMutexLocker cms(jclient->mutex);

jclient->bufferSizeCb = callback;
jclient->bufferSizeCbPtr = arg;
return 0;
}

CARLA_EXPORT
int jack_set_port_registration_callback(jack_client_t* client, JackPortRegistrationCallback, void*)
int jack_set_sample_rate_callback(jack_client_t* client, JackSampleRateCallback callback, void* arg)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);
const CarlaMutexLocker cms(jclient->mutex);

jclient->sampleRateCb = callback;
jclient->sampleRateCbPtr = arg;
return 0;
}

CARLA_EXPORT
int jack_set_port_connect_callback(jack_client_t* client, JackPortConnectCallback, void*)
int jack_set_client_registration_callback(jack_client_t*, JackClientRegistrationCallback, void*)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);

return 0;
}

// int jack_set_port_rename_callback (jack_client_t *client,
// JackPortRenameCallback
// rename_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT;

CARLA_EXPORT
int jack_set_graph_order_callback(jack_client_t* client, JackGraphOrderCallback, void*)
int jack_set_port_registration_callback(jack_client_t*, JackPortRegistrationCallback, void*)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);
return 0;
}

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);
CARLA_EXPORT
int jack_set_port_connect_callback(jack_client_t*, JackPortConnectCallback, void*)
{
return 0;
}

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);
CARLA_EXPORT
int jack_set_port_rename_callback(jack_client_t*, JackPortRenameCallback, void*)
{
return 0;
}

CARLA_EXPORT
int jack_set_graph_order_callback(jack_client_t*, JackGraphOrderCallback, void*)
{
return 0;
}



+ 13
- 88
source/libjack/libjack_client.cpp View File

@@ -19,50 +19,6 @@

CARLA_BACKEND_USE_NAMESPACE

static CarlaJackClient gClient;
static int gClientRefCount = 0;

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

CARLA_EXPORT
jack_client_t* jack_client_open(const char* client_name, jack_options_t /*options*/, jack_status_t* status, ...)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

if (! gClient.initIfNeeded(client_name))
{
if (status != nullptr)
*status = JackServerError;
return nullptr;
}

++gClientRefCount;
return (jack_client_t*)&gClient;
}

CARLA_EXPORT
jack_client_t* jack_client_new(const char* client_name)
{
return jack_client_open(client_name, JackNullOption, nullptr);
}

CARLA_EXPORT
int jack_client_close(jack_client_t* client)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

JackClientState& jstate(jclient->fState);

if (jstate.activated)
jclient->deactivate();

--gClientRefCount;
return 0;
}

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

CARLA_EXPORT
@@ -74,14 +30,10 @@ int jack_client_name_size(void)
CARLA_EXPORT
char* jack_get_client_name(jack_client_t* client)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr);

const JackClientState& jstate(jclient->fState);

return jstate.name;
return jclient->name;
}

CARLA_EXPORT
@@ -91,7 +43,7 @@ char* jack_get_uuid_for_client_name(jack_client_t*, const char*)
}

CARLA_EXPORT
char* jack_get_client_name_by_uuid (jack_client_t*, const char*)
char* jack_get_client_name_by_uuid(jack_client_t*, const char*)
{
return nullptr;
}
@@ -114,39 +66,26 @@ void jack_internal_client_close(const char*)
CARLA_EXPORT
int jack_activate(jack_client_t* client)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);

#if 0
// needed for pulseaudio
static bool skipFirstActivate = true;
if (skipFirstActivate) {
skipFirstActivate = false;
return 0;
}
#endif
const CarlaMutexLocker cms(jclient->mutex);

jclient->activate();
jclient->activated = true;
jclient->deactivated = false;
return 0;
}

CARLA_EXPORT
int jack_deactivate(jack_client_t* /*client*/)
int jack_deactivate(jack_client_t* client)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

//CarlaJackClient* const jclient = (CarlaJackClient*)client;
//CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

//JackClientState& jstate(jclient->fState);
//CARLA_SAFE_ASSERT_RETURN(jstate.activated, 1);
const CarlaMutexLocker cms(jclient->mutex);

//jclient->deactivate();
jclient->activated = false;
jclient->deactivated = true;
return 0;
}

@@ -158,18 +97,4 @@ int jack_get_client_pid(const char*)
return 0;
}

CARLA_EXPORT
pthread_t jack_client_thread_id(jack_client_t* client)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(jstate.activated, 0);

return (pthread_t)jclient->getThreadId();
}

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

+ 27
- 59
source/libjack/libjack_ports.cpp View File

@@ -27,49 +27,32 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co
{
carla_stdout("CarlaJackClient :: %s | %s %s %lu", __FUNCTION__, port_name, port_type, flags);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, nullptr);

JackClientState& jstate(jclient->fState);

CARLA_SAFE_ASSERT_RETURN(port_name != nullptr && port_name[0] != '\0', nullptr);
CARLA_SAFE_ASSERT_RETURN(port_type != nullptr && port_type[0] != '\0', nullptr);

if (std::strcmp(port_type, JACK_DEFAULT_AUDIO_TYPE) == 0)
{
uint32_t index;

/**/ if (flags & JackPortIsInput)
if (flags & JackPortIsInput)
{
if (jstate.prematurelyActivated)
{
CARLA_SAFE_ASSERT_RETURN(jstate.fakeIns > 0, nullptr);
jstate.fakeIns -= 1;
index = jstate.audioIns.count() - jstate.fakeIns - 1;
}
else
{
index = jstate.audioIns.count();
jstate.audioIns.append(new JackPortState(jstate.name, port_name, index, flags, false));
}

return (jack_port_t*)jstate.audioIns.getAt(index, nullptr);
JackPortState* const port = new JackPortState(jclient->name, port_name, jclient->audioIns.count(), flags, false);

const CarlaMutexLocker cms(jclient->mutex);

jclient->audioIns.append(port);
return (jack_port_t*)port;
}
else if (flags & JackPortIsOutput)

if (flags & JackPortIsOutput)
{
if (jstate.prematurelyActivated)
{
CARLA_SAFE_ASSERT_RETURN(jstate.fakeOuts > 0, nullptr);
jstate.fakeOuts -= 1;
index = jstate.audioOuts.count() - jstate.fakeOuts - 1;
}
else
{
index = jstate.audioOuts.count();
jstate.audioOuts.append(new JackPortState(jstate.name, port_name, index, flags, false));
}

return (jack_port_t*)jstate.audioOuts.getAt(index, nullptr);
JackPortState* const port = new JackPortState(jclient->name, port_name, jclient->audioOuts.count(), flags, false);

const CarlaMutexLocker cms(jclient->mutex);

jclient->audioOuts.append(port);
return (jack_port_t*)port;
}

carla_stderr2("Invalid port flags '%x'", flags);
@@ -83,44 +66,29 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co
CARLA_EXPORT
int jack_port_unregister(jack_client_t* client, jack_port_t* port)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

JackPortState* const jport = (JackPortState*)port;
CARLA_SAFE_ASSERT_RETURN(jport != nullptr, 1);
CARLA_SAFE_ASSERT_RETURN(! jport->isSystem, 1);

JackClientState& jstate(jclient->fState);
//CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);
const CarlaMutexLocker cms(jclient->mutex);

if (jport->flags & JackPortIsOutput)
if (jport->flags & JackPortIsInput)
{
if (jstate.prematurelyActivated)
{
CARLA_SAFE_ASSERT_RETURN(jstate.fakeIns < 2, 1);
jstate.fakeIns += 1;
}
else
{
CARLA_SAFE_ASSERT_RETURN(jstate.audioIns.removeOne(jport), 1);
}
CARLA_SAFE_ASSERT_RETURN(jclient->audioOuts.removeOne(jport), 1);
return 0;
}
else

if (jport->flags & JackPortIsOutput)
{
if (jstate.prematurelyActivated)
{
CARLA_SAFE_ASSERT_RETURN(jstate.fakeOuts < 2, 1);
jstate.fakeOuts += 1;
}
else
{
CARLA_SAFE_ASSERT_RETURN(jstate.audioOuts.removeOne(jport), 1);
}
CARLA_SAFE_ASSERT_RETURN(jclient->audioIns.removeOne(jport), 1);
return 0;
}

return 0;
carla_stderr2("Invalid port type on unregister");
return 1;
}

CARLA_EXPORT


+ 8
- 23
source/libjack/libjack_server-control.cpp View File

@@ -25,49 +25,34 @@ CARLA_BACKEND_USE_NAMESPACE
CARLA_EXPORT
int jack_set_freewheel(jack_client_t*, int)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

return 1;
}

CARLA_EXPORT
int jack_set_buffer_size(jack_client_t*, jack_nframes_t)
int jack_set_buffer_size(jack_client_t* client, jack_nframes_t bufferSize)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

return 1;
return (jclient->server.bufferSize == bufferSize) ? 0 : 1;
}

CARLA_EXPORT
jack_nframes_t jack_get_sample_rate(jack_client_t* client)
{
carla_debug("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

const JackClientState& jstate(jclient->fState);

return jstate.sampleRate;
return jclient->server.sampleRate;
}

CARLA_EXPORT
jack_nframes_t jack_get_buffer_size(jack_client_t* client)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

const JackClientState& jstate(jclient->fState);

return jstate.bufferSize;
}

CARLA_EXPORT
int jack_engine_takeover_timebase(jack_client_t*)
{
return ENOSYS;
return jclient->server.bufferSize;
}

CARLA_EXPORT


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

@@ -27,15 +27,10 @@ CARLA_BACKEND_USE_NAMESPACE
CARLA_EXPORT
jack_nframes_t jack_frame_time(const jack_client_t* client)
{
carla_debug("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(jstate.activated, 0);

return jstate.position.usecs;
return jclient->server.position.usecs;
}

// jack_nframes_t jack_last_frame_time (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;


+ 30
- 29
source/libjack/libjack_transport.cpp View File

@@ -22,21 +22,24 @@ CARLA_BACKEND_USE_NAMESPACE

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

CARLA_EXPORT
int jack_engine_takeover_timebase(jack_client_t*)
{
return ENOSYS;
}

// int jack_release_timebase (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;

CARLA_EXPORT
int jack_set_sync_callback(jack_client_t* client, JackSyncCallback /*callback*/, void* /*arg*/)
int jack_set_sync_callback(jack_client_t* client, JackSyncCallback callback, void* arg)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);

// TODO
const CarlaMutexLocker cms(jclient->mutex);

jclient->syncCb = callback;
jclient->syncCbPtr = arg;
return 0;
}

@@ -44,47 +47,45 @@ int jack_set_sync_callback(jack_client_t* client, JackSyncCallback /*callback*/,
// jack_time_t timeout) JACK_OPTIONAL_WEAK_EXPORT;

CARLA_EXPORT
int jack_set_timebase_callback(jack_client_t* client, int, JackTimebaseCallback, void*)
int jack_set_timebase_callback(jack_client_t*, int, JackTimebaseCallback, void*)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(! jstate.activated, 1);

// TODO

// FIXME?
return EBUSY;
}

CARLA_EXPORT
int jack_transport_locate(jack_client_t*, jack_nframes_t)
{
carla_stdout("CarlaJackClient :: %s", __FUNCTION__);

// FIXME?
return 1;
}

CARLA_EXPORT
jack_transport_state_t jack_transport_query(const jack_client_t* client, jack_position_t* pos)
{
carla_debug("CarlaJackClient :: %s", __FUNCTION__);
if (const JackClientState* const jclient = (JackClientState*)client)
{
const JackServerState& jserver(jclient->server);

CarlaJackClient* const jclient = (CarlaJackClient*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, JackTransportStopped);
if (pos != nullptr)
std::memcpy(pos, &jserver.position, sizeof(jack_position_t));

const JackClientState& jstate(jclient->fState);
CARLA_SAFE_ASSERT_RETURN(jstate.activated, JackTransportStopped);
return jserver.playing ? JackTransportRolling : JackTransportStopped;
}

if (pos != nullptr)
std::memcpy(pos, &jstate.position, sizeof(jack_position_t));
std::memset(pos, 0, sizeof(jack_position_t));

return jstate.playing ? JackTransportRolling : JackTransportStopped;
return JackTransportStopped;
}

// jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;
jack_nframes_t jack_get_current_transport_frame(const jack_client_t* client)
{
if (const JackClientState* const jclient = (JackClientState*)client)
return jclient->server.position.frame;

return 0;
}

CARLA_EXPORT
int jack_transport_reposition(jack_client_t*, const jack_position_t*)


Loading…
Cancel
Save