JackGraphManager.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis
00003 Copyright (C) 2004-2006 Grame  
00004 
00005 This program is free software; you can redistribute it and/or modify
00006   it under the terms of the GNU General Public License as published by
00007   the Free Software Foundation; either version 2 of the License, or
00008   (at your option) any later version.
00009 
00010   This program is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013   GNU General Public License for more details.
00014 
00015   You should have received a copy of the GNU General Public License
00016   along with this program; if not, write to the Free Software
00017   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 #include "JackGraphManager.h"
00021 #include "JackConstants.h"
00022 #include <assert.h>
00023 #include <stdlib.h>
00024 #include <algorithm>
00025 #include <regex.h>
00026 
00027 namespace Jack
00028 {
00029 
00030 static inline jack_nframes_t MAX(jack_nframes_t a, jack_nframes_t b)
00031 {
00032     return (a < b) ? b : a;
00033 }
00034 
00035 static void AssertPort(jack_port_id_t port_index)
00036 {
00037     if (port_index >= PORT_NUM) {
00038         JackLog("JackGraphManager::AssertPort port_index = %ld\n", port_index);
00039         assert(port_index < PORT_NUM);
00040     }
00041 }
00042 
00043 static void AssertBufferSize(jack_nframes_t buffer_size)
00044 {
00045     if (buffer_size > BUFFER_SIZE_MAX) {
00046         JackLog("JackGraphManager::AssertBufferSize frames = %ld\n", buffer_size);
00047         assert(buffer_size <= BUFFER_SIZE_MAX);
00048     }
00049 }
00050 
00051 JackPort* JackGraphManager::GetPort(jack_port_id_t port_index)
00052 {
00053     AssertPort(port_index);
00054     return &fPortArray[port_index];
00055 }
00056 
00057 float* JackGraphManager::GetBuffer(jack_port_id_t port_index)
00058 {
00059     return fPortArray[port_index].GetBuffer();
00060 }
00061 
00062 // RT, client
00063 int JackGraphManager::GetConnectionsNum(jack_port_id_t port_index)
00064 {
00065     JackConnectionManager* manager = ReadCurrentState();
00066     return manager->Connections(port_index);
00067 }
00068 
00069 // Server
00070 void JackGraphManager::InitRefNum(int refnum)
00071 {
00072     JackConnectionManager* manager = WriteNextStateStart();
00073     manager->InitRefNum(refnum);
00074     WriteNextStateStop();
00075 }
00076 
00077 // RT
00078 void JackGraphManager::RunCurrentGraph()
00079 {
00080     JackConnectionManager* manager = ReadCurrentState();
00081     manager->ResetGraph(fClientTiming);
00082 }
00083 
00084 // RT
00085 bool JackGraphManager::RunNextGraph()
00086 {
00087     bool res;
00088     JackConnectionManager* manager = TrySwitchState(&res);
00089     manager->ResetGraph(fClientTiming);
00090     return res;
00091 }
00092 
00093 // RT
00094 bool JackGraphManager::IsFinishedGraph()
00095 {
00096     JackConnectionManager* manager = ReadCurrentState();
00097     return (manager->GetActivation(FREEWHEEL_DRIVER_REFNUM) == 0);
00098 }
00099 
00100 // RT
00101 int JackGraphManager::ResumeRefNum(JackClientControl* control, JackSynchro** table)
00102 {
00103     JackConnectionManager* manager = ReadCurrentState();
00104     return manager->ResumeRefNum(control, table, fClientTiming);
00105 }
00106 
00107 // RT
00108 int JackGraphManager::SuspendRefNum(JackClientControl* control, JackSynchro** table, long usec)
00109 {
00110     JackConnectionManager* manager = ReadCurrentState();
00111     return manager->SuspendRefNum(control, table, fClientTiming, usec);
00112 }
00113 
00114 JackClientTiming* JackGraphManager::GetClientTiming(int ref)
00115 {
00116         return &fClientTiming[ref];
00117 }
00118 
00119 // Server
00120 void JackGraphManager::DirectConnect(int ref1, int ref2)
00121 {
00122     JackConnectionManager* manager = WriteNextStateStart();
00123     manager->DirectConnect(ref1, ref2);
00124     JackLog("JackGraphManager::ConnectRefNum cur_index = %ld ref1 = %ld ref2 = %ld\n", CurIndex(fCounter), ref1, ref2);
00125     WriteNextStateStop();
00126 }
00127 
00128 // Server
00129 void JackGraphManager::DirectDisconnect(int ref1, int ref2)
00130 {
00131     JackConnectionManager* manager = WriteNextStateStart();
00132     manager->DirectDisconnect(ref1, ref2);
00133     JackLog("JackGraphManager::DisconnectRefNum cur_index = %ld ref1 = %ld ref2 = %ld\n", CurIndex(fCounter), ref1, ref2);
00134     WriteNextStateStop();
00135 }
00136 
00137 // Server
00138 bool JackGraphManager::IsDirectConnection(int ref1, int ref2)
00139 {
00140     JackConnectionManager* manager = ReadCurrentState();
00141     return manager->IsDirectConnection(ref1, ref2);
00142 }
00143 
00144 // RT
00145 void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buffer_size)
00146 {
00147     AssertPort(port_index);
00148     AssertBufferSize(buffer_size);
00149 
00150     JackConnectionManager* manager = ReadCurrentState();
00151     JackPort* port = GetPort(port_index);
00152 
00153     if (!port->IsUsed()) {
00154         // This happens when a port has just been unregistered and is still used by the RT code.
00155         JackLog("JackGraphManager::GetBuffer : port = %ld is released state\n", port_index);
00156         return GetBuffer(0); // port_index 0 is not used
00157     }
00158 
00159     // Output port
00160     if (port->fFlags & JackPortIsOutput) {
00161         return (port->fTied != NO_PORT) ? GetBuffer(port->fTied, buffer_size) : GetBuffer(port_index);
00162     }
00163 
00164     // Input port
00165     jack_int_t len = manager->Connections(port_index);
00166 
00167     if (len == 0) {  // No connections: return a zero-filled buffer
00168         float* buffer = GetBuffer(port_index);
00169         memset(buffer, 0, buffer_size * sizeof(float)); // Clear buffer
00170         return buffer;
00171     } else if (len == 1) {       // One connection: use zero-copy mode - just pass the buffer of the connected (output) port.
00172         assert(manager->GetPort(port_index, 0) != port_index); // Check recursion
00173         return GetBuffer(manager->GetPort(port_index, 0), buffer_size);
00174     } else {  // Multiple connections
00175         const jack_int_t* connections = manager->GetConnections(port_index);
00176         float* mixbuffer = GetBuffer(port_index);
00177         jack_port_id_t src_index;
00178         float* buffer;
00179 
00180         // Copy first buffer
00181         src_index = connections[0];
00182         AssertPort(src_index);
00183         buffer = (float*)GetBuffer(src_index, buffer_size);
00184         memcpy(mixbuffer, buffer, buffer_size * sizeof(float));
00185 
00186         // Mix remaining buffers
00187         for (int i = 1; (i < CONNECTION_NUM) && ((src_index = connections[i]) != EMPTY); i++) {
00188             AssertPort(src_index);
00189             buffer = (float*)GetBuffer(src_index, buffer_size);
00190             JackPort::MixBuffer(mixbuffer, buffer, buffer_size);
00191         }
00192         return mixbuffer;
00193     }
00194 }
00195 
00196 int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // Client
00197 {
00198     AssertPort(port_index);
00199     JackPort* port = GetPort(port_index);
00200 
00210     port->RequestMonitor(onoff);
00211 
00212     const jack_int_t* connections = ReadCurrentState()->GetConnections(port_index);
00213     if ((port->fFlags & JackPortIsOutput) == 0) { // ?? Taken from jack, why not (port->fFlags  & JackPortIsInput) ?
00214         jack_port_id_t src_index;
00215         for (int i = 0; (i < CONNECTION_NUM) && ((src_index = connections[i]) != EMPTY); i++) {
00216             // XXX much worse things will happen if there is a feedback loop !!!
00217             RequestMonitor(src_index, onoff);
00218         }
00219     }
00220 
00221     return 0;
00222 }
00223 
00224 jack_nframes_t JackGraphManager::GetTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count)
00225 {
00226     const jack_int_t* connections = manager->GetConnections(port_index);
00227     jack_nframes_t latency = GetPort(port_index)->GetLatency();
00228     jack_nframes_t max_latency = 0;
00229     jack_port_id_t dst_index;
00230 
00231     if (hop_count > 8)
00232         return latency;
00233 
00234     for (int i = 0; (i < CONNECTION_NUM) && ((dst_index = connections[i]) != EMPTY); i++) {
00235         if (src_port_index != dst_index) {
00236             AssertPort(dst_index);
00237             JackPort* dst_port = GetPort(dst_index);
00238             jack_nframes_t this_latency = (dst_port->fFlags & JackPortIsTerminal)
00239                                           ? dst_port->GetLatency()
00240                                           : GetTotalLatencyAux(dst_index, port_index, manager, hop_count + 1);
00241             max_latency = MAX(max_latency, this_latency);
00242         }
00243     }
00244 
00245     return max_latency + latency;
00246 }
00247 
00248 jack_nframes_t JackGraphManager::GetTotalLatency(jack_port_id_t port_index)
00249 {
00250     UInt16 cur_index;
00251     UInt16 next_index;
00252     jack_nframes_t total_latency;
00253     AssertPort(port_index);
00254     JackLog("JackGraphManager::GetTotalLatency port_index = %ld\n", port_index);
00255 
00256     do {
00257         cur_index = GetCurrentIndex();
00258         total_latency = GetTotalLatencyAux(port_index, port_index, ReadCurrentState(), 0);
00259         next_index = GetCurrentIndex();
00260     } while (cur_index != next_index); // Until a coherent state has been read
00261 
00262     return total_latency;
00263 }
00264 
00265 // Server
00266 jack_port_id_t JackGraphManager::AllocatePortAux(int refnum, const char* port_name, JackPortFlags flags)
00267 {
00268     jack_port_id_t port_index;
00269 
00270     // Available ports start at FIRST_AVAILABLE_PORT (= 1), otherwise a port_index of 0 is "seen" as a NULL port by the external API...
00271     for (port_index = FIRST_AVAILABLE_PORT; port_index < PORT_NUM; port_index++) {
00272         JackPort* port = GetPort(port_index);
00273         if (!port->IsUsed()) {
00274             JackLog("JackGraphManager::AllocatePortAux port_index = %ld name = %s\n", port_index, port_name);
00275             port->Allocate(refnum, port_name, flags);
00276             break;
00277         }
00278     }
00279 
00280     return (port_index < PORT_NUM) ? port_index : NO_PORT;
00281 }
00282 
00283 // Server
00284 jack_port_id_t JackGraphManager::AllocatePort(int refnum, const char* port_name, JackPortFlags flags)
00285 {
00286     JackConnectionManager* manager = WriteNextStateStart();
00287     jack_port_id_t port_index = AllocatePortAux(refnum, port_name, flags);
00288 
00289     if (port_index != NO_PORT) {
00290         int res;
00291         if (flags & JackPortIsOutput) {
00292             res = manager->AddOutputPort(refnum, port_index);
00293         } else {
00294             res = manager->AddInputPort(refnum, port_index);
00295         }
00296         if (res < 0) {
00297             JackPort* port = GetPort(port_index);
00298             assert(port);
00299             port->Release();
00300             port_index = NO_PORT;
00301         }
00302     }
00303 
00304     WriteNextStateStop();
00305     return port_index;
00306 }
00307 
00308 // Server
00309 void JackGraphManager::ReleasePort(jack_port_id_t port_index)
00310 {
00311     JackPort* port = GetPort(port_index);
00312     port->Release();
00313 }
00314 
00315 // Server
00316 int JackGraphManager::RemovePort(int refnum, jack_port_id_t port_index)
00317 {
00318     JackConnectionManager* manager = WriteNextStateStart();
00319     JackPort* port = GetPort(port_index);
00320     int res;
00321 
00322     if (port->fFlags & JackPortIsOutput) {
00323         DisconnectAllOutput(port_index);
00324         res = manager->RemoveOutputPort(refnum, port_index);
00325     } else {
00326         DisconnectAllInput(port_index);
00327         res = manager->RemoveInputPort(refnum, port_index);
00328     }
00329 
00330     WriteNextStateStop();
00331     return res;
00332 }
00333 
00334 // Server
00335 void JackGraphManager::RemoveAllPorts(int refnum)
00336 {
00337     JackLog("JackGraphManager::RemoveAllPorts ref = %ld\n", refnum);
00338     JackConnectionManager* manager = WriteNextStateStart();
00339     jack_port_id_t port_index;
00340 
00341     // Warning : RemovePort shift port to left, thus we always remove the first port until the "input" table is empty
00342     const jack_int_t* input = manager->GetInputPorts(refnum);
00343     while ((port_index = input[0]) != EMPTY) {
00344         RemovePort(refnum, port_index);
00345         ReleasePort(port_index);
00346     }
00347 
00348     // Warning : RemovePort shift port to left, thus we always remove the first port until the "output" table is empty
00349     const jack_int_t* output = manager->GetOutputPorts(refnum);
00350     while ((port_index = output[0]) != EMPTY) {
00351         RemovePort(refnum, port_index);
00352         ReleasePort(port_index);
00353     }
00354 
00355     WriteNextStateStop();
00356 }
00357 
00358 // Server
00359 void JackGraphManager::DisconnectAllPorts(int refnum)
00360 {
00361     int i;
00362     JackLog("JackGraphManager::DisconnectAllPorts ref = %ld\n", refnum);
00363     JackConnectionManager* manager = WriteNextStateStart();
00364 
00365     const jack_int_t* input = manager->GetInputPorts(refnum);
00366     for (i = 0; i < PORT_NUM_FOR_CLIENT && input[i] != EMPTY ; i++) {
00367         DisconnectAllInput(input[i]);
00368     }
00369 
00370     const jack_int_t* output = manager->GetOutputPorts(refnum);
00371     for (i = 0; i < PORT_NUM_FOR_CLIENT && output[i] != EMPTY; i++) {
00372         DisconnectAllOutput(output[i]);
00373     }
00374 
00375     WriteNextStateStop();
00376 }
00377 
00378 // Server
00379 void JackGraphManager::DisconnectAllInput(jack_port_id_t port_index)
00380 {
00381     JackLog("JackGraphManager::DisconnectAllInput port_index = %ld \n", port_index);
00382     JackConnectionManager* manager = WriteNextStateStart();
00383 
00384     for (int i = 0; i < PORT_NUM; i++) {
00385         if (manager->IsConnected(i, port_index)) {
00386             JackLog("JackGraphManager::Disconnect i = %ld  port_index = %ld\n", i, port_index);
00387             Disconnect(i, port_index);
00388         }
00389     }
00390     WriteNextStateStop();
00391 }
00392 
00393 // Server
00394 void JackGraphManager::DisconnectAllOutput(jack_port_id_t port_index)
00395 {
00396     JackLog("JackGraphManager::DisconnectAllOutput port_index = %ld \n", port_index);
00397     JackConnectionManager* manager = WriteNextStateStart();
00398 
00399     const jack_int_t* connections = manager->GetConnections(port_index);
00400     while (connections[0] != EMPTY) {
00401         Disconnect(port_index, connections[0]); // Warning : Disconnect shift port to left
00402     }
00403     WriteNextStateStop();
00404 }
00405 
00406 // Server
00407 int JackGraphManager::DisconnectAll(jack_port_id_t port_index)
00408 {
00409     AssertPort(port_index);
00410 
00411     JackPort* port = GetPort(port_index);
00412     if (port->fFlags & JackPortIsOutput) {
00413         DisconnectAllOutput(port_index);
00414     } else {
00415         DisconnectAllInput(port_index);
00416     }
00417     return 0;
00418 }
00419 
00420 // Server
00421 int JackGraphManager::GetInputRefNum(jack_port_id_t port_index)
00422 {
00423     AssertPort(port_index);
00424     JackConnectionManager* manager = WriteNextStateStart();
00425     int res = manager->GetInputRefNum(port_index);
00426     WriteNextStateStop();
00427     return res;
00428 }
00429 
00430 // Server
00431 int JackGraphManager::GetOutputRefNum(jack_port_id_t port_index)
00432 {
00433     AssertPort(port_index);
00434     JackConnectionManager* manager = WriteNextStateStart();
00435     int res = manager->GetOutputRefNum(port_index);
00436     WriteNextStateStop();
00437     return res;
00438 }
00439 
00440 int JackGraphManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
00441 {
00442     JackConnectionManager* manager = WriteNextStateStart();
00443     JackLog("JackGraphManager::Connect port_src = %ld port_dst = %ld\n", port_src, port_dst);
00444     bool in_use_src = GetPort(port_src)->fInUse;
00445     bool in_use_dst = GetPort(port_src)->fInUse;
00446     int res = 0;
00447 
00448     if (!in_use_src || !in_use_dst) {
00449         if (!in_use_src)
00450             jack_error("JackGraphManager::Connect: port_src not %ld used name = %s", port_src, GetPort(port_src)->fName);
00451         if (!in_use_dst)
00452             jack_error("JackGraphManager::Connect: port_dst not %ld used name = %s", port_dst, GetPort(port_dst)->fName);
00453         res = -1;
00454         goto end;
00455     }
00456     if (manager->IsConnected(port_src, port_dst)) {
00457         jack_error("JackGraphManager::Connect already connected port_src = %ld port_dst = %ld", port_src, port_dst);
00458         res = EEXIST;
00459         goto end;
00460     }
00461 
00462     res = manager->Connect(port_src, port_dst);
00463     if (res < 0) {
00464         jack_error("JackGraphManager::Connect failed port_src = %ld port_dst = %ld", port_src, port_dst);
00465         goto end;
00466     }
00467     manager->Connect(port_dst, port_src);
00468     if (res < 0) {
00469         jack_error("JackGraphManager::Connect failed port_src = %ld port_dst = %ld", port_dst, port_src);
00470         goto end;
00471     }
00472 
00473     if (manager->IsLoopPath(port_src, port_dst)) {
00474         JackLog("JackGraphManager::Connect: LOOP detected\n");
00475         manager->IncFeedbackConnection(port_src, port_dst);
00476     } else {
00477         manager->IncDirectConnection(port_src, port_dst);
00478     }
00479 
00480 end:
00481     WriteNextStateStop();
00482     if (res < 0)
00483         jack_error("JackGraphManager::Connect failed port_src = %ld port_dst = %ld", port_dst, port_src);
00484     return res;
00485 }
00486 
00487 // Server
00488 int JackGraphManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
00489 {
00490     JackConnectionManager* manager = WriteNextStateStart();
00491     JackLog("JackGraphManager::Disconnect port_src = %ld port_dst = %ld\n", port_src, port_dst);
00492     bool in_use_src = GetPort(port_src)->fInUse;
00493     bool in_use_dst = GetPort(port_src)->fInUse;
00494     int res = 0;
00495 
00496     if (!in_use_src || !in_use_dst) {
00497         if (!in_use_src)
00498             jack_error("JackGraphManager::Disconnect: port_src not %ld used name = %s", port_src, GetPort(port_src)->fName);
00499         if (!in_use_dst)
00500             jack_error("JackGraphManager::Disconnect: port_src not %ld used name = %s", port_dst, GetPort(port_dst)->fName);
00501         res = -1;
00502         goto end;
00503     }
00504     if (!manager->IsConnected(port_src, port_dst)) {
00505         jack_error("JackGraphManager::Disconnect not connected port_src = %ld port_dst = %ld", port_src, port_dst);
00506         res = -1;
00507         goto end;
00508     }
00509 
00510     manager->Disconnect(port_src, port_dst);
00511     if (res < 0) {
00512         jack_error("JackGraphManager::Disconnect failed port_src = %ld port_dst = %ld", port_src, port_dst);
00513         goto end;
00514     }
00515     manager->Disconnect(port_dst, port_src);
00516     if (res < 0) {
00517         jack_error("JackGraphManager::Disconnect failed port_src = %ld port_dst = %ld", port_dst, port_src);
00518         goto end;
00519     }
00520 
00521     if (manager->IsFeedbackConnection(port_src, port_dst)) {
00522         JackLog("JackGraphManager::Disconnect: FEEDBACK removed\n");
00523         manager->DecFeedbackConnection(port_src, port_dst);
00524     } else {
00525         manager->DecDirectConnection(port_src, port_dst);
00526     }
00527 
00528 end:
00529     WriteNextStateStop();
00530     return res;
00531 }
00532 
00533 // Client
00534 int JackGraphManager::ConnectedTo(jack_port_id_t port_src, const char* port_name)
00535 {
00536     JackLog("JackGraphManager::ConnectedTo port_src = %ld port_name = %s\n", port_src, port_name);
00537     JackConnectionManager* manager = ReadCurrentState();
00538     jack_port_id_t port_dst;
00539 
00540     if ((port_dst = GetPort(port_name)) == NO_PORT) {
00541         jack_error("Unknown destination port port_name = %s", port_name);
00542         return 0;
00543     } else {
00544         return manager->IsConnected(port_src, port_dst);
00545     }
00546 }
00547 
00548 // Server
00549 int JackGraphManager::CheckPort(jack_port_id_t port_index)
00550 {
00551     JackPort* port = GetPort(port_index);
00552 
00553     if (port->fLocked) {
00554         jack_error("Port %s is locked against connection changes", port->fName);
00555         return -1;
00556     } else {
00557         return 0;
00558     }
00559 }
00560 
00561 int JackGraphManager::CheckPorts(jack_port_id_t port_src, jack_port_id_t port_dst)
00562 {
00563     JackPort* src = GetPort(port_src);
00564     JackPort* dst = GetPort(port_dst);
00565 
00566     if ((dst->Flags() & JackPortIsInput) == 0) {
00567         jack_error("Destination port in attempted (dis)connection of %s and %s is not an input port", src->fName, dst->fName);
00568         return -1;
00569     }
00570 
00571     if ((src->Flags() & JackPortIsOutput) == 0) {
00572         jack_error("Source port in attempted (dis)connection of %s and %s is not an output port", src->fName, dst->fName);
00573         return -1;
00574     }
00575 
00576     if (src->fLocked) {
00577         jack_error("Source port %s is locked against connection changes", src->fName);
00578         return -1;
00579     }
00580 
00581     if (dst->fLocked) {
00582         jack_error("Destination port %s is locked against connection changes", dst->fName);
00583         return -1;
00584     }
00585 
00586     return 0;
00587 }
00588 
00589 int JackGraphManager::CheckPorts(const char* src_name, const char* dst_name, jack_port_id_t* port_src, jack_port_id_t* port_dst)
00590 {
00591     JackLog("JackGraphManager::CheckConnect src_name = %s dst_name = %s\n", src_name, dst_name);
00592 
00593     if ((*port_src = GetPort(src_name)) == NO_PORT) {
00594         jack_error("Unknown source port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
00595         return -1;
00596     }
00597 
00598     if ((*port_dst = GetPort(dst_name)) == NO_PORT) {
00599         jack_error("Unknown destination port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
00600         return -1;
00601     }
00602 
00603     return CheckPorts(*port_src, *port_dst);
00604 }
00605 
00606 // Client : port array
00607 jack_port_id_t JackGraphManager::GetPort(const char* name)
00608 {
00609     for (int i = 0; i < PORT_NUM; i++) {
00610         JackPort* port = GetPort(i);
00611         if (port->IsUsed() && strcmp(port->fName, name) == 0)
00612             return i;
00613     }
00614     return NO_PORT;
00615 }
00616 
00621 // Client
00622 void JackGraphManager::GetConnectionsAux(JackConnectionManager* manager, const char** res, jack_port_id_t port_index)
00623 {
00624     const jack_int_t* connections = manager->GetConnections(port_index);
00625     jack_int_t index;
00626     int i;
00627 
00628     for (i = 0; (i < CONNECTION_NUM) && ((index = connections[i]) != EMPTY) ; i++) {
00629         JackPort* port = GetPort(index);
00630         res[i] = port->fName;
00631     }
00632 
00633     res[i] = NULL;
00634 }
00635 
00636 // Client
00637 /*
00638         Use the state returned by ReadCurrentState and check that the state was not changed during the read operation.
00639         The operation is lock-free since there is no intermediate state in the write operation that could cause the
00640         read to loop forever.
00641 */
00642 const char** JackGraphManager::GetConnections(jack_port_id_t port_index)
00643 {
00644     const char** res = (const char**)malloc(sizeof(char*) * (CONNECTION_NUM + 1));
00645     UInt16 cur_index;
00646     UInt16 next_index;
00647     AssertPort(port_index);
00648 
00649     do {
00650         cur_index = GetCurrentIndex();
00651         GetConnectionsAux(ReadCurrentState(), res, port_index);
00652         next_index = GetCurrentIndex();
00653     } while (cur_index != next_index); // Until a coherent state has been read
00654 
00655     return res;
00656 }
00657 
00658 // Client
00659 const char** JackGraphManager::GetPortsAux(const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
00660 {
00661     const char** matching_ports;
00662     unsigned long match_cnt = 0;
00663     regex_t port_regex;
00664     regex_t type_regex;
00665     bool matching;
00666 
00667     if (port_name_pattern && port_name_pattern[0]) {
00668         regcomp(&port_regex, port_name_pattern, REG_EXTENDED | REG_NOSUB);
00669     }
00670     if (type_name_pattern && type_name_pattern[0]) {
00671         regcomp(&type_regex, type_name_pattern, REG_EXTENDED | REG_NOSUB);
00672     }
00673 
00674     matching_ports = (const char**)malloc(sizeof(char*) * PORT_NUM);
00675 
00676     for (int i = 0; i < PORT_NUM; i++) {
00677         matching = true;
00678 
00679         JackPort* port = GetPort(i);
00680 
00681         if (port->IsUsed()) {
00682 
00683             if (flags) {
00684                 if ((port->fFlags & flags) != flags) {
00685                     matching = false;
00686                 }
00687             }
00688 
00689             if (matching && port_name_pattern && port_name_pattern[0]) {
00690                 if (regexec(&port_regex, port->fName, 0, NULL, 0)) {
00691                     matching = false;
00692                 }
00693             }
00694 
00695             /*
00696             if (matching && type_name_pattern && type_name_pattern[0]) {
00697                 jack_port_type_id_t ptid = psp[i].ptype_id;
00698                 if (regexec (&type_regex,engine->port_types[ptid].type_name,0, NULL, 0)) {
00699                     matching = false;
00700                 }
00701             } 
00702             */
00703 
00704             // TO BE IMPROVED
00705             if (matching && type_name_pattern && type_name_pattern[0]) {
00706                 if (regexec(&type_regex, JACK_DEFAULT_AUDIO_TYPE, 0, NULL, 0)) {
00707                     matching = false;
00708                 }
00709             }
00710 
00711             if (matching) {
00712                 matching_ports[match_cnt++] = port->fName;
00713             }
00714         }
00715     }
00716 
00717     matching_ports[match_cnt] = 0;
00718 
00719     if (match_cnt == 0) {
00720         free(matching_ports);
00721         matching_ports = NULL;
00722     }
00723 
00724     return matching_ports;
00725 }
00726 
00727 // Client
00728 /*
00729         Check that the state was not changed during the read operation.
00730         The operation is lock-free since there is no intermediate state in the write operation that could cause the
00731         read to loop forever.
00732 */
00733 const char** JackGraphManager::GetPorts(const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
00734 {
00735     const char** matching_ports = NULL;
00736     UInt16 cur_index;
00737     UInt16 next_index;
00738 
00739     do {
00740         cur_index = GetCurrentIndex();
00741         if (matching_ports) {
00742             free(matching_ports);
00743                         JackLog("JackGraphManager::GetPorts retry... \n");
00744                 }
00745         matching_ports = GetPortsAux(port_name_pattern, type_name_pattern, flags);
00746         next_index = GetCurrentIndex();
00747     } while (cur_index != next_index); // Until a coherent state has been read
00748 
00749     return matching_ports;
00750 }
00751 
00752 // Server
00753 void JackGraphManager::Save(JackConnectionManager* dst)
00754 {
00755     JackConnectionManager* manager = WriteNextStateStart();
00756     memcpy(dst, manager, sizeof(JackConnectionManager));
00757     WriteNextStateStop();
00758 }
00759 
00760 // Server
00761 void JackGraphManager::Restore(JackConnectionManager* src)
00762 {
00763     JackConnectionManager* manager = WriteNextStateStart();
00764     memcpy(manager, src, sizeof(JackConnectionManager));
00765     WriteNextStateStop();
00766 }
00767 
00768 } // end of namespace
00769 
00770 

Generated on Wed Jan 10 11:42:45 2007 for Jackdmp by  doxygen 1.4.5