21 #include "JackGraphManager.h" 22 #include "JackConstants.h" 23 #include "JackError.h" 32 static void AssertBufferSize(jack_nframes_t buffer_size)
34 if (buffer_size > BUFFER_SIZE_MAX) {
35 jack_log(
"JackGraphManager::AssertBufferSize frames = %ld", buffer_size);
36 assert(buffer_size <= BUFFER_SIZE_MAX);
40 void JackGraphManager::AssertPort(jack_port_id_t port_index)
42 if (port_index >= fPortMax) {
43 jack_log(
"JackGraphManager::AssertPort port_index = %ld", port_index);
44 assert(port_index < fPortMax);
48 JackGraphManager* JackGraphManager::Allocate(
int port_max)
51 void* shared_ptr = JackShmMem::operator
new(
sizeof(JackGraphManager) + port_max *
sizeof(JackPort));
52 return new(shared_ptr) JackGraphManager(port_max);
55 void JackGraphManager::Destroy(JackGraphManager* manager)
58 manager->~JackGraphManager();
59 JackShmMem::operator
delete(manager);
62 JackGraphManager::JackGraphManager(
int port_max)
64 assert(port_max <= PORT_NUM_MAX);
66 for (
int i = 0; i < port_max; i++) {
67 fPortArray[i].Release();
73 JackPort* JackGraphManager::GetPort(jack_port_id_t port_index)
75 AssertPort(port_index);
76 return &fPortArray[port_index];
79 jack_default_audio_sample_t* JackGraphManager::GetBuffer(jack_port_id_t port_index)
81 return fPortArray[port_index].GetBuffer();
85 void JackGraphManager::InitRefNum(
int refnum)
88 manager->InitRefNum(refnum);
93 void JackGraphManager::RunCurrentGraph()
96 manager->ResetGraph(fClientTiming);
100 bool JackGraphManager::RunNextGraph()
104 manager->ResetGraph(fClientTiming);
109 bool JackGraphManager::IsFinishedGraph()
112 return (manager->GetActivation(FREEWHEEL_DRIVER_REFNUM) == 0);
116 int JackGraphManager::ResumeRefNum(JackClientControl* control, JackSynchro* table)
119 return manager->ResumeRefNum(control, table, fClientTiming);
123 int JackGraphManager::SuspendRefNum(JackClientControl* control, JackSynchro* table,
long usec)
126 return manager->SuspendRefNum(control, table, fClientTiming, usec);
129 void JackGraphManager::TopologicalSort(std::vector<jack_int_t>& sorted)
139 }
while (cur_index != next_index);
143 void JackGraphManager::DirectConnect(
int ref1,
int ref2)
146 manager->DirectConnect(ref1, ref2);
147 jack_log(
"JackGraphManager::ConnectRefNum cur_index = %ld ref1 = %ld ref2 = %ld", CurIndex(fCounter), ref1, ref2);
152 void JackGraphManager::DirectDisconnect(
int ref1,
int ref2)
155 manager->DirectDisconnect(ref1, ref2);
156 jack_log(
"JackGraphManager::DisconnectRefNum cur_index = %ld ref1 = %ld ref2 = %ld", CurIndex(fCounter), ref1, ref2);
161 bool JackGraphManager::IsDirectConnection(
int ref1,
int ref2)
164 return manager->IsDirectConnection(ref1, ref2);
168 void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buffer_size)
170 AssertPort(port_index);
171 AssertBufferSize(buffer_size);
174 JackPort* port = GetPort(port_index);
177 if (!port->IsUsed()) {
178 jack_log(
"JackGraphManager::GetBuffer : port = %ld is released state", port_index);
182 jack_int_t len = manager->Connections(port_index);
185 if (port->fFlags & JackPortIsOutput) {
186 return (port->fTied != NO_PORT) ? GetBuffer(port->fTied, buffer_size) : GetBuffer(port_index);
191 port->ClearBuffer(buffer_size);
192 return port->GetBuffer();
195 }
else if (len == 1) {
196 jack_port_id_t src_index = manager->GetPort(port_index, 0);
199 if (GetPort(src_index)->GetRefNum() == port->GetRefNum()) {
201 buffers[0] = GetBuffer(src_index, buffer_size);
202 port->MixBuffers(buffers, 1, buffer_size);
203 return port->GetBuffer();
206 return GetBuffer(src_index, buffer_size);
212 const jack_int_t* connections = manager->GetConnections(port_index);
213 void* buffers[CONNECTION_NUM_FOR_PORT];
214 jack_port_id_t src_index;
217 for (i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((src_index = connections[i]) != EMPTY); i++) {
218 AssertPort(src_index);
219 buffers[i] = GetBuffer(src_index, buffer_size);
222 port->MixBuffers(buffers, i, buffer_size);
223 return port->GetBuffer();
230 AssertPort(port_index);
231 JackPort* port = GetPort(port_index);
245 if ((port->fFlags & JackPortIsOutput) == 0) {
246 jack_port_id_t src_index;
247 for (
int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((src_index = connections[i]) != EMPTY); i++) {
257 jack_nframes_t JackGraphManager::ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index,
JackConnectionManager* manager,
int hop_count)
260 jack_nframes_t max_latency = 0;
261 jack_port_id_t dst_index;
264 return GetPort(port_index)->GetLatency();
266 for (
int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((dst_index = connections[i]) != EMPTY); i++) {
267 if (src_port_index != dst_index) {
268 AssertPort(dst_index);
269 JackPort* dst_port = GetPort(dst_index);
270 jack_nframes_t this_latency = (dst_port->fFlags & JackPortIsTerminal)
271 ? dst_port->GetLatency()
272 : ComputeTotalLatencyAux(dst_index, port_index, manager, hop_count + 1);
273 max_latency = ((max_latency > this_latency) ? max_latency : this_latency);
277 return max_latency + GetPort(port_index)->GetLatency();
281 int JackGraphManager::ComputeTotalLatency(jack_port_id_t port_index)
285 JackPort* port = GetPort(port_index);
286 AssertPort(port_index);
290 port->fTotalLatency = ComputeTotalLatencyAux(port_index, port_index,
ReadCurrentState(), 0);
292 }
while (cur_index != next_index);
294 jack_log(
"JackGraphManager::GetTotalLatency port_index = %ld total latency = %ld", port_index, port->fTotalLatency);
299 int JackGraphManager::ComputeTotalLatencies()
301 jack_port_id_t port_index;
302 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) {
303 JackPort* port = GetPort(port_index);
304 if (port->IsUsed()) {
305 ComputeTotalLatency(port_index);
311 void JackGraphManager::RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode)
314 JackPort* port = GetPort(port_index);
316 jack_port_id_t dst_index;
318 for (
int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((dst_index = connections[i]) != EMPTY); i++) {
319 AssertPort(dst_index);
320 JackPort* dst_port = GetPort(dst_index);
323 dst_port->GetLatencyRange(mode, &other_latency);
325 if (other_latency.
max > latency.
max) {
326 latency.
max = other_latency.
max;
328 if (other_latency.
min < latency.
min) {
329 latency.
min = other_latency.
min;
333 if (latency.
min == UINT32_MAX) {
337 port->SetLatencyRange(mode, &latency);
340 void JackGraphManager::RecalculateLatency(jack_port_id_t port_index, jack_latency_callback_mode_t mode)
347 RecalculateLatencyAux(port_index, mode);
349 }
while (cur_index != next_index);
355 void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size)
357 jack_log(
"JackGraphManager::SetBufferSize size = %ld", buffer_size);
359 jack_port_id_t port_index;
360 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) {
361 JackPort* port = GetPort(port_index);
362 if (port->IsUsed()) {
363 port->ClearBuffer(buffer_size);
369 jack_port_id_t JackGraphManager::AllocatePortAux(
int refnum,
const char* port_name,
const char* port_type, JackPortFlags flags)
371 jack_port_id_t port_index;
374 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) {
375 JackPort* port = GetPort(port_index);
376 if (!port->IsUsed()) {
377 jack_log(
"JackGraphManager::AllocatePortAux port_index = %ld name = %s type = %s", port_index, port_name, port_type);
378 if (!port->Allocate(refnum, port_name, port_type, flags)) {
385 return (port_index < fPortMax) ? port_index : NO_PORT;
389 jack_port_id_t JackGraphManager::AllocatePort(
int refnum,
const char* port_name,
const char* port_type, JackPortFlags flags, jack_nframes_t buffer_size)
392 jack_port_id_t port_index = AllocatePortAux(refnum, port_name, port_type, flags);
394 if (port_index != NO_PORT) {
395 JackPort* port = GetPort(port_index);
397 port->ClearBuffer(buffer_size);
400 if (flags & JackPortIsOutput) {
408 port_index = NO_PORT;
417 int JackGraphManager::ReleasePort(
int refnum, jack_port_id_t port_index)
420 JackPort* port = GetPort(port_index);
423 if (port->fFlags & JackPortIsOutput) {
424 DisconnectAllOutput(port_index);
427 DisconnectAllInput(port_index);
436 void JackGraphManager::GetInputPorts(
int refnum, jack_int_t* res)
440 memcpy(res, input,
sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT);
444 void JackGraphManager::GetOutputPorts(
int refnum, jack_int_t* res)
448 memcpy(res, output,
sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT);
453 void JackGraphManager::RemoveAllPorts(
int refnum)
455 jack_log(
"JackGraphManager::RemoveAllPorts ref = %ld", refnum);
457 jack_port_id_t port_index;
461 while ((port_index = input[0]) != EMPTY) {
462 int res = ReleasePort(refnum, port_index);
464 jack_error(
"JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index);
472 while ((port_index = output[0]) != EMPTY) {
473 int res = ReleasePort(refnum, port_index);
475 jack_error(
"JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index);
485 void JackGraphManager::DisconnectAllPorts(
int refnum)
488 jack_log(
"JackGraphManager::DisconnectAllPorts ref = %ld", refnum);
492 for (i = 0; i < PORT_NUM_FOR_CLIENT && input[i] != EMPTY ; i++) {
493 DisconnectAllInput(input[i]);
497 for (i = 0; i < PORT_NUM_FOR_CLIENT && output[i] != EMPTY; i++) {
498 DisconnectAllOutput(output[i]);
505 void JackGraphManager::DisconnectAllInput(jack_port_id_t port_index)
507 jack_log(
"JackGraphManager::DisconnectAllInput port_index = %ld", port_index);
510 for (
unsigned int i = 0; i < fPortMax; i++) {
512 jack_log(
"JackGraphManager::Disconnect i = %ld port_index = %ld", i, port_index);
513 Disconnect(i, port_index);
520 void JackGraphManager::DisconnectAllOutput(jack_port_id_t port_index)
522 jack_log(
"JackGraphManager::DisconnectAllOutput port_index = %ld ", port_index);
525 const jack_int_t* connections = manager->
GetConnections(port_index);
526 while (connections[0] != EMPTY) {
527 Disconnect(port_index, connections[0]);
533 int JackGraphManager::DisconnectAll(jack_port_id_t port_index)
535 AssertPort(port_index);
537 JackPort* port = GetPort(port_index);
538 if (port->fFlags & JackPortIsOutput) {
539 DisconnectAllOutput(port_index);
541 DisconnectAllInput(port_index);
547 void JackGraphManager::GetConnections(jack_port_id_t port_index, jack_int_t* res)
550 const jack_int_t* connections = manager->
GetConnections(port_index);
551 memcpy(res, connections,
sizeof(jack_int_t) * CONNECTION_NUM_FOR_PORT);
556 void JackGraphManager::Activate(
int refnum)
558 DirectConnect(FREEWHEEL_DRIVER_REFNUM, refnum);
559 DirectConnect(refnum, FREEWHEEL_DRIVER_REFNUM);
568 void JackGraphManager::Deactivate(
int refnum)
571 if (IsDirectConnection(refnum, FREEWHEEL_DRIVER_REFNUM)) {
572 DirectDisconnect(refnum, FREEWHEEL_DRIVER_REFNUM);
574 jack_log(
"JackServer::Deactivate client = %ld was not activated", refnum);
578 if (IsDirectConnection(FREEWHEEL_DRIVER_REFNUM, refnum)) {
579 DirectDisconnect(FREEWHEEL_DRIVER_REFNUM, refnum);
581 jack_log(
"JackServer::Deactivate client = %ld was not activated", refnum);
586 int JackGraphManager::GetInputRefNum(jack_port_id_t port_index)
588 AssertPort(port_index);
596 int JackGraphManager::GetOutputRefNum(jack_port_id_t port_index)
598 AssertPort(port_index);
605 int JackGraphManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
608 jack_log(
"JackGraphManager::Connect port_src = %ld port_dst = %ld", port_src, port_dst);
613 if (!src->fInUse || !dst->fInUse) {
615 jack_error(
"JackGraphManager::Connect port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName);
617 jack_error(
"JackGraphManager::Connect port_dst = %ld not used name = %s", port_dst, GetPort(port_dst)->fName);
621 if (src->fTypeId != dst->fTypeId) {
622 jack_error(
"JackGraphManager::Connect different port types port_src = %ld port_dst = %ld", port_src, port_dst);
627 jack_error(
"JackGraphManager::Connect already connected port_src = %ld port_dst = %ld", port_src, port_dst);
632 res = manager->
Connect(port_src, port_dst);
634 jack_error(
"JackGraphManager::Connect failed port_src = %ld port_dst = %ld", port_src, port_dst);
637 res = manager->
Connect(port_dst, port_src);
639 jack_error(
"JackGraphManager::Connect failed port_dst = %ld port_src = %ld", port_dst, port_src);
643 if (manager->
IsLoopPath(port_src, port_dst)) {
644 jack_log(
"JackGraphManager::Connect: LOOP detected");
645 manager->IncFeedbackConnection(port_src, port_dst);
656 int JackGraphManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
659 jack_log(
"JackGraphManager::Disconnect port_src = %ld port_dst = %ld", port_src, port_dst);
660 bool in_use_src = GetPort(port_src)->fInUse;
661 bool in_use_dst = GetPort(port_dst)->fInUse;
664 if (!in_use_src || !in_use_dst) {
666 jack_error(
"JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName);
668 jack_error(
"JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_dst, GetPort(port_dst)->fName);
673 jack_error(
"JackGraphManager::Disconnect not connected port_src = %ld port_dst = %ld", port_src, port_dst);
678 res = manager->
Disconnect(port_src, port_dst);
680 jack_error(
"JackGraphManager::Disconnect failed port_src = %ld port_dst = %ld", port_src, port_dst);
683 res = manager->
Disconnect(port_dst, port_src);
685 jack_error(
"JackGraphManager::Disconnect failed port_dst = %ld port_src = %ld", port_dst, port_src);
689 if (manager->IsFeedbackConnection(port_src, port_dst)) {
690 jack_log(
"JackGraphManager::Disconnect: FEEDBACK removed");
691 manager->DecFeedbackConnection(port_src, port_dst);
702 int JackGraphManager::IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst)
709 int JackGraphManager::CheckPorts(jack_port_id_t port_src, jack_port_id_t port_dst)
714 if ((dst->fFlags & JackPortIsInput) == 0) {
715 jack_error(
"Destination port in attempted (dis)connection of %s and %s is not an input port", src->fName, dst->fName);
719 if ((src->fFlags & JackPortIsOutput) == 0) {
720 jack_error(
"Source port in attempted (dis)connection of %s and %s is not an output port", src->fName, dst->fName);
727 int JackGraphManager::GetTwoPorts(
const char* src_name,
const char* dst_name, jack_port_id_t* port_src, jack_port_id_t* port_dst)
729 jack_log(
"JackGraphManager::CheckConnect src_name = %s dst_name = %s", src_name, dst_name);
731 if ((*port_src = GetPort(src_name)) == NO_PORT) {
732 jack_error(
"Unknown source port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
736 if ((*port_dst = GetPort(dst_name)) == NO_PORT) {
737 jack_error(
"Unknown destination port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
745 jack_port_id_t JackGraphManager::GetPort(
const char* name)
747 for (
unsigned int i = 0; i < fPortMax; i++) {
749 if (port->IsUsed() && port->NameEquals(name)) {
761 void JackGraphManager::GetConnectionsAux(
JackConnectionManager* manager,
const char** res, jack_port_id_t port_index)
763 const jack_int_t* connections = manager->
GetConnections(port_index);
768 memset(res, 0,
sizeof(
char*) * CONNECTION_NUM_FOR_PORT);
770 for (i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((index = connections[i]) != EMPTY); i++) {
772 res[i] = port->fName;
785 const char** JackGraphManager::GetConnections(jack_port_id_t port_index)
787 const char** res = (
const char**)malloc(
sizeof(
char*) * CONNECTION_NUM_FOR_PORT);
788 UInt16 cur_index, next_index;
797 }
while (cur_index != next_index);
808 void JackGraphManager::GetPortsAux(
const char** matching_ports,
const char* port_name_pattern,
const char* type_name_pattern,
unsigned long flags)
811 regex_t port_regex, type_regex;
813 if (port_name_pattern && port_name_pattern[0]) {
814 regcomp(&port_regex, port_name_pattern, REG_EXTENDED | REG_NOSUB);
816 if (type_name_pattern && type_name_pattern[0]) {
817 regcomp(&type_regex, type_name_pattern, REG_EXTENDED | REG_NOSUB);
821 memset(matching_ports, 0,
sizeof(
char*) * fPortMax);
823 for (
unsigned int i = 0; i < fPortMax; i++) {
824 bool matching =
true;
827 if (port->IsUsed()) {
830 if ((port->fFlags & flags) != flags) {
835 if (matching && port_name_pattern && port_name_pattern[0]) {
836 if (regexec(&port_regex, port->GetName(), 0, NULL, 0)) {
840 if (matching && type_name_pattern && type_name_pattern[0]) {
841 if (regexec(&type_regex, port->GetType(), 0, NULL, 0)) {
847 matching_ports[match_cnt++] = port->fName;
852 matching_ports[match_cnt] = 0;
854 if (port_name_pattern && port_name_pattern[0]) {
855 regfree(&port_regex);
857 if (type_name_pattern && type_name_pattern[0]) {
858 regfree(&type_regex);
868 const char** JackGraphManager::GetPorts(
const char* port_name_pattern,
const char* type_name_pattern,
unsigned long flags)
870 const char** res = (
const char**)malloc(
sizeof(
char*) * fPortMax);
871 UInt16 cur_index, next_index;
878 GetPortsAux(res, port_name_pattern, type_name_pattern, flags);
880 }
while (cur_index != next_index);
JackConnectionManager * ReadCurrentState()
Returns the current state : only valid in the RT reader thread.
int GetOutputRefNum(jack_port_id_t port_index) const
Get the client refnum of a given ouput port.
int Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
Disconnect port_src from port_dst.
void IncDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
Increment the number of ports between 2 clients, if the 2 clients become connected, then the Activation counter is updated.
void WriteNextStateStop()
Stop write operation : make the next state ready to be used by the RT thread.
SERVER_EXPORT void jack_error(const char *fmt,...)
int RemoveInputPort(int refnum, jack_port_id_t port_index)
Remove an input port from a client.
int AddOutputPort(int refnum, jack_port_id_t port_index)
Add an output port to a client.
int GetInputRefNum(jack_port_id_t port_index) const
Get the client refnum of a given input port.
void DecDirectConnection(jack_port_id_t port_src, jack_port_id_t port_dst)
Decrement the number of ports between 2 clients, if the 2 clients become disconnected, then the Activation counter is updated.
int Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
Connect port_src to port_dst.
JackConnectionManager * WriteNextStateStart()
Start write operation : setup and returns the next state to update, check for recursive write calls...
const jack_int_t * GetOutputPorts(int refnum)
Get the output port array of a given refnum.
bool IsLoopPath(jack_port_id_t port_src, jack_port_id_t port_dst) const
Test is a connection path exists between port_src and port_dst.
UInt16 GetCurrentIndex()
Returns the current state index.
JackConnectionManager * TrySwitchState()
Tries to switch to the next state and returns the new current state (either the same as before if cas...
int RequestMonitor(bool onoff)
int RemoveOutputPort(int refnum, jack_port_id_t port_index)
Remove an output port from a client.
int RequestMonitor(jack_port_id_t port_index, bool onoff)
int AddInputPort(int refnum, jack_port_id_t port_index)
Add an input port to a client.
bool IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst) const
Check if port_src and port_dst are connected.
const jack_int_t * GetConnections(jack_port_id_t port_index) const
Get the connection port array.
SERVER_EXPORT void jack_log(const char *fmt,...)
const jack_int_t * GetInputPorts(int refnum)
Get the input port array of a given refnum.