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);
305 ComputeTotalLatency(port_index);
310 void JackGraphManager::RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode)
313 JackPort* port = GetPort(port_index);
315 jack_port_id_t dst_index;
317 for (
int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((dst_index = connections[i]) != EMPTY); i++) {
318 AssertPort(dst_index);
319 JackPort* dst_port = GetPort(dst_index);
322 dst_port->GetLatencyRange(mode, &other_latency);
324 if (other_latency.
max > latency.
max)
325 latency.
max = other_latency.
max;
326 if (other_latency.
min < latency.
min)
327 latency.
min = other_latency.
min;
330 if (latency.
min == UINT32_MAX)
333 port->SetLatencyRange(mode, &latency);
336 void JackGraphManager::RecalculateLatency(jack_port_id_t port_index, jack_latency_callback_mode_t mode)
343 RecalculateLatencyAux(port_index, mode);
345 }
while (cur_index != next_index);
351 void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size)
353 jack_log(
"JackGraphManager::SetBufferSize size = %ld", buffer_size);
355 jack_port_id_t port_index;
356 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) {
357 JackPort* port = GetPort(port_index);
359 port->ClearBuffer(buffer_size);
364 jack_port_id_t JackGraphManager::AllocatePortAux(
int refnum,
const char* port_name,
const char* port_type, JackPortFlags flags)
366 jack_port_id_t port_index;
369 for (port_index = FIRST_AVAILABLE_PORT; port_index < fPortMax; port_index++) {
370 JackPort* port = GetPort(port_index);
371 if (!port->IsUsed()) {
372 jack_log(
"JackGraphManager::AllocatePortAux port_index = %ld name = %s type = %s", port_index, port_name, port_type);
373 if (!port->Allocate(refnum, port_name, port_type, flags))
379 return (port_index < fPortMax) ? port_index : NO_PORT;
383 jack_port_id_t JackGraphManager::AllocatePort(
int refnum,
const char* port_name,
const char* port_type, JackPortFlags flags, jack_nframes_t buffer_size)
386 jack_port_id_t port_index = AllocatePortAux(refnum, port_name, port_type, flags);
388 if (port_index != NO_PORT) {
389 JackPort* port = GetPort(port_index);
391 port->ClearBuffer(buffer_size);
394 if (flags & JackPortIsOutput) {
395 res = manager->AddOutputPort(refnum, port_index);
397 res = manager->AddInputPort(refnum, port_index);
402 port_index = NO_PORT;
411 int JackGraphManager::ReleasePort(
int refnum, jack_port_id_t port_index)
414 JackPort* port = GetPort(port_index);
417 if (port->fFlags & JackPortIsOutput) {
418 DisconnectAllOutput(port_index);
419 res = manager->RemoveOutputPort(refnum, port_index);
421 DisconnectAllInput(port_index);
422 res = manager->RemoveInputPort(refnum, port_index);
430 void JackGraphManager::GetInputPorts(
int refnum, jack_int_t* res)
433 const jack_int_t* input = manager->GetInputPorts(refnum);
434 memcpy(res, input,
sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT);
438 void JackGraphManager::GetOutputPorts(
int refnum, jack_int_t* res)
441 const jack_int_t* output = manager->GetOutputPorts(refnum);
442 memcpy(res, output,
sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT);
447 void JackGraphManager::RemoveAllPorts(
int refnum)
449 jack_log(
"JackGraphManager::RemoveAllPorts ref = %ld", refnum);
451 jack_port_id_t port_index;
454 const jack_int_t* input = manager->GetInputPorts(refnum);
455 while ((port_index = input[0]) != EMPTY) {
456 int res = ReleasePort(refnum, port_index);
458 jack_error(
"JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index);
465 const jack_int_t* output = manager->GetOutputPorts(refnum);
466 while ((port_index = output[0]) != EMPTY) {
467 int res = ReleasePort(refnum, port_index);
469 jack_error(
"JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index);
479 void JackGraphManager::DisconnectAllPorts(
int refnum)
482 jack_log(
"JackGraphManager::DisconnectAllPorts ref = %ld", refnum);
485 const jack_int_t* input = manager->GetInputPorts(refnum);
486 for (i = 0; i < PORT_NUM_FOR_CLIENT && input[i] != EMPTY ; i++) {
487 DisconnectAllInput(input[i]);
490 const jack_int_t* output = manager->GetOutputPorts(refnum);
491 for (i = 0; i < PORT_NUM_FOR_CLIENT && output[i] != EMPTY; i++) {
492 DisconnectAllOutput(output[i]);
499 void JackGraphManager::DisconnectAllInput(jack_port_id_t port_index)
501 jack_log(
"JackGraphManager::DisconnectAllInput port_index = %ld", port_index);
504 for (
unsigned int i = 0; i < fPortMax; i++) {
505 if (manager->IsConnected(i, port_index)) {
506 jack_log(
"JackGraphManager::Disconnect i = %ld port_index = %ld", i, port_index);
507 Disconnect(i, port_index);
514 void JackGraphManager::DisconnectAllOutput(jack_port_id_t port_index)
516 jack_log(
"JackGraphManager::DisconnectAllOutput port_index = %ld ", port_index);
519 const jack_int_t* connections = manager->GetConnections(port_index);
520 while (connections[0] != EMPTY) {
521 Disconnect(port_index, connections[0]);
527 int JackGraphManager::DisconnectAll(jack_port_id_t port_index)
529 AssertPort(port_index);
531 JackPort* port = GetPort(port_index);
532 if (port->fFlags & JackPortIsOutput) {
533 DisconnectAllOutput(port_index);
535 DisconnectAllInput(port_index);
541 void JackGraphManager::GetConnections(jack_port_id_t port_index, jack_int_t* res)
544 const jack_int_t* connections = manager->GetConnections(port_index);
545 memcpy(res, connections,
sizeof(jack_int_t) * CONNECTION_NUM_FOR_PORT);
550 void JackGraphManager::Activate(
int refnum)
552 DirectConnect(FREEWHEEL_DRIVER_REFNUM, refnum);
553 DirectConnect(refnum, FREEWHEEL_DRIVER_REFNUM);
562 void JackGraphManager::Deactivate(
int refnum)
565 if (IsDirectConnection(refnum, FREEWHEEL_DRIVER_REFNUM)) {
566 DirectDisconnect(refnum, FREEWHEEL_DRIVER_REFNUM);
568 jack_log(
"JackServer::Deactivate client = %ld was not activated", refnum);
572 if (IsDirectConnection(FREEWHEEL_DRIVER_REFNUM, refnum)) {
573 DirectDisconnect(FREEWHEEL_DRIVER_REFNUM, refnum);
575 jack_log(
"JackServer::Deactivate client = %ld was not activated", refnum);
580 int JackGraphManager::GetInputRefNum(jack_port_id_t port_index)
582 AssertPort(port_index);
584 int res = manager->GetInputRefNum(port_index);
590 int JackGraphManager::GetOutputRefNum(jack_port_id_t port_index)
592 AssertPort(port_index);
594 int res = manager->GetOutputRefNum(port_index);
599 int JackGraphManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
602 jack_log(
"JackGraphManager::Connect port_src = %ld port_dst = %ld", port_src, port_dst);
603 JackPort* src = GetPort(port_src);
604 JackPort* dst = GetPort(port_dst);
607 if (!src->fInUse || !dst->fInUse) {
609 jack_error(
"JackGraphManager::Connect port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName);
611 jack_error(
"JackGraphManager::Connect port_dst = %ld not used name = %s", port_dst, GetPort(port_dst)->fName);
615 if (src->fTypeId != dst->fTypeId) {
616 jack_error(
"JackGraphManager::Connect different port types port_src = %ld port_dst = %ld", port_src, port_dst);
620 if (manager->IsConnected(port_src, port_dst)) {
621 jack_error(
"JackGraphManager::Connect already connected port_src = %ld port_dst = %ld", port_src, port_dst);
626 res = manager->Connect(port_src, port_dst);
628 jack_error(
"JackGraphManager::Connect failed port_src = %ld port_dst = %ld", port_src, port_dst);
631 res = manager->Connect(port_dst, port_src);
633 jack_error(
"JackGraphManager::Connect failed port_dst = %ld port_src = %ld", port_dst, port_src);
637 if (manager->IsLoopPath(port_src, port_dst)) {
638 jack_log(
"JackGraphManager::Connect: LOOP detected");
639 manager->IncFeedbackConnection(port_src, port_dst);
641 manager->IncDirectConnection(port_src, port_dst);
650 int JackGraphManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
653 jack_log(
"JackGraphManager::Disconnect port_src = %ld port_dst = %ld", port_src, port_dst);
654 bool in_use_src = GetPort(port_src)->fInUse;
655 bool in_use_dst = GetPort(port_dst)->fInUse;
658 if (!in_use_src || !in_use_dst) {
660 jack_error(
"JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName);
662 jack_error(
"JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_dst, GetPort(port_dst)->fName);
666 if (!manager->IsConnected(port_src, port_dst)) {
667 jack_error(
"JackGraphManager::Disconnect not connected port_src = %ld port_dst = %ld", port_src, port_dst);
672 res = manager->Disconnect(port_src, port_dst);
674 jack_error(
"JackGraphManager::Disconnect failed port_src = %ld port_dst = %ld", port_src, port_dst);
677 res = manager->Disconnect(port_dst, port_src);
679 jack_error(
"JackGraphManager::Disconnect failed port_dst = %ld port_src = %ld", port_dst, port_src);
683 if (manager->IsFeedbackConnection(port_src, port_dst)) {
684 jack_log(
"JackGraphManager::Disconnect: FEEDBACK removed");
685 manager->DecFeedbackConnection(port_src, port_dst);
687 manager->DecDirectConnection(port_src, port_dst);
696 int JackGraphManager::IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst)
699 return manager->IsConnected(port_src, port_dst);
703 int JackGraphManager::CheckPorts(jack_port_id_t port_src, jack_port_id_t port_dst)
705 JackPort* src = GetPort(port_src);
706 JackPort* dst = GetPort(port_dst);
708 if ((dst->fFlags & JackPortIsInput) == 0) {
709 jack_error(
"Destination port in attempted (dis)connection of %s and %s is not an input port", src->fName, dst->fName);
713 if ((src->fFlags & JackPortIsOutput) == 0) {
714 jack_error(
"Source port in attempted (dis)connection of %s and %s is not an output port", src->fName, dst->fName);
721 int JackGraphManager::GetTwoPorts(
const char* src_name,
const char* dst_name, jack_port_id_t* port_src, jack_port_id_t* port_dst)
723 jack_log(
"JackGraphManager::CheckConnect src_name = %s dst_name = %s", src_name, dst_name);
725 if ((*port_src = GetPort(src_name)) == NO_PORT) {
726 jack_error(
"Unknown source port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
730 if ((*port_dst = GetPort(dst_name)) == NO_PORT) {
731 jack_error(
"Unknown destination port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
739 jack_port_id_t JackGraphManager::GetPort(
const char* name)
741 for (
unsigned int i = 0; i < fPortMax; i++) {
742 JackPort* port = GetPort(i);
743 if (port->IsUsed() && port->NameEquals(name)) {
755 void JackGraphManager::GetConnectionsAux(JackConnectionManager* manager,
const char** res, jack_port_id_t port_index)
757 const jack_int_t* connections = manager->GetConnections(port_index);
762 memset(res, 0,
sizeof(
char*) * CONNECTION_NUM_FOR_PORT);
764 for (i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((index = connections[i]) != EMPTY); i++) {
765 JackPort* port = GetPort(index);
766 res[i] = port->fName;
779 const char** JackGraphManager::GetConnections(jack_port_id_t port_index)
781 const char** res = (
const char**)malloc(
sizeof(
char*) * CONNECTION_NUM_FOR_PORT);
782 UInt16 cur_index, next_index;
791 }
while (cur_index != next_index);
802 void JackGraphManager::GetPortsAux(
const char** matching_ports,
const char* port_name_pattern,
const char* type_name_pattern,
unsigned long flags)
805 regex_t port_regex, type_regex;
807 if (port_name_pattern && port_name_pattern[0]) {
808 regcomp(&port_regex, port_name_pattern, REG_EXTENDED | REG_NOSUB);
810 if (type_name_pattern && type_name_pattern[0]) {
811 regcomp(&type_regex, type_name_pattern, REG_EXTENDED | REG_NOSUB);
815 memset(matching_ports, 0,
sizeof(
char*) * fPortMax);
817 for (
unsigned int i = 0; i < fPortMax; i++) {
818 bool matching =
true;
819 JackPort* port = GetPort(i);
821 if (port->IsUsed()) {
824 if ((port->fFlags & flags) != flags) {
829 if (matching && port_name_pattern && port_name_pattern[0]) {
830 if (regexec(&port_regex, port->GetName(), 0, NULL, 0)) {
834 if (matching && type_name_pattern && type_name_pattern[0]) {
835 if (regexec(&type_regex, port->GetType(), 0, NULL, 0)) {
841 matching_ports[match_cnt++] = port->fName;
846 matching_ports[match_cnt] = 0;
848 if (port_name_pattern && port_name_pattern[0]) {
849 regfree(&port_regex);
851 if (type_name_pattern && type_name_pattern[0]) {
852 regfree(&type_regex);
862 const char** JackGraphManager::GetPorts(
const char* port_name_pattern,
const char* type_name_pattern,
unsigned long flags)
864 const char** res = (
const char**)malloc(
sizeof(
char*) * fPortMax);
865 UInt16 cur_index, next_index;
872 GetPortsAux(res, port_name_pattern, type_name_pattern, flags);
874 }
while (cur_index != next_index);
885 void JackGraphManager::Save(JackConnectionManager* dst)
888 memcpy(dst, manager,
sizeof(JackConnectionManager));
893 void JackGraphManager::Restore(JackConnectionManager* src)
896 memcpy(manager, src,
sizeof(JackConnectionManager));
JackConnectionManager * ReadCurrentState()
Returns the current state : only valid in the RT reader thread.
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,...)
JackConnectionManager * WriteNextStateStart()
Start write operation : setup and returns the next state to update, check for recursive write calls...
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)
const jack_int_t * GetConnections(jack_port_id_t port_index) const
Get the connection port array.
int RequestMonitor(jack_port_id_t port_index, bool onoff)
SERVER_EXPORT void jack_log(const char *fmt,...)