JackGraphManager.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis
00003 Copyright (C) 2004-2008 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         port->ClearBuffer(buffer_size);
00169         return port->GetBuffer();
00170     } else if (len == 1) {       // One connection: use zero-copy mode - just pass the buffer of the connected (output) port.
00171         assert(manager->GetPort(port_index, 0) != port_index); // Check recursion
00172         return GetBuffer(manager->GetPort(port_index, 0), buffer_size);
00173     } else {  // Multiple connections
00174         
00175         const jack_int_t* connections = manager->GetConnections(port_index);
00176                 void* buffers[CONNECTION_NUM];
00177                 jack_port_id_t src_index;
00178                 int i;
00179         
00180                 for (i = 0; (i < CONNECTION_NUM) && ((src_index = connections[i]) != EMPTY); i++) {
00181             AssertPort(src_index);
00182                         buffers[i] = GetBuffer(src_index, buffer_size);
00183         }
00184                 
00185                 JackPort* port = GetPort(port_index);
00186                 port->MixBuffers(buffers, i, buffer_size);
00187         return port->GetBuffer();
00188     }
00189 }
00190 
00191 // Server
00192 int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // Client
00193 {
00194     AssertPort(port_index);
00195     JackPort* port = GetPort(port_index);
00196 
00206     port->RequestMonitor(onoff);
00207 
00208     const jack_int_t* connections = ReadCurrentState()->GetConnections(port_index);
00209     if ((port->fFlags & JackPortIsOutput) == 0) { // ?? Taken from jack, why not (port->fFlags  & JackPortIsInput) ?
00210         jack_port_id_t src_index;
00211         for (int i = 0; (i < CONNECTION_NUM) && ((src_index = connections[i]) != EMPTY); i++) {
00212             // XXX much worse things will happen if there is a feedback loop !!!
00213             RequestMonitor(src_index, onoff);
00214         }
00215     }
00216 
00217     return 0;
00218 }
00219 
00220 // Client
00221 jack_nframes_t JackGraphManager::ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count)
00222 {
00223     const jack_int_t* connections = manager->GetConnections(port_index);
00224     jack_nframes_t max_latency = 0;
00225     jack_port_id_t dst_index;
00226 
00227     if (hop_count > 8)
00228         return GetPort(port_index)->GetLatency();
00229         
00230     for (int i = 0; (i < CONNECTION_NUM) && ((dst_index = connections[i]) != EMPTY); i++) {
00231         if (src_port_index != dst_index) {
00232                 AssertPort(dst_index);
00233             JackPort* dst_port = GetPort(dst_index);
00234             jack_nframes_t this_latency = (dst_port->fFlags & JackPortIsTerminal)
00235                                           ? dst_port->GetLatency()
00236                                           : ComputeTotalLatencyAux(dst_index, port_index, manager, hop_count + 1);
00237             max_latency = MAX(max_latency, this_latency);
00238         }
00239     }
00240         
00241     return max_latency + GetPort(port_index)->GetLatency();
00242 }
00243 
00244 // Client
00245 int JackGraphManager::ComputeTotalLatency(jack_port_id_t port_index)
00246 {
00247     UInt16 cur_index;
00248     UInt16 next_index;
00249         JackPort* port = GetPort(port_index);
00250     AssertPort(port_index);
00251   
00252     do {
00253         cur_index = GetCurrentIndex();
00254         port->fTotalLatency = ComputeTotalLatencyAux(port_index, port_index, ReadCurrentState(), 0);
00255         next_index = GetCurrentIndex();
00256     } while (cur_index != next_index); // Until a coherent state has been read
00257         
00258         JackLog("JackGraphManager::GetTotalLatency port_index = %ld total latency = %ld\n", port_index, port->fTotalLatency);
00259         return 0;
00260 }
00261 
00262 // Client
00263 int JackGraphManager::ComputeTotalLatencies()
00264 {
00265         jack_port_id_t port_index;
00266         for (port_index = FIRST_AVAILABLE_PORT; port_index < PORT_NUM; port_index++) {
00267         JackPort* port = GetPort(port_index);
00268         if (port->IsUsed()) 
00269                         ComputeTotalLatency(port_index);
00270         }
00271         return 0;
00272 }
00273 
00274 // Server
00275 void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size)
00276 {
00277     JackLock lock(this);
00278     JackLog("JackGraphManager::SetBufferSize size = %ld\n", (long int)buffer_size);
00279    
00280         jack_port_id_t port_index;
00281     for (port_index = FIRST_AVAILABLE_PORT; port_index < PORT_NUM; port_index++) {
00282         JackPort* port = GetPort(port_index);
00283         if (port->IsUsed())
00284             port->ClearBuffer(buffer_size);
00285     }
00286 }
00287 
00288 // Server
00289 jack_port_id_t JackGraphManager::AllocatePortAux(int refnum, const char* port_name, const char* port_type, JackPortFlags flags)
00290 {
00291     jack_port_id_t port_index;
00292 
00293     // Available ports start at FIRST_AVAILABLE_PORT (= 1), otherwise a port_index of 0 is "seen" as a NULL port by the external API...
00294     for (port_index = FIRST_AVAILABLE_PORT; port_index < PORT_NUM; port_index++) {
00295         JackPort* port = GetPort(port_index);
00296         if (!port->IsUsed()) {
00297             JackLog("JackGraphManager::AllocatePortAux port_index = %ld name = %s type = %s\n", port_index, port_name, port_type);
00298             if (!port->Allocate(refnum, port_name, port_type, flags))
00299                                 return NO_PORT;
00300             break;
00301         }
00302     }
00303 
00304     return (port_index < PORT_NUM) ? port_index : NO_PORT;
00305 }
00306 
00307 // Server
00308 jack_port_id_t JackGraphManager::AllocatePort(int refnum, const char* port_name, const char* port_type, JackPortFlags flags, jack_nframes_t buffer_size)
00309 {
00310         JackLock lock(this);
00311     JackConnectionManager* manager = WriteNextStateStart();
00312     jack_port_id_t port_index = AllocatePortAux(refnum, port_name, port_type, flags);
00313 
00314     if (port_index != NO_PORT) {
00315         JackPort* port = GetPort(port_index);
00316         assert(port);
00317         port->ClearBuffer(buffer_size);
00318 
00319         int res;
00320         if (flags & JackPortIsOutput) {
00321             res = manager->AddOutputPort(refnum, port_index);
00322         } else {
00323             res = manager->AddInputPort(refnum, port_index);
00324         }
00325                 // Insertion failure
00326         if (res < 0) {
00327             port->Release();
00328             port_index = NO_PORT;
00329         }
00330     }
00331 
00332     WriteNextStateStop();
00333     return port_index;
00334 }
00335 
00336 // Server
00337 int JackGraphManager::ReleasePort(int refnum, jack_port_id_t port_index)
00338 {
00339         JackLock lock(this);
00340     JackConnectionManager* manager = WriteNextStateStart();
00341     JackPort* port = GetPort(port_index);
00342     int res;
00343 
00344     if (port->fFlags & JackPortIsOutput) {
00345         DisconnectAllOutput(port_index);
00346         res = manager->RemoveOutputPort(refnum, port_index);
00347     } else {
00348         DisconnectAllInput(port_index);
00349         res = manager->RemoveInputPort(refnum, port_index);
00350     }
00351 
00352         port->Release();
00353     WriteNextStateStop();
00354     return res;
00355 }
00356 
00357 void JackGraphManager::GetInputPorts(int refnum, jack_int_t* res)
00358 {
00359         JackConnectionManager* manager = WriteNextStateStart();
00360         const jack_int_t* input = manager->GetInputPorts(refnum);
00361         memcpy(res, input, sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT);
00362         WriteNextStateStop();
00363 }
00364 
00365 void JackGraphManager::GetOutputPorts(int refnum, jack_int_t* res)
00366 {
00367         JackConnectionManager* manager = WriteNextStateStart();
00368         const jack_int_t* output = manager->GetOutputPorts(refnum);
00369         memcpy(res, output, sizeof(jack_int_t) * PORT_NUM_FOR_CLIENT);
00370         WriteNextStateStop();
00371 }
00372 
00373 // Server
00374 void JackGraphManager::RemoveAllPorts(int refnum)
00375 {
00376     JackLog("JackGraphManager::RemoveAllPorts ref = %ld\n", refnum);
00377     JackConnectionManager* manager = WriteNextStateStart();
00378     jack_port_id_t port_index;
00379 
00380     // Warning : RemovePort shift port to left, thus we always remove the first port until the "input" table is empty
00381     const jack_int_t* input = manager->GetInputPorts(refnum);
00382     while ((port_index = input[0]) != EMPTY) {
00383         ReleasePort(refnum, port_index);
00384     }
00385 
00386     // Warning : RemovePort shift port to left, thus we always remove the first port until the "output" table is empty
00387     const jack_int_t* output = manager->GetOutputPorts(refnum);
00388     while ((port_index = output[0]) != EMPTY) {
00389         ReleasePort(refnum, port_index);
00390     }
00391 
00392     WriteNextStateStop();
00393 }
00394 
00395 // Server
00396 void JackGraphManager::DisconnectAllPorts(int refnum)
00397 {
00398     int i;
00399     JackLog("JackGraphManager::DisconnectAllPorts ref = %ld\n", refnum);
00400     JackConnectionManager* manager = WriteNextStateStart();
00401 
00402     const jack_int_t* input = manager->GetInputPorts(refnum);
00403     for (i = 0; i < PORT_NUM_FOR_CLIENT && input[i] != EMPTY ; i++) {
00404         DisconnectAllInput(input[i]);
00405     }
00406 
00407     const jack_int_t* output = manager->GetOutputPorts(refnum);
00408     for (i = 0; i < PORT_NUM_FOR_CLIENT && output[i] != EMPTY; i++) {
00409         DisconnectAllOutput(output[i]);
00410     }
00411 
00412     WriteNextStateStop();
00413 }
00414 
00415 // Server
00416 void JackGraphManager::DisconnectAllInput(jack_port_id_t port_index)
00417 {
00418     JackLog("JackGraphManager::DisconnectAllInput port_index = %ld \n", port_index);
00419     JackConnectionManager* manager = WriteNextStateStart();
00420 
00421     for (int i = 0; i < PORT_NUM; i++) {
00422         if (manager->IsConnected(i, port_index)) {
00423                         JackLog("JackGraphManager::Disconnect i = %ld  port_index = %ld\n", i, port_index);
00424             Disconnect(i, port_index);
00425         }
00426     }
00427     WriteNextStateStop();
00428 }
00429 
00430 // Server
00431 void JackGraphManager::DisconnectAllOutput(jack_port_id_t port_index)
00432 {
00433     JackLog("JackGraphManager::DisconnectAllOutput port_index = %ld \n", port_index);
00434     JackConnectionManager* manager = WriteNextStateStart();
00435 
00436     const jack_int_t* connections = manager->GetConnections(port_index);
00437         while (connections[0] != EMPTY) {
00438                 Disconnect(port_index, connections[0]); // Warning : Disconnect shift port to left
00439     }
00440     WriteNextStateStop();
00441 }
00442 
00443 // Server
00444 int JackGraphManager::DisconnectAll(jack_port_id_t port_index)
00445 {
00446     AssertPort(port_index);
00447 
00448     JackPort* port = GetPort(port_index);
00449     if (port->fFlags & JackPortIsOutput) {
00450                 DisconnectAllOutput(port_index);
00451     } else {
00452                 DisconnectAllInput(port_index);
00453     }
00454     return 0;
00455 }
00456 
00457 // Server
00458 void JackGraphManager::GetConnections(jack_port_id_t port_index, jack_int_t* res)
00459 {
00460         JackConnectionManager* manager = WriteNextStateStart();
00461         const jack_int_t* connections = manager->GetConnections(port_index);
00462         memcpy(res, connections, sizeof(jack_int_t) * CONNECTION_NUM);
00463         WriteNextStateStop();
00464 }
00465 
00466 // Server
00467 void JackGraphManager::Activate(int refnum)
00468 {
00469         DirectConnect(FREEWHEEL_DRIVER_REFNUM, refnum);
00470     DirectConnect(refnum, FREEWHEEL_DRIVER_REFNUM);
00471 }
00472 
00473 /*
00474         Disconnection from the FW must be done in last otherwise an intermediate "unconnected"
00475         (thus unactivated) state may happen where the client is still checked for its end.
00476 */
00477 
00478 // Server
00479 void JackGraphManager::Deactivate(int refnum)
00480 {
00481         DisconnectAllPorts(refnum);
00482         
00483         // Disconnect only when needed
00484     if (IsDirectConnection(refnum, FREEWHEEL_DRIVER_REFNUM)) {
00485         DirectDisconnect(refnum, FREEWHEEL_DRIVER_REFNUM);
00486     } else {
00487         JackLog("JackServer::Deactivate: client = %ld was not activated \n", refnum);
00488     }
00489 
00490         // Disconnect only when needed
00491     if (IsDirectConnection(FREEWHEEL_DRIVER_REFNUM, refnum)) {
00492         DirectDisconnect(FREEWHEEL_DRIVER_REFNUM, refnum);
00493     } else {
00494         JackLog("JackServer::Deactivate: client = %ld was not activated \n", refnum);
00495     }
00496 }
00497 
00498 // Server
00499 int JackGraphManager::GetInputRefNum(jack_port_id_t port_index)
00500 {
00501     AssertPort(port_index);
00502     JackConnectionManager* manager = WriteNextStateStart();
00503     int res = manager->GetInputRefNum(port_index);
00504     WriteNextStateStop();
00505     return res;
00506 }
00507 
00508 // Server
00509 int JackGraphManager::GetOutputRefNum(jack_port_id_t port_index)
00510 {
00511     AssertPort(port_index);
00512     JackConnectionManager* manager = WriteNextStateStart();
00513     int res = manager->GetOutputRefNum(port_index);
00514     WriteNextStateStop();
00515     return res;
00516 }
00517 
00518 int JackGraphManager::Connect(jack_port_id_t port_src, jack_port_id_t port_dst)
00519 {
00520     JackConnectionManager* manager = WriteNextStateStart();
00521     JackLog("JackGraphManager::Connect port_src = %ld port_dst = %ld\n", port_src, port_dst);
00522     JackPort* src = GetPort(port_src);
00523     JackPort* dst = GetPort(port_dst);
00524     int res = 0;
00525 
00526     if (!src->fInUse || !dst->fInUse) {
00527         if (!src->fInUse)
00528             jack_error("JackGraphManager::Connect: port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName);
00529         if (!dst->fInUse)
00530             jack_error("JackGraphManager::Connect: port_dst = %ld not used name = %s", port_dst, GetPort(port_dst)->fName);
00531         res = -1;
00532         goto end;
00533     }
00534     if (src->fTypeId != dst->fTypeId) {
00535                 jack_error("JackGraphManager::Connect: different port types: port_src = %ld port_dst = %ld", port_src, port_dst);
00536             res = -1;
00537             goto end;
00538     }
00539     if (manager->IsConnected(port_src, port_dst)) {
00540         jack_error("JackGraphManager::Connect already connected port_src = %ld port_dst = %ld", port_src, port_dst);
00541         res = EEXIST;
00542         goto end;
00543     }
00544 
00545     res = manager->Connect(port_src, port_dst);
00546     if (res < 0) {
00547         jack_error("JackGraphManager::Connect failed port_src = %ld port_dst = %ld", port_src, port_dst);
00548         goto end;
00549     }
00550     manager->Connect(port_dst, port_src);
00551     if (res < 0) {
00552         jack_error("JackGraphManager::Connect failed port_dst = %ld port_src = %ld", port_dst, port_src);
00553         goto end;
00554     }
00555 
00556     if (manager->IsLoopPath(port_src, port_dst)) {
00557         JackLog("JackGraphManager::Connect: LOOP detected\n");
00558         manager->IncFeedbackConnection(port_src, port_dst);
00559     } else {
00560         manager->IncDirectConnection(port_src, port_dst);
00561     }
00562 
00563 end:
00564     WriteNextStateStop();
00565     return res;
00566 }
00567 
00568 // Server
00569 int JackGraphManager::Disconnect(jack_port_id_t port_src, jack_port_id_t port_dst)
00570 {
00571     JackConnectionManager* manager = WriteNextStateStart();
00572     JackLog("JackGraphManager::Disconnect port_src = %ld port_dst = %ld\n", port_src, port_dst);
00573     bool in_use_src = GetPort(port_src)->fInUse;
00574     bool in_use_dst = GetPort(port_dst)->fInUse;
00575     int res = 0;
00576 
00577     if (!in_use_src || !in_use_dst) {
00578         if (!in_use_src)
00579             jack_error("JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_src, GetPort(port_src)->fName);
00580         if (!in_use_dst)
00581             jack_error("JackGraphManager::Disconnect: port_src = %ld not used name = %s", port_dst, GetPort(port_dst)->fName);
00582         res = -1;
00583         goto end;
00584     }
00585     if (!manager->IsConnected(port_src, port_dst)) {
00586         jack_error("JackGraphManager::Disconnect not connected port_src = %ld port_dst = %ld", port_src, port_dst);
00587         res = -1;
00588         goto end;
00589     }
00590 
00591     manager->Disconnect(port_src, port_dst);
00592     if (res < 0) {
00593         jack_error("JackGraphManager::Disconnect failed port_src = %ld port_dst = %ld", port_src, port_dst);
00594         goto end;
00595     }
00596     manager->Disconnect(port_dst, port_src);
00597     if (res < 0) {
00598         jack_error("JackGraphManager::Disconnect failed port_dst = %ld port_src = %ld", port_dst, port_src);
00599         goto end;
00600     }
00601 
00602     if (manager->IsFeedbackConnection(port_src, port_dst)) {
00603         JackLog("JackGraphManager::Disconnect: FEEDBACK removed\n");
00604         manager->DecFeedbackConnection(port_src, port_dst);
00605     } else {
00606         manager->DecDirectConnection(port_src, port_dst);
00607     }
00608 
00609 end:
00610     WriteNextStateStop();
00611     return res;
00612 }
00613 
00614 // Client
00615 int JackGraphManager::IsConnected(jack_port_id_t port_src, jack_port_id_t port_dst)
00616 {
00617     JackConnectionManager* manager = ReadCurrentState();
00618         return manager->IsConnected(port_src, port_dst);
00619 }
00620 
00621 // Server
00622 int JackGraphManager::CheckPorts(jack_port_id_t port_src, jack_port_id_t port_dst)
00623 {
00624     JackPort* src = GetPort(port_src);
00625     JackPort* dst = GetPort(port_dst);
00626 
00627     if ((dst->fFlags & JackPortIsInput) == 0) {
00628         jack_error("Destination port in attempted (dis)connection of %s and %s is not an input port", src->fName, dst->fName);
00629         return -1;
00630     }
00631 
00632     if ((src->fFlags & JackPortIsOutput) == 0) {
00633         jack_error("Source port in attempted (dis)connection of %s and %s is not an output port", src->fName, dst->fName);
00634         return -1;
00635     }
00636 
00637     return 0;
00638 }
00639 
00640 int JackGraphManager::CheckPorts(const char* src_name, const char* dst_name, jack_port_id_t* port_src, jack_port_id_t* port_dst)
00641 {
00642     JackLog("JackGraphManager::CheckConnect src_name = %s dst_name = %s\n", src_name, dst_name);
00643 
00644     if ((*port_src = GetPort(src_name)) == NO_PORT) {
00645         jack_error("Unknown source port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
00646         return -1;
00647     }
00648 
00649     if ((*port_dst = GetPort(dst_name)) == NO_PORT) {
00650         jack_error("Unknown destination port in attempted (dis)connection src_name [%s] dst_name [%s]", src_name, dst_name);
00651         return -1;
00652     }
00653 
00654     return CheckPorts(*port_src, *port_dst);
00655 }
00656 
00657 // Client : port array
00658 jack_port_id_t JackGraphManager::GetPort(const char* name)
00659 {
00660     for (int i = 0; i < PORT_NUM; i++) {
00661         JackPort* port = GetPort(i);
00662         if (port->IsUsed() && port->NameEquals(name))
00663             return i;
00664     }
00665     return NO_PORT;
00666 }
00667 
00672 // Client
00673 void JackGraphManager::GetConnectionsAux(JackConnectionManager* manager, const char** res, jack_port_id_t port_index)
00674 {
00675     const jack_int_t* connections = manager->GetConnections(port_index);
00676     jack_int_t index;
00677     int i;
00678 
00679     for (i = 0; (i < CONNECTION_NUM) && ((index = connections[i]) != EMPTY); i++) {
00680         JackPort* port = GetPort(index);
00681         res[i] = port->fName;
00682     }
00683 
00684     res[i] = NULL;
00685 }
00686 
00687 /*
00688         Use the state returned by ReadCurrentState and check that the state was not changed during the read operation.
00689         The operation is lock-free since there is no intermediate state in the write operation that could cause the
00690         read to loop forever.
00691 */
00692 
00693 // Client
00694 const char** JackGraphManager::GetConnections(jack_port_id_t port_index)
00695 {
00696     const char** res = (const char**)malloc(sizeof(char*) * (CONNECTION_NUM + 1));
00697     UInt16 cur_index;
00698     UInt16 next_index;
00699     AssertPort(port_index);
00700 
00701     do {
00702         cur_index = GetCurrentIndex();
00703         GetConnectionsAux(ReadCurrentState(), res, port_index);
00704         next_index = GetCurrentIndex();
00705     } while (cur_index != next_index); // Until a coherent state has been read
00706 
00707     return res;
00708 }
00709 
00710 // Client
00711 const char** JackGraphManager::GetPortsAux(const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
00712 {
00713     unsigned long match_cnt = 0;
00714     regex_t port_regex;
00715     regex_t type_regex;
00716     bool matching;
00717 
00718     if (port_name_pattern && port_name_pattern[0]) {
00719         regcomp(&port_regex, port_name_pattern, REG_EXTENDED | REG_NOSUB);
00720     }
00721     if (type_name_pattern && type_name_pattern[0]) {
00722         regcomp(&type_regex, type_name_pattern, REG_EXTENDED | REG_NOSUB);
00723     }
00724 
00725         const char** matching_ports = (const char**)malloc(sizeof(char*) * PORT_NUM);
00726 
00727     for (int i = 0; i < PORT_NUM; i++) {
00728         matching = true;
00729                 JackPort* port = GetPort(i);
00730 
00731         if (port->IsUsed()) {
00732 
00733             if (flags) {
00734                 if ((port->fFlags & flags) != flags) {
00735                     matching = false;
00736                 }
00737             }
00738 
00739             if (matching && port_name_pattern && port_name_pattern[0]) {
00740                 if (regexec(&port_regex, port->GetName(), 0, NULL, 0)) {
00741                     matching = false;
00742                 }
00743             }
00744                         if (matching && type_name_pattern && type_name_pattern[0]) {
00745                 if (regexec(&type_regex, port->GetType(), 0, NULL, 0)) {
00746                     matching = false;
00747                 }
00748             }
00749 
00750             if (matching) {
00751                 matching_ports[match_cnt++] = port->fName;
00752             }
00753         }
00754     }
00755 
00756     matching_ports[match_cnt] = 0;
00757 
00758     if (match_cnt == 0) {
00759         free(matching_ports);
00760         matching_ports = NULL;
00761     }
00762 
00763     if (port_name_pattern && port_name_pattern[0]) {
00764         regfree(&port_regex);
00765     }
00766     if (type_name_pattern && type_name_pattern[0]) {
00767         regfree(&type_regex);
00768     }
00769 
00770     return matching_ports;
00771 }
00772 
00773 // Client
00774 /*
00775         Check that the state was not changed during the read operation.
00776         The operation is lock-free since there is no intermediate state in the write operation that could cause the
00777         read to loop forever.
00778 */
00779 const char** JackGraphManager::GetPorts(const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
00780 {
00781     const char** matching_ports = NULL;
00782     UInt16 cur_index;
00783     UInt16 next_index;
00784 
00785     do {
00786         cur_index = GetCurrentIndex();
00787         if (matching_ports) {
00788             free(matching_ports);
00789                         JackLog("JackGraphManager::GetPorts retry... \n");
00790                 }
00791         matching_ports = GetPortsAux(port_name_pattern, type_name_pattern, flags);
00792         next_index = GetCurrentIndex();
00793     } while (cur_index != next_index); // Until a coherent state has been read
00794 
00795     return matching_ports;
00796 }
00797 
00798 // Server
00799 void JackGraphManager::Save(JackConnectionManager* dst)
00800 {
00801     JackConnectionManager* manager = WriteNextStateStart();
00802     memcpy(dst, manager, sizeof(JackConnectionManager));
00803     WriteNextStateStop();
00804 }
00805 
00806 // Server
00807 void JackGraphManager::Restore(JackConnectionManager* src)
00808 {
00809     JackConnectionManager* manager = WriteNextStateStart();
00810     memcpy(manager, src, sizeof(JackConnectionManager));
00811     WriteNextStateStop();
00812 }
00813 
00814 } // end of namespace
00815 
00816 

Generated on Thu Feb 14 11:16:01 2008 for Jackdmp by  doxygen 1.5.1