@@ -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; | |||
} | |||
@@ -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 | |||
@@ -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); | |||
} | |||
@@ -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; | |||
} | |||
@@ -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,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 | |||
@@ -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 | |||
@@ -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; | |||
@@ -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*) | |||