|
|
@@ -156,17 +156,10 @@ class CarlaJackClient : public Thread |
|
|
|
public: |
|
|
|
JackClientState fState; |
|
|
|
|
|
|
|
CarlaJackClient(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) |
|
|
|
CarlaJackClient() |
|
|
|
: Thread("CarlaJackClient"), |
|
|
|
fState(), |
|
|
|
fShmAudioPool(), |
|
|
|
fShmRtClientControl(), |
|
|
|
fShmNonRtClientControl(), |
|
|
|
fShmNonRtServerControl(), |
|
|
|
fBaseNameAudioPool(audioPoolBaseName), |
|
|
|
fBaseNameRtClientControl(rtClientBaseName), |
|
|
|
fBaseNameNonRtClientControl(nonRtClientBaseName), |
|
|
|
fBaseNameNonRtServerControl(nonRtServerBaseName), |
|
|
|
fIsValid(false), |
|
|
|
fIsOffline(false), |
|
|
|
fFirstIdle(true), |
|
|
|
fLastPingTime(-1), |
|
|
@@ -174,118 +167,27 @@ public: |
|
|
|
fAudioOuts(0) |
|
|
|
{ |
|
|
|
carla_debug("CarlaJackClient::CarlaJackClient(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); |
|
|
|
} |
|
|
|
|
|
|
|
~CarlaJackClient() noexcept override |
|
|
|
{ |
|
|
|
carla_debug("CarlaJackClient::~CarlaJackClient()"); |
|
|
|
|
|
|
|
clear(); |
|
|
|
} |
|
|
|
|
|
|
|
bool init(const char* const clientName) |
|
|
|
{ |
|
|
|
carla_debug("CarlaJackClient::init(\"%s\")", clientName); |
|
|
|
|
|
|
|
if (! fShmAudioPool.attachClient(fBaseNameAudioPool)) |
|
|
|
{ |
|
|
|
carla_stderr("Failed to attach to audio pool shared memory"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
const char* const shmIds(std::getenv("CARLA_SHM_IDS")); |
|
|
|
CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && std::strlen(shmIds) == 6*4,); |
|
|
|
|
|
|
|
if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl)) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to attach to rt client control shared memory"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
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); |
|
|
|
|
|
|
|
if (! fShmRtClientControl.mapData()) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to map rt client control shared memory"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl)) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to attach to non-rt client control shared memory"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtClientControl.mapData()) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to map non-rt control client shared memory"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl)) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to attach to non-rt server control shared memory"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtServerControl.mapData()) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to map non-rt control server shared memory"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
PluginBridgeNonRtClientOpcode opcode; |
|
|
|
|
|
|
|
opcode = fShmNonRtClientControl.readOpcode(); |
|
|
|
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientNull, opcode); |
|
|
|
|
|
|
|
const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt(); |
|
|
|
CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData)); |
|
|
|
|
|
|
|
const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt(); |
|
|
|
CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData)); |
|
|
|
|
|
|
|
const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt(); |
|
|
|
CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData)); |
|
|
|
|
|
|
|
if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) |
|
|
|
{ |
|
|
|
carla_stderr2("CarlaJackClient: data size mismatch"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
opcode = fShmNonRtClientControl.readOpcode(); |
|
|
|
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetBufferSize, opcode); |
|
|
|
fState.bufferSize = fShmNonRtClientControl.readUInt(); |
|
|
|
|
|
|
|
opcode = fShmNonRtClientControl.readOpcode(); |
|
|
|
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode); |
|
|
|
fState.sampleRate = fShmNonRtClientControl.readDouble(); |
|
|
|
|
|
|
|
if (fState.bufferSize == 0 || carla_isZero(fState.sampleRate)) |
|
|
|
{ |
|
|
|
carla_stderr2("CarlaJackClient: invalid empty state"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
fState.name = strdup(clientName); |
|
|
|
|
|
|
|
// tell backend we're live |
|
|
|
{ |
|
|
|
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); |
|
|
|
|
|
|
|
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong); |
|
|
|
fShmNonRtServerControl.commitWrite(); |
|
|
|
} |
|
|
|
fBaseNameAudioPool[6] = '\0'; |
|
|
|
fBaseNameRtClientControl[6] = '\0'; |
|
|
|
fBaseNameNonRtClientControl[6] = '\0'; |
|
|
|
fBaseNameNonRtServerControl[6] = '\0'; |
|
|
|
|
|
|
|
startThread(10); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool close() |
|
|
|
~CarlaJackClient() noexcept override |
|
|
|
{ |
|
|
|
carla_debug("CarlaJackClient::~CarlaJackClient()"); |
|
|
|
|
|
|
|
carla_debug("CarlaEnginePlugin::close()"); |
|
|
|
fLastPingTime = -1; |
|
|
|
|
|
|
@@ -306,8 +208,16 @@ public: |
|
|
|
|
|
|
|
fState.audioIns.clear(); |
|
|
|
fState.audioOuts.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
bool initIfNeeded(const char* const clientName) |
|
|
|
{ |
|
|
|
carla_debug("CarlaJackClient::initIfNeeded(\"%s\")", clientName); |
|
|
|
|
|
|
|
if (fState.name == nullptr) |
|
|
|
fState.name = strdup(clientName); |
|
|
|
|
|
|
|
return true; |
|
|
|
return fIsValid; |
|
|
|
} |
|
|
|
|
|
|
|
void clear() noexcept |
|
|
@@ -318,6 +228,11 @@ public: |
|
|
|
fShmNonRtServerControl.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
bool isValid() const noexcept |
|
|
|
{ |
|
|
|
return fIsValid; |
|
|
|
} |
|
|
|
|
|
|
|
void activate() |
|
|
|
{ |
|
|
|
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); |
|
|
@@ -607,6 +522,98 @@ protected: |
|
|
|
{ |
|
|
|
carla_stderr("CarlaJackClient run START"); |
|
|
|
|
|
|
|
if (! fShmAudioPool.attachClient(fBaseNameAudioPool)) |
|
|
|
{ |
|
|
|
carla_stderr("Failed to attach to audio pool shared memory"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl)) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to attach to rt client control shared memory"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmRtClientControl.mapData()) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to map rt client control shared memory"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl)) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to attach to non-rt client control shared memory"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtClientControl.mapData()) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to map non-rt control client shared memory"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl)) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to attach to non-rt server control shared memory"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (! fShmNonRtServerControl.mapData()) |
|
|
|
{ |
|
|
|
clear(); |
|
|
|
carla_stderr("Failed to map non-rt control server shared memory"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
PluginBridgeNonRtClientOpcode opcode; |
|
|
|
|
|
|
|
opcode = fShmNonRtClientControl.readOpcode(); |
|
|
|
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientNull, opcode); |
|
|
|
|
|
|
|
const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt(); |
|
|
|
CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData)); |
|
|
|
|
|
|
|
const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt(); |
|
|
|
CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData)); |
|
|
|
|
|
|
|
const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt(); |
|
|
|
CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData)); |
|
|
|
|
|
|
|
if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) |
|
|
|
{ |
|
|
|
carla_stderr2("CarlaJackClient: data size mismatch"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
opcode = fShmNonRtClientControl.readOpcode(); |
|
|
|
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetBufferSize, opcode); |
|
|
|
fState.bufferSize = fShmNonRtClientControl.readUInt(); |
|
|
|
|
|
|
|
opcode = fShmNonRtClientControl.readOpcode(); |
|
|
|
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode); |
|
|
|
fState.sampleRate = fShmNonRtClientControl.readDouble(); |
|
|
|
|
|
|
|
if (fState.bufferSize == 0 || carla_isZero(fState.sampleRate)) |
|
|
|
{ |
|
|
|
carla_stderr2("CarlaJackClient: invalid empty state"); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// tell backend we're live |
|
|
|
{ |
|
|
|
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); |
|
|
|
|
|
|
|
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong); |
|
|
|
fShmNonRtServerControl.commitWrite(); |
|
|
|
} |
|
|
|
|
|
|
|
fIsValid = true; |
|
|
|
|
|
|
|
#ifdef __SSE2_MATH__ |
|
|
|
// Set FTZ and DAZ flags |
|
|
|
_mm_setcsr(_mm_getcsr() | 0x8040); |
|
|
@@ -791,11 +798,12 @@ private: |
|
|
|
BridgeNonRtClientControl fShmNonRtClientControl; |
|
|
|
BridgeNonRtServerControl fShmNonRtServerControl; |
|
|
|
|
|
|
|
CarlaString fBaseNameAudioPool; |
|
|
|
CarlaString fBaseNameRtClientControl; |
|
|
|
CarlaString fBaseNameNonRtClientControl; |
|
|
|
CarlaString fBaseNameNonRtServerControl; |
|
|
|
char fBaseNameAudioPool[6+1]; |
|
|
|
char fBaseNameRtClientControl[6+1]; |
|
|
|
char fBaseNameNonRtClientControl[6+1]; |
|
|
|
char fBaseNameNonRtServerControl[6+1]; |
|
|
|
|
|
|
|
bool fIsValid; |
|
|
|
bool fIsOffline; |
|
|
|
bool fFirstIdle; |
|
|
|
int64_t fLastPingTime; |
|
|
@@ -814,57 +822,23 @@ CARLA_BACKEND_END_NAMESPACE |
|
|
|
|
|
|
|
CARLA_BACKEND_USE_NAMESPACE |
|
|
|
|
|
|
|
static CarlaJackClient* gClient = nullptr; |
|
|
|
static int gClientRefCount = 0; |
|
|
|
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 != nullptr) |
|
|
|
{ |
|
|
|
++gClientRefCount; |
|
|
|
return (jack_client_t*)gClient; |
|
|
|
} |
|
|
|
|
|
|
|
const char* const shmIds(std::getenv("CARLA_SHM_IDS")); |
|
|
|
|
|
|
|
if (shmIds == nullptr || std::strlen(shmIds) != 6*4) |
|
|
|
{ |
|
|
|
if (status != nullptr) |
|
|
|
*status = JackFailure; |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
char audioPoolBaseName[6+1]; |
|
|
|
char rtClientBaseName[6+1]; |
|
|
|
char nonRtClientBaseName[6+1]; |
|
|
|
char nonRtServerBaseName[6+1]; |
|
|
|
|
|
|
|
std::memcpy(audioPoolBaseName, shmIds+6*0, 6); |
|
|
|
std::memcpy(rtClientBaseName, shmIds+6*1, 6); |
|
|
|
std::memcpy(nonRtClientBaseName, shmIds+6*2, 6); |
|
|
|
std::memcpy(nonRtServerBaseName, shmIds+6*3, 6); |
|
|
|
|
|
|
|
audioPoolBaseName[6] = '\0'; |
|
|
|
rtClientBaseName[6] = '\0'; |
|
|
|
nonRtClientBaseName[6] = '\0'; |
|
|
|
nonRtServerBaseName[6] = '\0'; |
|
|
|
|
|
|
|
CarlaJackClient* const client = new CarlaJackClient(audioPoolBaseName, rtClientBaseName, |
|
|
|
nonRtClientBaseName, nonRtServerBaseName); |
|
|
|
|
|
|
|
if (! client->init(client_name)) |
|
|
|
if (! gClient.initIfNeeded(client_name)) |
|
|
|
{ |
|
|
|
if (status != nullptr) |
|
|
|
*status = JackServerError; |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
gClient = client; |
|
|
|
++gClientRefCount; |
|
|
|
return (jack_client_t*)client; |
|
|
|
return (jack_client_t*)&gClient; |
|
|
|
} |
|
|
|
|
|
|
|
CARLA_EXPORT |
|
|
@@ -886,21 +860,7 @@ int jack_client_close(jack_client_t* client) |
|
|
|
if (jstate.activated) |
|
|
|
jclient->deactivate(); |
|
|
|
|
|
|
|
if (--gClientRefCount == 0) |
|
|
|
{ |
|
|
|
#if 0 |
|
|
|
static bool ignoreFirstClientClose = true; |
|
|
|
if (ignoreFirstClientClose) |
|
|
|
{ |
|
|
|
ignoreFirstClientClose = false; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
#endif |
|
|
|
jclient->close(); |
|
|
|
delete jclient; |
|
|
|
gClient = nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
--gClientRefCount; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|