jack2 icon indicating copy to clipboard operation
jack2 copied to clipboard

[DRAFT] Multi server by same client support

Open twischer-adit opened this issue 5 years ago • 2 comments

These PR add support for Jack "multi client" mode. By multi client I mean allowing to create multiple clients who connect to different servers from one process.

In current Jack version this would result in overwriting synchronization and signalling primitives of shared memory. Each created client would overwrite client before, so that previous client would not be able to accept process and other callbacks and notify server of graph competition.

The patch introduces "global context" reference that holds instance of global and shared memory variables for each created client. This global context reference is then passed to all objects who require it.

Please note this PR disables functionality of metadata - this area is still under development and requires some architectural decisions on how to pass the global pointer to metadata.

It replaces https://github.com/jackaudio/jack2/pull/547

twischer-adit avatar Jun 05 '20 11:06 twischer-adit

This PR introduces the following diff compared to https://github.com/jackaudio/jack2/pull/547

diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp
index 3503a52..2c44dca 100644
--- a/common/JackAPI.cpp
+++ b/common/JackAPI.cpp
@@ -354,6 +354,10 @@ LIB_EXPORT void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t frames)
         return NULL;
     } else {
         JackGlobals *global = JackGlobals::PortGlobal(port);
+        if (!global) {
+            jack_error("jack_port_get_buffer called with invalid context (port %ld)", myport);
+            return NULL;
+        }
         JackGraphManager* manager = global->GetGraphManager();
         return (manager ? manager->GetBuffer(myport, frames) : NULL);
     }
diff --git a/common/JackClient.cpp b/common/JackClient.cpp
index d937464..11e1972 100644
--- a/common/JackClient.cpp
+++ b/common/JackClient.cpp
@@ -39,8 +39,8 @@ namespace Jack
 
 #define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL))
 
-JackClient::JackClient(JackGlobals* globals):fThread(this)
-    , JackGlobalsInterface(globals)
+JackClient::JackClient(JackGlobals* globals):JackGlobalsInterface(globals),
+    fThread(this)
 {
     fSynchroTable = globals->GetSynchroTable();
     fProcess = NULL;
diff --git a/common/JackEngineProfiling.cpp b/common/JackEngineProfiling.cpp
index 595435b..a3084c7 100644
--- a/common/JackEngineProfiling.cpp
+++ b/common/JackEngineProfiling.cpp
@@ -31,12 +31,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 namespace Jack
 {
 
-JackEngineProfiling::JackEngineProfiling(JackGlobals *global):fAudioCycle(0),fMeasuredClient(0)
+JackEngineProfiling::JackEngineProfiling(JackGlobals *global):fGlobal(global), fAudioCycle(0),fMeasuredClient(0)
 {
     jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024));
 
-    fGlobal.SetGlobal(global);
-
     // Force memory page in
     memset(fProfileTable, 0, sizeof(fProfileTable));
 }
@@ -356,7 +354,7 @@ void JackEngineProfiling::Profile(JackClientInterface** table,
     fProfileTable[fAudioCycle].fPrevCycleEnd = prev_cycle_end;
     fProfileTable[fAudioCycle].fAudioCycle = fAudioCycle;
 
-    for (int i = fGlobal.GetGlobal()->GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
+    for (int i = fGlobal->GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
         JackClientInterface* client = table[i];
         JackClientTiming* timing = manager->GetClientTiming(i);
         if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) {
diff --git a/common/JackEngineProfiling.h b/common/JackEngineProfiling.h
index bd1fada..bebb820 100644
--- a/common/JackEngineProfiling.h
+++ b/common/JackEngineProfiling.h
@@ -112,14 +112,14 @@ class SERVER_EXPORT JackEngineProfiling
 
     private:
 
+        JackGlobals* fGlobal;
+
         JackTimingMeasure fProfileTable[TIME_POINTS];
         JackTimingClientInterval fIntervalTable[MEASURED_CLIENTS];
 
         unsigned int fAudioCycle;
         unsigned int fMeasuredClient;
 
-        JackGlobalsInterface fGlobal;
-
         bool CheckClient(const char* name, int cur_point);
 
     public:
diff --git a/common/JackGlobals.h b/common/JackGlobals.h
index 97c8fea..d58dd86 100644
--- a/common/JackGlobals.h
+++ b/common/JackGlobals.h
@@ -168,7 +168,11 @@ class JackGlobals
                 return NULL;
             }
 
-            return (jack_port_t*) ((context_id << PORT_SERVER_CONTEXT_SHIFT) | port_id);
+            /* cast to uintptr_t required to avoid [-Wint-to-pointer-cast] warning */
+            const uintptr_t port = ((context_id << PORT_SERVER_CONTEXT_SHIFT) | port_id);
+            return (jack_port_t*)port;
+
+
         }
 
 };
diff --git a/common/JackLibAPI.cpp b/common/JackLibAPI.cpp
index 4e81b33..ba8af64 100644
--- a/common/JackLibAPI.cpp
+++ b/common/JackLibAPI.cpp
@@ -235,7 +235,7 @@ LIB_EXPORT int jack_set_property(jack_client_t* ext_client, jack_uuid_t subject,
     JackGlobals::CheckContext("jack_set_property");
 
     jack_error("jack_set_property is not implemented");
-    abort();
+    return -1;
 
 //    JackClient* client = (JackClient*)ext_client;
 //    jack_log("jack_set_property ext_client %x client %x ", ext_client, client);
@@ -253,7 +253,7 @@ LIB_EXPORT int jack_get_property(jack_uuid_t subject, const char* key, char** va
     JackGlobals::CheckContext("jack_get_property");
 
     jack_error("jack_get_property is not implemented");
-    abort();
+    return -1;
 
 //    JackMetadata* metadata = GetMetadata();
 //    return (metadata ? metadata->GetProperty(subject, key, value, type) : -1);
@@ -264,7 +264,7 @@ LIB_EXPORT void jack_free_description(jack_description_t* desc, int free_actual_
     JackGlobals::CheckContext("jack_free_description");
 
     jack_error("jack_free_description is not implemented");
-    abort();
+    return;
 
 //    JackMetadata* metadata = GetMetadata();
 //    if (metadata)
@@ -276,7 +276,7 @@ LIB_EXPORT int jack_get_properties(jack_uuid_t subject, jack_description_t* desc
     JackGlobals::CheckContext("jack_get_properties");
 
     jack_error("jack_get_properties is not implemented");
-    abort();
+    return -1;
 
 //    JackMetadata* metadata = GetMetadata();
 //    return (metadata ? metadata->GetProperties(subject, desc) : -1);
@@ -287,7 +287,7 @@ LIB_EXPORT int jack_get_all_properties(jack_description_t** descriptions)
     JackGlobals::CheckContext("jack_get_all_properties");
 
     jack_error("jack_get_all_properties is not implemented");
-    abort();
+    return -1;
 
 //    JackMetadata* metadata = GetMetadata();
 //    return (metadata ? metadata->GetAllProperties(descriptions) : -1);
@@ -298,7 +298,7 @@ LIB_EXPORT int jack_remove_property(jack_client_t* ext_client, jack_uuid_t subje
     JackGlobals::CheckContext("jack_remove_property");
 
     jack_error("jack_remove_property is not implemented");
-    abort();
+    return -1;
 
 //    JackClient* client = (JackClient*)ext_client;
 //    jack_log("jack_remove_property ext_client %x client %x ", ext_client, client);
@@ -316,7 +316,7 @@ LIB_EXPORT int jack_remove_properties(jack_client_t* ext_client, jack_uuid_t sub
     JackGlobals::CheckContext("jack_remove_properties");
 
     jack_error("jack_remove_properties is not implemented");
-    abort();
+    return -1;
 
 //    JackClient* client = (JackClient*)ext_client;
 //    jack_log("jack_remove_properties ext_client %x client %x ", ext_client, client);
@@ -334,7 +334,7 @@ LIB_EXPORT int jack_remove_all_properties(jack_client_t* ext_client)
     JackGlobals::CheckContext("jack_remove_all_properties");
 
     jack_error("jack_remove_all_properties is not implemented");
-    abort();
+    return -1;
 
 //    JackClient* client = (JackClient*)ext_client;
 //    jack_log("jack_remove_all_properties ext_client %x client %x ", ext_client, client);
diff --git a/posix/JackSocketClientChannel.h b/posix/JackSocketClientChannel.h
index eba9a05..120d303 100644
--- a/posix/JackSocketClientChannel.h
+++ b/posix/JackSocketClientChannel.h
@@ -29,7 +29,6 @@ namespace Jack
 {
 
 class JackClient;
-class JackGlobal;
 
 /*!
 \brief JackClientChannel using sockets.

This changes are mainly required to solve compiler warnings.

twischer-adit avatar Jun 05 '20 12:06 twischer-adit

First of all, thanks a lot for the all the small patches.

Please set this specific PR as draft though, since it is not complete.

One thing to note about meta-data, is that it is not implemented on the server-side, only client-side. So external clients can change and read meta-data, but internal clients cannot. This is a flaw in the original design from JACK1, which got adopted into JACK2 (so not considered a regression).

falkTX avatar Jun 06 '20 08:06 falkTX