From 81e2c528ccc2d9dfc382a181c9bf856a68eaf0ff Mon Sep 17 00:00:00 2001 From: falkTX Date: Wed, 27 Sep 2017 23:19:51 +0200 Subject: [PATCH] Rework some of libjack to better support multiple clients --- source/libjack/libjack.cpp | 469 +++++++++++++--------- source/libjack/libjack.hpp | 144 +++---- source/libjack/libjack_base.cpp | 6 +- source/libjack/libjack_callbacks.cpp | 120 ++---- source/libjack/libjack_client.cpp | 101 +---- source/libjack/libjack_ports.cpp | 86 ++-- source/libjack/libjack_server-control.cpp | 31 +- source/libjack/libjack_time.cpp | 9 +- source/libjack/libjack_transport.cpp | 59 +-- 9 files changed, 485 insertions(+), 540 deletions(-) diff --git a/source/libjack/libjack.cpp b/source/libjack/libjack.cpp index bcbccb764..fb4cfd113 100644 --- a/source/libjack/libjack.cpp +++ b/source/libjack/libjack.cpp @@ -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 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::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::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::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(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; iname); - 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(std::strlen(portName)); + bufStrSize = static_cast(std::strlen(bufStr)); fShmNonRtServerControl.writeUInt(bufStrSize); - fShmNonRtServerControl.writeCustomData(portName, bufStrSize); + fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize); } // kPluginBridgeNonRtServerPortName for (uint32_t i=0; iname); + //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(std::strlen(portName)); + bufStrSize = static_cast(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::Itenerator it = fState.audioIns.begin2(); it.valid(); it.next()) - { - if (JackPortState* const jport = it.getValue(nullptr)) - delete jport; - } - - for (LinkedList::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 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(0); + } - uint32_t i = 0; - for (LinkedList::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::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::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(0); + uint32_t i; + + i = 0; + for (LinkedList::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::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; } diff --git a/source/libjack/libjack.hpp b/source/libjack/libjack.hpp index 93b92a672..baf2f1fdb 100644 --- a/source/libjack/libjack.hpp +++ b/source/libjack/libjack.hpp @@ -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 audioIns; LinkedList audioOuts; - uint32_t fakeIns, fakeOuts; - LinkedList midiIns; LinkedList 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::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::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 diff --git a/source/libjack/libjack_base.cpp b/source/libjack/libjack_base.cpp index 669f86f43..4bbf5b03c 100644 --- a/source/libjack/libjack_base.cpp +++ b/source/libjack/libjack_base.cpp @@ -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); } diff --git a/source/libjack/libjack_callbacks.cpp b/source/libjack/libjack_callbacks.cpp index 13a0e6602..3f3872e91 100644 --- a/source/libjack/libjack_callbacks.cpp +++ b/source/libjack/libjack_callbacks.cpp @@ -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; } diff --git a/source/libjack/libjack_client.cpp b/source/libjack/libjack_client.cpp index 9deaf1b27..366602003 100644 --- a/source/libjack/libjack_client.cpp +++ b/source/libjack/libjack_client.cpp @@ -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(); -} - // -------------------------------------------------------------------------------------------------------------------- diff --git a/source/libjack/libjack_ports.cpp b/source/libjack/libjack_ports.cpp index 39e8a6d8f..021460f18 100644 --- a/source/libjack/libjack_ports.cpp +++ b/source/libjack/libjack_ports.cpp @@ -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 diff --git a/source/libjack/libjack_server-control.cpp b/source/libjack/libjack_server-control.cpp index a27cfbac5..1a8991e44 100644 --- a/source/libjack/libjack_server-control.cpp +++ b/source/libjack/libjack_server-control.cpp @@ -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 diff --git a/source/libjack/libjack_time.cpp b/source/libjack/libjack_time.cpp index 73be1e524..4d7c4b89f 100644 --- a/source/libjack/libjack_time.cpp +++ b/source/libjack/libjack_time.cpp @@ -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; diff --git a/source/libjack/libjack_transport.cpp b/source/libjack/libjack_transport.cpp index b779f945c..9db085048 100644 --- a/source/libjack/libjack_transport.cpp +++ b/source/libjack/libjack_transport.cpp @@ -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*)