Browse Source

libjack can now control window show/hide, lots more libjack work

tags/1.9.8
falkTX 7 years ago
parent
commit
4fd815b2d8
10 changed files with 487 additions and 148 deletions
  1. +3
    -3
      resources/ui/carla_add_jack.ui
  2. +63
    -28
      source/backend/plugin/CarlaPluginJack.cpp
  3. +151
    -31
      source/interposer/interposer-jack-x11.cpp
  4. +86
    -48
      source/libjack/libjack.cpp
  5. +20
    -6
      source/libjack/libjack.hpp
  6. +49
    -3
      source/libjack/libjack_latency.cpp
  7. +17
    -5
      source/libjack/libjack_midi.cpp
  8. +7
    -4
      source/libjack/libjack_port-searching.cpp
  9. +63
    -16
      source/libjack/libjack_ports.cpp
  10. +28
    -4
      source/libjack/libjack_time.cpp

+ 3
- 3
resources/ui/carla_add_jack.ui View File

@@ -159,12 +159,12 @@
</item> </item>
<item row="3" column="1" colspan="3"> <item row="3" column="1" colspan="3">
<widget class="QCheckBox" name="cb_manage_window"> <widget class="QCheckBox" name="cb_manage_window">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>Take control of main applicaton window</string> <string>Take control of main applicaton window</string>
</property> </property>
<property name="checked">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item row="2" column="1" colspan="2"> <item row="2" column="1" colspan="2">


+ 63
- 28
source/backend/plugin/CarlaPluginJack.cpp View File

@@ -130,7 +130,11 @@ protected:
const ScopedEnvVar sev2("LD_LIBRARY_PATH", libjackdir.buffer()); const ScopedEnvVar sev2("LD_LIBRARY_PATH", libjackdir.buffer());
const ScopedEnvVar sev1("LD_PRELOAD", ldpreload.isNotEmpty() ? ldpreload.buffer() : nullptr); const ScopedEnvVar sev1("LD_PRELOAD", ldpreload.isNotEmpty() ? ldpreload.buffer() : nullptr);


carla_setenv("CARLA_FRONTEND_WIN_ID", strBuf);
if (kPlugin->getHints() & PLUGIN_HAS_CUSTOM_UI)
carla_setenv("CARLA_FRONTEND_WIN_ID", strBuf);
else
carla_unsetenv("CARLA_FRONTEND_WIN_ID");

carla_setenv("CARLA_LIBJACK_SETUP", fNumPorts.buffer()); carla_setenv("CARLA_LIBJACK_SETUP", fNumPorts.buffer());
carla_setenv("CARLA_SHM_IDS", fShmIds.buffer()); carla_setenv("CARLA_SHM_IDS", fShmIds.buffer());


@@ -154,12 +158,12 @@ protected:


if (fProcess->isRunning()) if (fProcess->isRunning())
{ {
carla_stdout("CarlaPluginJackThread::run() - bridge refused to close, force kill now");
carla_stdout("CarlaPluginJackThread::run() - application refused to close, force kill now");
fProcess->kill(); fProcess->kill();
} }
else else
{ {
carla_stdout("CarlaPluginJackThread::run() - bridge auto-closed successfully");
carla_stdout("CarlaPluginJackThread::run() - application auto-closed successfully");
} }
} }
else else
@@ -167,7 +171,7 @@ protected:
// forced quit, may have crashed // forced quit, may have crashed
if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/)
{ {
carla_stderr("CarlaPluginJackThread::run() - bridge crashed");
carla_stderr("CarlaPluginJackThread::run() - application crashed");


CarlaString errorString("Plugin '" + CarlaString(kPlugin->getName()) + "' has crashed!\n" CarlaString errorString("Plugin '" + CarlaString(kPlugin->getName()) + "' has crashed!\n"
"Saving now will lose its current settings.\n" "Saving now will lose its current settings.\n"
@@ -176,7 +180,7 @@ protected:
} }
else else
{ {
carla_stderr("CarlaPluginJackThread::run() - bridge closed itself");
carla_stderr("CarlaPluginJackThread::run() - application closed itself");
} }
} }


@@ -364,6 +368,18 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Set ui stuff // Set ui stuff


void showCustomUI(const bool yesNo) override
{
if (yesNo && ! fBridgeThread.isThreadRunning()) {
CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),);
}

const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);

fShmNonRtClientControl.writeOpcode(yesNo ? kPluginBridgeNonRtClientShowUI : kPluginBridgeNonRtClientHideUI);
fShmNonRtClientControl.commitWrite();
}

void idle() override void idle() override
{ {
if (fBridgeThread.isThreadRunning()) if (fBridgeThread.isThreadRunning())
@@ -395,9 +411,12 @@ public:
fTimedOut = true; fTimedOut = true;
fTimedError = true; fTimedError = true;
fInitiated = false; fInitiated = false;
carla_stderr2("Plugin bridge has been stopped or crashed");
pData->engine->callback(ENGINE_CALLBACK_PLUGIN_UNAVAILABLE, pData->id, 0, 0, 0.0f,
"Plugin bridge has been stopped or crashed");
handleProcessStopped();
}
else if (fProcCanceled)
{
handleProcessStopped();
fProcCanceled = false;
} }


CarlaPlugin::idle(); CarlaPlugin::idle();
@@ -941,7 +960,6 @@ public:


if (fShmRtClientControl.data->procFlags) if (fShmRtClientControl.data->procFlags)
{ {
carla_stdout("PROC Flags active, disabling plugin");
fInitiated = false; fInitiated = false;
fProcCanceled = true; fProcCanceled = true;
} }
@@ -1126,17 +1144,11 @@ public:
break; break;


case kPluginBridgeNonRtServerUiClosed: case kPluginBridgeNonRtServerUiClosed:
carla_stdout("bridge closed cleanly?");
pData->active = false;

#ifdef HAVE_LIBLO
if (pData->engine->isOscControlRegistered())
pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_ACTIVE, 0.0f);
#endif

pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0.0f, nullptr);

fBridgeThread.stopThread(1000);
carla_stdout("got kPluginBridgeNonRtServerUiClosed, bridge closed cleanly?");
pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
//fBridgeThread.signalThreadShouldExit();
//handleProcessStopped();
//fBridgeThread.stopThread(5000);
break; break;


case kPluginBridgeNonRtServerError: { case kPluginBridgeNonRtServerError: {
@@ -1220,6 +1232,8 @@ public:


fInfo.setupLabel = label; fInfo.setupLabel = label;


const int setupHints = label[4] - '0';

// --------------------------------------------------------------- // ---------------------------------------------------------------
// set info // set info


@@ -1265,6 +1279,17 @@ public:
return false; return false;
} }


// ---------------------------------------------------------------
// setup hints and options

// FIXME dryWet broken
pData->hints = PLUGIN_IS_BRIDGE | /*PLUGIN_CAN_DRYWET |*/ PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_NEEDS_FIXED_BUFFERS;
pData->options = PLUGIN_OPTION_FIXED_BUFFERS;
//fInfo.optionsAvailable = optionAv;

if (setupHints & 0x10)
pData->hints |= PLUGIN_HAS_CUSTOM_UI;

// --------------------------------------------------------------- // ---------------------------------------------------------------
// init bridge thread // init bridge thread


@@ -1283,14 +1308,6 @@ public:
if (! restartBridgeThread()) if (! restartBridgeThread())
return false; return false;


// ---------------------------------------------------------------
// setup hints and options

// FIXME dryWet broken
pData->hints = PLUGIN_IS_BRIDGE | /*PLUGIN_CAN_DRYWET |*/ PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE | PLUGIN_NEEDS_FIXED_BUFFERS;
pData->options = PLUGIN_OPTION_FIXED_BUFFERS;
//fInfo.optionsAvailable = optionAv;

// --------------------------------------------------------------- // ---------------------------------------------------------------
// register client // register client


@@ -1344,6 +1361,24 @@ private:
CARLA_DECLARE_NON_COPY_STRUCT(Info) CARLA_DECLARE_NON_COPY_STRUCT(Info)
} fInfo; } fInfo;


void handleProcessStopped() noexcept
{
const bool wasActive = pData->active;
pData->active = false;

if (wasActive)
{
#ifdef HAVE_LIBLO
if (pData->engine->isOscControlRegistered())
pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_ACTIVE, 0.0f);
#endif
pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0.0f, nullptr);
}

if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
}

void resizeAudioPool(const uint32_t bufferSize) void resizeAudioPool(const uint32_t bufferSize)
{ {
fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, 0); fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, 0);


+ 151
- 31
source/interposer/interposer-jack-x11.cpp View File

@@ -22,9 +22,22 @@


struct ScopedLibOpen { struct ScopedLibOpen {
void* handle; void* handle;
Window winId;


ScopedLibOpen() ScopedLibOpen()
: handle(dlopen("libjack.so.0", RTLD_NOW|RTLD_LOCAL)) {}
: handle(dlopen("libjack.so.0", RTLD_NOW|RTLD_LOCAL)),
winId(0)
{
if (const char* const winIdStr = std::getenv("CARLA_FRONTEND_WIN_ID"))
{
CARLA_SAFE_ASSERT_RETURN(winIdStr[0] != '\0',);

const long long winIdLL(std::strtoll(winIdStr, nullptr, 16));
CARLA_SAFE_ASSERT_RETURN(winIdLL > 0,);

winId = static_cast<Window>(winIdLL);
}
}


~ScopedLibOpen() ~ScopedLibOpen()
{ {
@@ -33,18 +46,23 @@ struct ScopedLibOpen {
} }
}; };


// -----------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// Function typedefs // Function typedefs


typedef int (*XMapWindowFunc)(Display*, Window); typedef int (*XMapWindowFunc)(Display*, Window);
typedef int (*XUnmapWindowFunc)(Display*, Window); typedef int (*XUnmapWindowFunc)(Display*, Window);
typedef int (*CarlaInterposedCallback)(int, void*);


// -----------------------------------------------------------------------
// Current mapped window
// ---------------------------------------------------------------------------------------------------------------------
// Current state


static Window sCurrentlyMappedWindow = 0;
static Display* gCurrentlyMappedDisplay = nullptr;
static Window gCurrentlyMappedWindow = 0;
static CarlaInterposedCallback gInterposedCallback = nullptr;
static bool gCurrentWindowMapped = false;
static bool gCurrentWindowVisible = false;


// -----------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// Calling the real functions // Calling the real functions


static int real_XMapWindow(Display* display, Window window) static int real_XMapWindow(Display* display, Window window)
@@ -63,7 +81,7 @@ static int real_XUnmapWindow(Display* display, Window window)
return func(display, window); return func(display, window);
} }


// -----------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------
// Our custom functions // Our custom functions


CARLA_EXPORT CARLA_EXPORT
@@ -73,7 +91,7 @@ int XMapWindow(Display* display, Window window)


for (;;) for (;;)
{ {
if (sCurrentlyMappedWindow != 0)
if (slo.winId == 0)
break; break;


Atom atom; Atom atom;
@@ -84,40 +102,96 @@ int XMapWindow(Display* display, Window window)
const Atom wmWindowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", True); const Atom wmWindowType = XInternAtom(display, "_NET_WM_WINDOW_TYPE", True);


if (XGetWindowProperty(display, window, wmWindowType, 0, ~0L, False, AnyPropertyType, if (XGetWindowProperty(display, window, wmWindowType, 0, ~0L, False, AnyPropertyType,
&atom, &atomFormat, &numItems, &ignored, &atomPtrs) == Success)
&atom, &atomFormat, &numItems, &ignored, &atomPtrs) != Success)
break;

const Atom* const atomValues = (const Atom*)atomPtrs;
bool isMainWindow = (numItems == 0);

for (ulong i=0; i<numItems; ++i)
{ {
const Atom* const atomValues = (const Atom*)atomPtrs;
const char* const atomValue(XGetAtomName(display, atomValues[i]));
CARLA_SAFE_ASSERT_CONTINUE(atomValue != nullptr && atomValue[0] != '\0');

if (std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_COMBO" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DIALOG" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DND" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DOCK" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU") == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_MENU" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_NOTIFICATION" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_POPUP_MENU" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_SPLASH" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_TOOLBAR" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_TOOLTIP" ) == 0 ||
std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_UTILITY" ) == 0)
{
isMainWindow = false;
break;
}


for (ulong i=0; i<numItems; ++i)
if (std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_NORMAL") == 0)
{
// window is good, use it if no other types are set
isMainWindow = true;
}
else
{ {
const char* const atomValue(XGetAtomName(display, atomValues[i]));
CARLA_SAFE_ASSERT_CONTINUE(atomValue != nullptr && atomValue[0] != '\0');

if (std::strcmp(atomValue, "_NET_WM_WINDOW_TYPE_NORMAL") == 0)
{
sCurrentlyMappedWindow = window;
break;
}
carla_stdout("=======================================> %s", atomValue);
} }
} }


if (sCurrentlyMappedWindow == 0)
if (! isMainWindow)
{
// this has always bothered me...
if (gCurrentlyMappedWindow != 0 && gCurrentWindowMapped && gCurrentWindowVisible)
XSetTransientForHint(display, window, gCurrentlyMappedWindow);
break; break;
}


if (const char* const winIdStr = std::getenv("CARLA_FRONTEND_WIN_ID"))
Window transientWindow = 0;
if (XGetTransientForHint(display, window, &transientWindow) == Success && transientWindow != 0)
{ {
CARLA_SAFE_ASSERT_BREAK(winIdStr[0] != '\0');
carla_stdout("Window has transient set already, ignoring it");
break;
}


const long long winIdLL(std::strtoll(winIdStr, nullptr, 16));
CARLA_SAFE_ASSERT_BREAK(winIdLL > 0);
// got a new window, we may need to forget last one
if (gCurrentlyMappedDisplay != nullptr && gCurrentlyMappedWindow != 0)
{
// igonre requests against the current mapped window
if (gCurrentlyMappedWindow == window)
return 0;

// we already have a mapped window, with carla visible button on, should be a dialog of sorts..
if (gCurrentWindowMapped && gCurrentWindowVisible)
{
XSetTransientForHint(display, window, gCurrentlyMappedWindow);
break;
}
// ignore empty windows created after the main one
if (numItems == 0)
break;

carla_stdout("NOTICE: XMapWindow now showing previous window");
real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow);
}


const Window winId(static_cast<Window>(winIdLL));
XSetTransientForHint(display, window, static_cast<Window>(winId));
gCurrentlyMappedDisplay = display;
gCurrentlyMappedWindow = window;
gCurrentWindowMapped = true;


carla_stdout("Transient hint correctly applied before mapping window");
XSetTransientForHint(display, window, slo.winId);

if (gCurrentWindowVisible)
{
carla_stdout("JACK application window found, showing it now");
break;
} }


break;
gCurrentWindowMapped = false;
carla_stdout("JACK application window found and captured");
return 0;
} }


return real_XMapWindow(display, window); return real_XMapWindow(display, window);
@@ -126,10 +200,56 @@ int XMapWindow(Display* display, Window window)
CARLA_EXPORT CARLA_EXPORT
int XUnmapWindow(Display* display, Window window) int XUnmapWindow(Display* display, Window window)
{ {
if (sCurrentlyMappedWindow == window)
sCurrentlyMappedWindow = 0;
if (gCurrentlyMappedWindow == window)
{
gCurrentlyMappedDisplay = nullptr;
gCurrentlyMappedWindow = 0;
gCurrentWindowMapped = false;
gCurrentWindowVisible = false;

if (gInterposedCallback != nullptr)
gInterposedCallback(1, nullptr);
}


return real_XUnmapWindow(display, window); return real_XUnmapWindow(display, window);
} }


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

CARLA_EXPORT
int jack_carla_interposed_action(int action, void* ptr)
{
carla_stdout("jack_carla_interposed_action(%i, %p)", action, ptr);

switch (action)
{
case 1: // set callback
gInterposedCallback = (CarlaInterposedCallback)ptr;
break;

case 2: // show gui
gCurrentWindowVisible = true;
if (gCurrentlyMappedDisplay == nullptr || gCurrentlyMappedWindow == 0)
break;
gCurrentWindowMapped = true;
return real_XMapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow);

case 3: // hide gui
gCurrentWindowVisible = false;
if (gCurrentlyMappedDisplay == nullptr || gCurrentlyMappedWindow == 0)
break;
gCurrentWindowMapped = false;
return real_XUnmapWindow(gCurrentlyMappedDisplay, gCurrentlyMappedWindow);

case 4: // close everything
gCurrentWindowMapped = false;
gCurrentWindowVisible = false;
gCurrentlyMappedDisplay = nullptr;
gCurrentlyMappedWindow = 0;
return 0;
}

return -1;
}

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

+ 86
- 48
source/libjack/libjack.cpp View File

@@ -24,6 +24,15 @@ using juce::FloatVectorOperations;
using juce::Thread; using juce::Thread;
using juce::Time; using juce::Time;


typedef int (*CarlaInterposedCallback)(int, void*);

CARLA_EXPORT
int jack_carla_interposed_action(int, void*)
{
carla_stderr2("Non-export jack_carla_interposed_action called, this should not happen!!");
return 0;
}

CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


// --------------------------------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------------------------------
@@ -76,6 +85,8 @@ private:
Callback* const fCallback; Callback* const fCallback;
}; };


static int carla_interposed_callback(int, void*);

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


class CarlaJackAppClient : public CarlaJackRealtimeThread::Callback, class CarlaJackAppClient : public CarlaJackRealtimeThread::Callback,
@@ -90,7 +101,7 @@ public:
fAudioPoolCopy(nullptr), fAudioPoolCopy(nullptr),
fAudioTmpBuf(nullptr), fAudioTmpBuf(nullptr),
fDummyMidiInBuffer(true, "ignored"), fDummyMidiInBuffer(true, "ignored"),
fDummyMidiOutBuffer(true, "ignored"),
fDummyMidiOutBuffer(false, "ignored"),
fMidiInBuffers(nullptr), fMidiInBuffers(nullptr),
fMidiOutBuffers(nullptr), fMidiOutBuffers(nullptr),
fIsOffline(false), fIsOffline(false),
@@ -127,10 +138,12 @@ public:
fBaseNameNonRtClientControl[6] = '\0'; fBaseNameNonRtClientControl[6] = '\0';
fBaseNameNonRtServerControl[6] = '\0'; fBaseNameNonRtServerControl[6] = '\0';


fNumPorts.audioIns = libjackSetup[0] - '0';
fNumPorts.audioOuts = libjackSetup[1] - '0';
fNumPorts.midiIns = libjackSetup[2] - '0';
fNumPorts.midiOuts = libjackSetup[3] - '0';
fServer.numAudioIns = libjackSetup[0] - '0';
fServer.numAudioOuts = libjackSetup[1] - '0';
fServer.numMidiIns = libjackSetup[2] - '0';
fServer.numMidiOuts = libjackSetup[3] - '0';

jack_carla_interposed_action(1, (void*)carla_interposed_callback);


fNonRealtimeThread.startThread(); fNonRealtimeThread.startThread();
} }
@@ -181,6 +194,23 @@ public:
return (pthread_t)fRealtimeThread.getThreadId(); return (pthread_t)fRealtimeThread.getThreadId();
} }


int handleInterposerCallback(const int cb_action, void* const ptr)
{
carla_stdout("handleInterposerCallback(%o, %p)", cb_action, ptr);

switch (cb_action)
{
case 1: {
const CarlaMutexLocker cml(fShmNonRtServerControl.mutex);
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
fShmNonRtServerControl.commitWrite();
break;
}
}

return 0;
}

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


protected: protected:
@@ -215,19 +245,6 @@ private:
bool fIsOffline; bool fIsOffline;
int64_t fLastPingTime; int64_t fLastPingTime;


struct NumPorts {
uint8_t audioIns;
uint8_t audioOuts;
uint8_t midiIns;
uint8_t midiOuts;

NumPorts()
: audioIns(0),
audioOuts(0),
midiIns(0),
midiOuts(0) {}
} fNumPorts;

CarlaJackRealtimeThread fRealtimeThread; CarlaJackRealtimeThread fRealtimeThread;
CarlaJackNonRealtimeThread fNonRealtimeThread; CarlaJackNonRealtimeThread fNonRealtimeThread;


@@ -477,7 +494,7 @@ bool CarlaJackAppClient::handleRtData()
const uint8_t size(fShmRtClientControl.readByte()); const uint8_t size(fShmRtClientControl.readByte());
CARLA_SAFE_ASSERT_BREAK(size > 0); CARLA_SAFE_ASSERT_BREAK(size > 0);


if (port >= fNumPorts.midiIns || size > JackMidiPortBuffer::kMaxEventSize || ! fRealtimeThreadMutex.tryLock())
if (port >= fServer.numMidiIns || size > JackMidiPortBuffer::kMaxEventSize || ! fRealtimeThreadMutex.tryLock())
{ {
for (uint8_t i=0; i<size; ++i) for (uint8_t i=0; i<size; ++i)
fShmRtClientControl.readByte(); fShmRtClientControl.readByte();
@@ -513,7 +530,7 @@ bool CarlaJackAppClient::handleRtData()
CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr); CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);


// location to start of audio outputs (shm buffer) // location to start of audio outputs (shm buffer)
float* const fdataRealOuts = fShmAudioPool.data+(fServer.bufferSize*fNumPorts.audioIns);
float* const fdataRealOuts = fShmAudioPool.data+(fServer.bufferSize*fServer.numAudioIns);


if (! fClients.isEmpty()) if (! fClients.isEmpty())
{ {
@@ -558,8 +575,8 @@ bool CarlaJackAppClient::handleRtData()
// check if we can process // check if we can process
if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated) if (cmtl2.wasNotLocked() || jclient->processCb == nullptr || ! jclient->activated)
{ {
if (fNumPorts.audioOuts > 0)
FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts);
if (fServer.numAudioOuts > 0)
FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fServer.numAudioOuts);


if (jclient->deactivated) if (jclient->deactivated)
fShmRtClientControl.data->procFlags = 1; fShmRtClientControl.data->procFlags = 1;
@@ -581,7 +598,7 @@ bool CarlaJackAppClient::handleRtData()
JackPortState* const jport = it.getValue(nullptr); JackPortState* const jport = it.getValue(nullptr);
CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);


if (i++ < fNumPorts.audioIns)
if (i++ < fServer.numAudioIns)
{ {
jport->buffer = fdataReal; jport->buffer = fdataReal;
fdataReal += fServer.bufferSize; fdataReal += fServer.bufferSize;
@@ -594,7 +611,7 @@ bool CarlaJackAppClient::handleRtData()
} }
} }
// FIXME one single "if" // FIXME one single "if"
for (; i++ < fNumPorts.audioIns;)
for (; i++ < fServer.numAudioIns;)
{ {
fdataReal += fServer.bufferSize; fdataReal += fServer.bufferSize;
fdataCopy += fServer.bufferSize; fdataCopy += fServer.bufferSize;
@@ -610,7 +627,7 @@ bool CarlaJackAppClient::handleRtData()
JackPortState* const jport = it.getValue(nullptr); JackPortState* const jport = it.getValue(nullptr);
CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);


if (i++ < fNumPorts.audioOuts)
if (i++ < fServer.numAudioOuts)
{ {
jport->buffer = fdataCopy; jport->buffer = fdataCopy;
fdataCopy += fServer.bufferSize; fdataCopy += fServer.bufferSize;
@@ -622,7 +639,7 @@ bool CarlaJackAppClient::handleRtData()
} }
} }
// FIXME one single "if" // FIXME one single "if"
for (; i++ < fNumPorts.audioOuts;)
for (; i++ < fServer.numAudioOuts;)
{ {
FloatVectorOperations::clear(fdataCopy, fServer.bufferSize); FloatVectorOperations::clear(fdataCopy, fServer.bufferSize);
fdataCopy += fServer.bufferSize; fdataCopy += fServer.bufferSize;
@@ -635,7 +652,7 @@ bool CarlaJackAppClient::handleRtData()
JackPortState* const jport = it.getValue(nullptr); JackPortState* const jport = it.getValue(nullptr);
CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);


if (i++ < fNumPorts.midiIns)
if (i++ < fServer.numMidiIns)
jport->buffer = &fMidiInBuffers[i-1]; jport->buffer = &fMidiInBuffers[i-1];
else else
jport->buffer = &fDummyMidiInBuffer; jport->buffer = &fDummyMidiInBuffer;
@@ -648,7 +665,7 @@ bool CarlaJackAppClient::handleRtData()
JackPortState* const jport = it.getValue(nullptr); JackPortState* const jport = it.getValue(nullptr);
CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr); CARLA_SAFE_ASSERT_CONTINUE(jport != nullptr);


if (i++ < fNumPorts.midiOuts)
if (i++ < fServer.numMidiOuts)
jport->buffer = &fMidiOutBuffers[i-1]; jport->buffer = &fMidiOutBuffers[i-1];
else else
jport->buffer = &fDummyMidiOutBuffer; jport->buffer = &fDummyMidiOutBuffer;
@@ -659,19 +676,19 @@ bool CarlaJackAppClient::handleRtData()


jclient->processCb(fServer.bufferSize, jclient->processCbPtr); jclient->processCb(fServer.bufferSize, jclient->processCbPtr);


if (fNumPorts.audioOuts > 0)
if (fServer.numAudioOuts > 0)
{ {
if (++numClientOutputsProcessed == 1) if (++numClientOutputsProcessed == 1)
{ {
// first client, we can copy stuff over // first client, we can copy stuff over
FloatVectorOperations::copy(fdataRealOuts, fdataCopyOuts, FloatVectorOperations::copy(fdataRealOuts, fdataCopyOuts,
fServer.bufferSize*fNumPorts.audioOuts);
fServer.bufferSize*fServer.numAudioOuts);
} }
else else
{ {
// subsequent clients, add data (then divide by number of clients later on) // subsequent clients, add data (then divide by number of clients later on)
FloatVectorOperations::add(fdataRealOuts, fdataCopyOuts, FloatVectorOperations::add(fdataRealOuts, fdataCopyOuts,
fServer.bufferSize*fNumPorts.audioOuts);
fServer.bufferSize*fServer.numAudioOuts);
} }
} }
} }
@@ -682,28 +699,28 @@ bool CarlaJackAppClient::handleRtData()
// more than 1 client active, need to divide buffers // more than 1 client active, need to divide buffers
FloatVectorOperations::multiply(fdataRealOuts, FloatVectorOperations::multiply(fdataRealOuts,
1.0f/static_cast<float>(numClientOutputsProcessed), 1.0f/static_cast<float>(numClientOutputsProcessed),
fServer.bufferSize*fNumPorts.audioOuts);
fServer.bufferSize*fServer.numAudioOuts);
} }
} }
// fClients.isEmpty() // fClients.isEmpty()
else if (fNumPorts.audioOuts > 0)
else if (fServer.numAudioOuts > 0)
{ {
FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fNumPorts.audioOuts);
FloatVectorOperations::clear(fdataRealOuts, fServer.bufferSize*fServer.numAudioOuts);
} }


for (uint8_t i=0; i<fNumPorts.midiIns; ++i)
for (uint8_t i=0; i<fServer.numMidiIns; ++i)
{ {
fMidiInBuffers[i].count = 0; fMidiInBuffers[i].count = 0;
fMidiInBuffers[i].bufferPoolPos = 0; fMidiInBuffers[i].bufferPoolPos = 0;
} }


if (fNumPorts.midiOuts > 0)
if (fServer.numMidiOuts > 0)
{ {
uint8_t* midiData(fShmRtClientControl.data->midiOut); uint8_t* midiData(fShmRtClientControl.data->midiOut);
carla_zeroBytes(midiData, kBridgeRtClientDataMidiOutSize); carla_zeroBytes(midiData, kBridgeRtClientDataMidiOutSize);
std::size_t curMidiDataPos = 0; std::size_t curMidiDataPos = 0;


for (uint8_t i=0; i<fNumPorts.midiOuts; ++i)
for (uint8_t i=0; i<fServer.numMidiOuts; ++i)
{ {
JackMidiPortBuffer& midiPortBuf(fMidiOutBuffers[i]); JackMidiPortBuffer& midiPortBuf(fMidiOutBuffers[i]);


@@ -837,7 +854,13 @@ bool CarlaJackAppClient::handleNonRtData()
break; break;


case kPluginBridgeNonRtClientShowUI: case kPluginBridgeNonRtClientShowUI:
jack_carla_interposed_action(2, nullptr);
break;

case kPluginBridgeNonRtClientHideUI: case kPluginBridgeNonRtClientHideUI:
jack_carla_interposed_action(3, nullptr);
break;

case kPluginBridgeNonRtClientUiParameterChange: case kPluginBridgeNonRtClientUiParameterChange:
case kPluginBridgeNonRtClientUiProgramChange: case kPluginBridgeNonRtClientUiProgramChange:
case kPluginBridgeNonRtClientUiMidiProgramChange: case kPluginBridgeNonRtClientUiMidiProgramChange:
@@ -898,19 +921,19 @@ void CarlaJackAppClient::runNonRealtimeThread()
if (! initSharedMemmory()) if (! initSharedMemmory())
return; return;


if (fNumPorts.midiIns > 0)
if (fServer.numMidiIns > 0)
{ {
fMidiInBuffers = new JackMidiPortBuffer[fNumPorts.midiIns];
fMidiInBuffers = new JackMidiPortBuffer[fServer.numMidiIns];


for (uint8_t i=0; i<fNumPorts.midiIns; ++i)
for (uint8_t i=0; i<fServer.numMidiIns; ++i)
fMidiInBuffers[i].isInput = true; fMidiInBuffers[i].isInput = true;
} }


if (fNumPorts.midiOuts > 0)
if (fServer.numMidiOuts > 0)
{ {
fMidiOutBuffers = new JackMidiPortBuffer[fNumPorts.midiOuts];
fMidiOutBuffers = new JackMidiPortBuffer[fServer.numMidiOuts];


for (uint8_t i=0; i<fNumPorts.midiOuts; ++i)
for (uint8_t i=0; i<fServer.numMidiOuts; ++i)
fMidiOutBuffers[i].isInput = false; fMidiOutBuffers[i].isInput = false;
} }


@@ -999,9 +1022,9 @@ void CarlaJackAppClient::runNonRealtimeThread()
{ {
carla_stderr("CarlaJackAppClient runNonRealtimeThread END - quit itself"); carla_stderr("CarlaJackAppClient runNonRealtimeThread END - quit itself");


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


/* /*
@@ -1014,19 +1037,34 @@ void CarlaJackAppClient::runNonRealtimeThread()
*/ */
} }


fRealtimeThread.signalThreadShouldExit();
if (fRealtimeThread.isThreadRunning())
{
fRealtimeThread.signalThreadShouldExit();

const CarlaMutexLocker cml(fRealtimeThreadMutex);

if (fShmRtClientControl.data != nullptr)
fShmRtClientControl.data->procFlags = 1;
}


clearSharedMemory(); clearSharedMemory();


fRealtimeThread.stopThread(5000); fRealtimeThread.stopThread(5000);


carla_stderr("CarlaJackAppClient run FINISHED");
carla_stderr("CarlaJackAppClient runNonRealtimeThread FINISHED");
} }


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


static CarlaJackAppClient gClient; static CarlaJackAppClient gClient;


static int carla_interposed_callback(int cb_action, void* ptr)
{
return gClient.handleInterposerCallback(cb_action, ptr);
}

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

CARLA_EXPORT CARLA_EXPORT
jack_client_t* jack_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...) jack_client_t* jack_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...)
{ {


+ 20
- 6
source/libjack/libjack.hpp View File

@@ -83,7 +83,7 @@ struct JackMidiPortBuffer {
: count(0), : count(0),
isInput(input), isInput(input),
events(nullptr), events(nullptr),
bufferPoolPos(0),
bufferPoolPos(kBufferPoolSize),
bufferPool(nullptr) {} bufferPool(nullptr) {}


~JackMidiPortBuffer() ~JackMidiPortBuffer()
@@ -99,8 +99,10 @@ struct JackPortState {
void* buffer; void* buffer;
uint index; uint index;
uint flags; uint flags;
bool isMidi;
bool isSystem;
bool isMidi : 1;
bool isSystem : 1;
bool isConnected : 1;
bool unused : 1;


JackPortState() JackPortState()
: name(nullptr), : name(nullptr),
@@ -109,16 +111,19 @@ struct JackPortState {
index(0), index(0),
flags(0), flags(0),
isMidi(false), isMidi(false),
isSystem(false) {}
isSystem(false),
isConnected(false) {}


JackPortState(const char* const cn, const char* const pn, const uint i, const uint f, const bool midi, const bool sys)
JackPortState(const char* const cn, const char* const pn, const uint i, const uint f,
const bool midi, const bool sys, const bool con)
: name(strdup(pn)), : name(strdup(pn)),
fullname(nullptr), fullname(nullptr),
buffer(nullptr), buffer(nullptr),
index(i), index(i),
flags(f), flags(f),
isMidi(midi), isMidi(midi),
isSystem(sys)
isSystem(sys),
isConnected(con)
{ {
char strBuf[STR_MAX+1]; char strBuf[STR_MAX+1];
snprintf(strBuf, STR_MAX, "%s:%s", cn, pn); snprintf(strBuf, STR_MAX, "%s:%s", cn, pn);
@@ -235,6 +240,11 @@ struct JackServerState {
uint32_t bufferSize; uint32_t bufferSize;
double sampleRate; double sampleRate;


uint8_t numAudioIns;
uint8_t numAudioOuts;
uint8_t numMidiIns;
uint8_t numMidiOuts;

bool playing; bool playing;
jack_position_t position; jack_position_t position;


@@ -242,6 +252,10 @@ struct JackServerState {
: jackAppPtr(app), : jackAppPtr(app),
bufferSize(0), bufferSize(0),
sampleRate(0.0), sampleRate(0.0),
numAudioIns(0),
numAudioOuts(0),
numMidiIns(0),
numMidiOuts(0),
playing(false) playing(false)
{ {
carla_zeroStruct(position); carla_zeroStruct(position);


+ 49
- 3
source/libjack/libjack_latency.cpp View File

@@ -45,13 +45,59 @@ void jack_port_get_latency_range(jack_port_t*, jack_latency_callback_mode_t, jac
//int jack_recompute_total_latencies (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; //int jack_recompute_total_latencies (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;


CARLA_EXPORT CARLA_EXPORT
jack_nframes_t jack_port_get_latency(jack_port_t*)
jack_nframes_t jack_port_get_latency(jack_port_t* port)
{ {
JackPortState* const jport = (JackPortState*)port;
CARLA_SAFE_ASSERT_RETURN(jport != nullptr, 0);

if (jport->isMidi || ! jport->isSystem)
return 0;

// TODO
const uint32_t bufferSize = 128;
const uint32_t latencyMultiplier = 3;

if (jport->flags & JackPortIsInput)
return bufferSize*latencyMultiplier;
if (jport->flags & JackPortIsOutput)
return bufferSize;

return 0; return 0;
} }


//jack_nframes_t jack_port_get_total_latency (jack_client_t *client,
// jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT;
CARLA_EXPORT
jack_nframes_t jack_port_get_total_latency(jack_client_t* client, jack_port_t* port)
{
JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 1);

JackPortState* const jport = (JackPortState*)port;
CARLA_SAFE_ASSERT_RETURN(jport != nullptr, 0);

if (jport->isMidi)
return 0;

// TODO
const uint32_t bufferSize = jclient->server.bufferSize;
const uint32_t latencyMultiplier = 3;

if (jport->isSystem)
{
if (jport->flags & JackPortIsInput)
return bufferSize*latencyMultiplier;
if (jport->flags & JackPortIsOutput)
return bufferSize;
}
else
{
if (jport->flags & JackPortIsInput)
return bufferSize;
if (jport->flags & JackPortIsOutput)
return bufferSize*latencyMultiplier;
}

return 0;
}


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




+ 17
- 5
source/libjack/libjack_midi.cpp View File

@@ -53,8 +53,12 @@ void jack_midi_clear_buffer(void* buf)
CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput,); CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput,);


jmidibuf->count = 0; jmidibuf->count = 0;
jmidibuf->bufferPoolPos = 0;
std::memset(jmidibuf->bufferPool, 0, JackMidiPortBuffer::kBufferPoolSize);

if (jmidibuf->bufferPool != nullptr)
{
jmidibuf->bufferPoolPos = 0;
std::memset(jmidibuf->bufferPool, 0, JackMidiPortBuffer::kBufferPoolSize);
}
} }


CARLA_EXPORT CARLA_EXPORT
@@ -75,7 +79,11 @@ jack_midi_data_t* jack_midi_event_reserve(void* buf, jack_nframes_t frame, size_
JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf); JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf);
CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, nullptr);
CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput, nullptr); CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput, nullptr);
CARLA_SAFE_ASSERT_RETURN(size > 0 && size < JackMidiPortBuffer::kMaxEventSize, nullptr);
CARLA_SAFE_ASSERT_RETURN(size < JackMidiPortBuffer::kMaxEventSize, nullptr);

// back jack applicatons, wow...
if (size == 0)
return nullptr;


if (jmidibuf->count >= JackMidiPortBuffer::kMaxEventCount) if (jmidibuf->count >= JackMidiPortBuffer::kMaxEventCount)
return nullptr; return nullptr;
@@ -95,8 +103,12 @@ int jack_midi_event_write(void* buf, jack_nframes_t frame, const jack_midi_data_
{ {
JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf); JackMidiPortBuffer* const jmidibuf((JackMidiPortBuffer*)buf);
CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, EFAULT); CARLA_SAFE_ASSERT_RETURN(jmidibuf != nullptr, EFAULT);
CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput, EFAULT);
CARLA_SAFE_ASSERT_RETURN(size > 0 && size < JackMidiPortBuffer::kMaxEventSize, ENOBUFS);
CARLA_SAFE_ASSERT_RETURN(! jmidibuf->isInput, EINVAL);
CARLA_SAFE_ASSERT_RETURN(size < JackMidiPortBuffer::kMaxEventSize, ENOBUFS);

// back jack applicatons, wow...
if (size == 0)
return EINVAL;


if (jmidibuf->count >= JackMidiPortBuffer::kMaxEventCount) if (jmidibuf->count >= JackMidiPortBuffer::kMaxEventCount)
return ENOBUFS; return ENOBUFS;


+ 7
- 4
source/libjack/libjack_port-searching.cpp View File

@@ -81,13 +81,16 @@ jack_port_t* jack_port_by_name(jack_client_t* client, const char* name)
JackClientState* const jclient = (JackClientState*)client; JackClientState* const jclient = (JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);


const JackServerState& jserver(jclient->server);
const int commonFlags = JackPortIsPhysical|JackPortIsTerminal;

static const JackPortState capturePorts[] = { static const JackPortState capturePorts[] = {
JackPortState("system", "capture_1", 0, JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal, false, true),
JackPortState("system", "capture_2", 1, JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal, false, true),
JackPortState("system", "capture_1", 0, JackPortIsOutput|commonFlags, false, true, jserver.numAudioIns > 0),
JackPortState("system", "capture_2", 1, JackPortIsOutput|commonFlags, false, true, jserver.numAudioIns > 1),
}; };
static const JackPortState playbackPorts[] = { static const JackPortState playbackPorts[] = {
JackPortState("system", "playback_1", 3, JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal, false, true),
JackPortState("system", "playback_2", 4, JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal, false, true),
JackPortState("system", "playback_1", 3, JackPortIsInput|commonFlags, false, true, jserver.numAudioOuts > 0),
JackPortState("system", "playback_2", 4, JackPortIsInput|commonFlags, false, true, jserver.numAudioOuts > 1),
}; };


if (std::strncmp(name, "system:", 7) == 0) if (std::strncmp(name, "system:", 7) == 0)


+ 63
- 16
source/libjack/libjack_ports.cpp View File

@@ -33,11 +33,15 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co
CARLA_SAFE_ASSERT_RETURN(port_name != nullptr && port_name[0] != '\0', nullptr); CARLA_SAFE_ASSERT_RETURN(port_name != nullptr && port_name[0] != '\0', nullptr);
CARLA_SAFE_ASSERT_RETURN(port_type != nullptr && port_type[0] != '\0', nullptr); CARLA_SAFE_ASSERT_RETURN(port_type != nullptr && port_type[0] != '\0', nullptr);


const JackServerState& jserver(jclient->server);

if (std::strcmp(port_type, JACK_DEFAULT_AUDIO_TYPE) == 0) if (std::strcmp(port_type, JACK_DEFAULT_AUDIO_TYPE) == 0)
{ {
if (flags & JackPortIsInput) if (flags & JackPortIsInput)
{ {
JackPortState* const port = new JackPortState(jclient->name, port_name, jclient->audioIns.count(), flags, false, false);
const std::size_t index = jclient->audioIns.count();
JackPortState* const port = new JackPortState(jclient->name, port_name, index, flags,
false, false, index < jserver.numAudioIns);


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


@@ -47,7 +51,9 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co


if (flags & JackPortIsOutput) if (flags & JackPortIsOutput)
{ {
JackPortState* const port = new JackPortState(jclient->name, port_name, jclient->audioOuts.count(), flags, false, false);
const std::size_t index = jclient->audioOuts.count();
JackPortState* const port = new JackPortState(jclient->name, port_name, index, flags,
false, false, index < jserver.numAudioOuts);


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


@@ -63,7 +69,9 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co
{ {
if (flags & JackPortIsInput) if (flags & JackPortIsInput)
{ {
JackPortState* const port = new JackPortState(jclient->name, port_name, jclient->midiIns.count(), flags, true, false);
const std::size_t index = jclient->midiIns.count();
JackPortState* const port = new JackPortState(jclient->name, port_name, index, flags,
true, false, index < jserver.numMidiIns);


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


@@ -73,7 +81,9 @@ jack_port_t* jack_port_register(jack_client_t* client, const char* port_name, co


if (flags & JackPortIsOutput) if (flags & JackPortIsOutput)
{ {
JackPortState* const port = new JackPortState(jclient->name, port_name, jclient->midiOuts.count(), flags, true, false);
const std::size_t index = jclient->midiOuts.count();
JackPortState* const port = new JackPortState(jclient->name, port_name, index, flags,
true, false, index < jserver.numMidiOuts);


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


@@ -216,19 +226,21 @@ uint32_t jack_port_type_id(const jack_port_t* port)
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


CARLA_EXPORT CARLA_EXPORT
int jack_port_is_mine(const jack_client_t* client, const jack_port_t* port)
int jack_port_is_mine(const jack_client_t*, const jack_port_t* port)
{ {
carla_stderr2("%s(%p, %p)", __FUNCTION__, client, port);
JackPortState* const jport = (JackPortState*)port;
CARLA_SAFE_ASSERT_RETURN(jport != nullptr, 0);


return 0;
return jport->isSystem ? 0 : 1;
} }


CARLA_EXPORT CARLA_EXPORT
int jack_port_connected(const jack_port_t* port) int jack_port_connected(const jack_port_t* port)
{ {
carla_stderr2("%s(%p)", __FUNCTION__, port);
JackPortState* const jport = (JackPortState*)port;
CARLA_SAFE_ASSERT_RETURN(jport != nullptr, 0);


return 1;
return jport->isConnected ? 1 : 0;
} }


CARLA_EXPORT CARLA_EXPORT
@@ -259,21 +271,56 @@ const char** jack_port_get_all_connections(const jack_client_t* client, const ja


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


//int jack_port_tie (jack_port_t *src, jack_port_t *dst) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT;
CARLA_EXPORT
int jack_port_tie(jack_port_t* src, jack_port_t* dst)
{
carla_stderr2("%s(%p, %p)", __FUNCTION__, src, dst);
return ENOSYS;
}


//int jack_port_untie (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT;
CARLA_EXPORT
int jack_port_untie(jack_port_t* port)
{
carla_stderr2("%s(%p)", __FUNCTION__, port);
return ENOSYS;
}


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


//int jack_port_set_name (jack_port_t *port, const char *port_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT;
CARLA_EXPORT
int jack_port_set_name(jack_port_t *port, const char *port_name)
{
carla_stderr2("%s(%p, %s)", __FUNCTION__, port, port_name);
return ENOSYS;
}


//int jack_port_rename (jack_client_t* client, jack_port_t *port, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT;
CARLA_EXPORT
int jack_port_rename(jack_client_t* client, jack_port_t *port, const char *port_name)
{
carla_stderr2("%s(%p, %p, %s)", __FUNCTION__, client, port, port_name);
return ENOSYS;
}


//int jack_port_set_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT;
CARLA_EXPORT
int jack_port_set_alias(jack_port_t* port, const char* alias)
{
carla_stderr2("%s(%p, %s)", __FUNCTION__, port, alias);
return ENOSYS;
}


//int jack_port_unset_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT;
CARLA_EXPORT
int jack_port_unset_alias(jack_port_t* port, const char* alias)
{
carla_stderr2("%s(%p, %s)", __FUNCTION__, port, alias);
return ENOSYS;
}


//int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2]) JACK_OPTIONAL_WEAK_EXPORT;
CARLA_EXPORT
int jack_port_get_aliases(const jack_port_t*, char* aliases[2])
{
aliases[0] = aliases[1] = nullptr;
return 0;
}


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




+ 28
- 4
source/libjack/libjack_time.cpp View File

@@ -26,13 +26,22 @@ CARLA_BACKEND_USE_NAMESPACE
CARLA_EXPORT CARLA_EXPORT
jack_nframes_t jack_frame_time(const jack_client_t* client) jack_nframes_t jack_frame_time(const jack_client_t* client)
{ {
JackClientState* const jclient = (JackClientState*)client;
const JackClientState* const jclient = (const JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0); CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);


// FIXME
return jclient->server.position.usecs; return jclient->server.position.usecs;
} }


// jack_nframes_t jack_last_frame_time (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;
CARLA_EXPORT
jack_nframes_t jack_last_frame_time(const jack_client_t* client)
{
const JackClientState* const jclient = (const JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

// FIXME
return jclient->server.position.usecs;
}


// int jack_get_cycle_times(const jack_client_t *client, // int jack_get_cycle_times(const jack_client_t *client,
// jack_nframes_t *current_frames, // jack_nframes_t *current_frames,
@@ -42,8 +51,23 @@ jack_nframes_t jack_frame_time(const jack_client_t* client)


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


// jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT;
CARLA_EXPORT
jack_time_t jack_frames_to_time(const jack_client_t* client, jack_nframes_t frames)
{
const JackClientState* const jclient = (const JackClientState*)client;
CARLA_SAFE_ASSERT_RETURN(jclient != nullptr, 0);

return frames / jclient->server.sampleRate;
}

// jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) JACK_OPTIONAL_WEAK_EXPORT; // jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) JACK_OPTIONAL_WEAK_EXPORT;
// jack_time_t jack_get_time(void) JACK_OPTIONAL_WEAK_EXPORT;

CARLA_EXPORT
jack_time_t jack_get_time(void)
{
timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return t.tv_sec * 1000000 + t.tv_nsec / 1000;
}


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

Loading…
Cancel
Save