Does not yet fix the infamous bug #234, but some audio passes through now. Still don't really know what's going on...tags/1.9.7
@@ -33,9 +33,10 @@ using juce::File; | |||
using juce::MemoryBlock; | |||
using juce::String; | |||
using juce::Time; | |||
using juce::Thread; | |||
template<typename T> | |||
bool jackbridge_shm_map2(char* shm, T*& value) noexcept | |||
bool jackbridge_shm_map2(void* shm, T*& value) noexcept | |||
{ | |||
value = (T*)jackbridge_shm_map(shm, sizeof(T)); | |||
return (value != nullptr); | |||
@@ -162,24 +163,28 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> { | |||
setRingBuffer(nullptr, false); | |||
} | |||
void postClient() noexcept | |||
PluginBridgeRtClientOpcode readOpcode() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | |||
jackbridge_sem_post(&data->sem.client); | |||
return static_cast<PluginBridgeRtClientOpcode>(readUInt()); | |||
} | |||
bool waitForServer(const uint secs) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | |||
// helper class that automatically posts semaphore on destructor | |||
struct WaitHelper { | |||
BridgeRtClientData* const data; | |||
const bool ok; | |||
return jackbridge_sem_timedwait(&data->sem.server, secs); | |||
} | |||
WaitHelper(BridgeRtClientControl& c) noexcept | |||
: data(c.data), | |||
ok(jackbridge_sem_timedwait(&data->sem.server, 5)) {} | |||
PluginBridgeRtClientOpcode readOpcode() noexcept | |||
{ | |||
return static_cast<PluginBridgeRtClientOpcode>(readUInt()); | |||
} | |||
~WaitHelper() noexcept | |||
{ | |||
if (ok) | |||
jackbridge_sem_post(&data->sem.client); | |||
} | |||
CARLA_DECLARE_NON_COPY_STRUCT(WaitHelper) | |||
}; | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl) | |||
}; | |||
@@ -363,12 +368,12 @@ struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> | |||
// ------------------------------------------------------------------- | |||
class CarlaEngineBridge : public CarlaEngine, | |||
public CarlaThread | |||
public Thread | |||
{ | |||
public: | |||
CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) | |||
: CarlaEngine(), | |||
CarlaThread("CarlaEngineBridge"), | |||
Thread("CarlaEngineBridge"), | |||
fShmAudioPool(), | |||
fShmRtClientControl(), | |||
fShmNonRtClientControl(), | |||
@@ -500,7 +505,7 @@ public: | |||
fShmNonRtServerControl.commitWrite(); | |||
} | |||
startThread(); | |||
startThread(10); | |||
return true; | |||
} | |||
@@ -796,6 +801,7 @@ public: | |||
if (fLastPingTime > 0 && Time::currentTimeMillis() > fLastPingTime + 30000 && ! wasFirstIdle) | |||
{ | |||
carla_stderr("Did not receive ping message from server for 30 secs, closing..."); | |||
threadShouldExit(); | |||
callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr); | |||
} | |||
} | |||
@@ -1203,29 +1209,14 @@ public: | |||
protected: | |||
void run() override | |||
{ | |||
bool timedOut = false; | |||
bool quitReceived = false; | |||
for (; ! shouldThreadExit();) | |||
for (; ! threadShouldExit();) | |||
{ | |||
if (! fShmRtClientControl.waitForServer(5)) | |||
{ | |||
// Give engine 1 more change to catch up. | |||
if (! timedOut) | |||
{ | |||
carla_stderr2("Bridge timed-out, giving it one more chance"); | |||
timedOut = true; | |||
continue; | |||
} | |||
const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl); | |||
carla_stderr2("Bridge timed-out, final post..."); | |||
fShmRtClientControl.postClient(); | |||
carla_stderr2("Bridge timed-out, done."); | |||
signalThreadShouldExit(); | |||
break; | |||
} | |||
timedOut = false; | |||
if (! helper.ok) | |||
continue; | |||
for (; fShmRtClientControl.isDataAvailableForReading();) | |||
{ | |||
@@ -1504,8 +1495,6 @@ protected: | |||
} break; | |||
} | |||
} | |||
fShmRtClientControl.postClient(); | |||
} | |||
callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr); | |||
@@ -120,6 +120,7 @@ struct BridgeAudioPool { | |||
size = sizeof(float); | |||
data = (float*)carla_shm_map(shm, size); | |||
std::memset(data, 0, size); | |||
} | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) | |||
@@ -221,9 +222,7 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> { | |||
if (carla_shm_map<BridgeRtClientData>(shm, data)) | |||
{ | |||
carla_zeroStruct(data->sem); | |||
carla_zeroStruct(data->timeInfo); | |||
carla_zeroBytes(data->midiOut, kBridgeRtClientDataMidiOutSize); | |||
std::memset(data, 0, sizeof(BridgeRtClientData)); | |||
setRingBuffer(&data->ringBuffer, true); | |||
return true; | |||
} | |||
@@ -548,7 +547,12 @@ protected: | |||
#ifndef CARLA_OS_WIN | |||
// start with "wine" if needed | |||
if (fBinary.endsWithIgnoreCase(".exe")) | |||
arguments.add("wine"); | |||
{ | |||
if (File("/usr/bin/wine-rt").existsAsFile()) | |||
arguments.add("wine-rt"); | |||
else | |||
arguments.add("wine"); | |||
} | |||
#endif | |||
// binary | |||
@@ -2644,13 +2648,12 @@ private: | |||
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool); | |||
fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.size)); | |||
fShmRtClientControl.commitWrite(); | |||
waitForClient("resize-pool"); | |||
waitForClient("resize-pool", 5); | |||
} | |||
void waitForClient(const char* const action, const uint secs = 5) | |||
void waitForClient(const char* const action, const uint secs) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(! fTimedOut,); | |||
CARLA_SAFE_ASSERT_RETURN(! fTimedError,); | |||
@@ -2659,7 +2662,7 @@ private: | |||
return; | |||
fTimedOut = true; | |||
carla_stderr("waitForClient(%s) timeout here", action); | |||
carla_stderr("waitForClient(%s) timed out", action); | |||
} | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge) | |||
@@ -128,20 +128,49 @@ bool carla_sem_timedwait(carla_sem_t& sem, const uint secs) noexcept | |||
#elif defined(CARLA_OS_MAC) | |||
// TODO | |||
#else | |||
timespec timeout; | |||
# ifdef CARLA_OS_LINUX | |||
if (::sem_trywait(&sem.sem) == 0) | |||
return true; | |||
# if 1 | |||
/* NOTE: | |||
* This is very ugly! | |||
* While trying to fix 32bit-on-64bit issues I noticed this somehow gets a signal, | |||
* while that timedwait does not. | |||
* I'll keep this code for the time being, but only for TESTING! | |||
* It should revert to the proper code (below) when we know more info about the bug. | |||
*/ | |||
timespec timeout, now, step; | |||
step.tv_sec = 0; | |||
step.tv_nsec = 2; | |||
::clock_gettime(CLOCK_REALTIME, &timeout); | |||
timeout.tv_sec += static_cast<time_t>(secs); | |||
for (;;) | |||
{ | |||
::nanosleep(&step, NULL); | |||
::clock_gettime(CLOCK_REALTIME, &now); | |||
if (now.tv_sec >= timeout.tv_sec) | |||
return false; | |||
if (::sem_trywait(&sem.sem) == 0) | |||
return true; | |||
} | |||
//timeval now; | |||
//::gettimeofday(&now, nullptr); | |||
//timeout.tv_sec = now.tv_sec; | |||
//timeout.tv_nsec = now.tv_usec * 1000; | |||
# else | |||
timeval now; | |||
::gettimeofday(&now, nullptr); | |||
timeout.tv_sec = now.tv_sec; | |||
timeout.tv_nsec = now.tv_usec * 1000; | |||
# endif | |||
timespec timeout; | |||
::clock_gettime(CLOCK_REALTIME, &timeout); | |||
timeout.tv_sec += static_cast<time_t>(secs); | |||
try { | |||
return (::sem_timedwait(&sem.sem, &timeout) == 0); | |||
} CARLA_SAFE_EXCEPTION_RETURN("sem_timedwait", false); | |||
# endif | |||
#endif | |||
} | |||