26 #include "JackSystemDeps.h"    27 #include "JackLockedEngine.h"    28 #include "JackExternalClient.h"    29 #include "JackInternalClient.h"    30 #include "JackEngineControl.h"    31 #include "JackClientControl.h"    32 #include "JackServerGlobals.h"    33 #include "JackGlobals.h"    34 #include "JackChannel.h"    35 #include "JackError.h"    40 JackEngine::JackEngine(JackGraphManager* manager,
    42                        JackEngineControl* control,
    43                        char self_connect_mode)
    44                     : JackLockAble(control->fServerName), 
    45                     fSignal(control->fServerName)
    47     fGraphManager = manager;
    48     fSynchroTable = table;
    49     fEngineControl = control;
    50     fSelfConnectMode = self_connect_mode;
    51     for (
int i = 0; i < CLIENT_NUM; i++) {
    52         fClientTable[i] = NULL;
    56     fSessionPendingReplies = 0;
    57     fSessionTransaction = NULL;
    58     fSessionResult = NULL;
    61 JackEngine::~JackEngine()
    64 int JackEngine::Open()
    69     if (fChannel.Open(fEngineControl->fServerName) < 0) {
    77 int JackEngine::Close()
    83     for (
int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
    84         if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) {
    85             jack_log(
"JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName);
    86             loadable_client->Close();
    87             fClientTable[i] = NULL;
    88             delete loadable_client;
    89         } 
else if (JackExternalClient* external_client = dynamic_cast<JackExternalClient*>(fClientTable[i])) {
    90             jack_log(
"JackEngine::Close external client = %s", external_client->GetClientControl()->fName);
    91             external_client->Close();
    92             fClientTable[i] = NULL;
    93             delete external_client;
   100 void JackEngine::NotifyQuit()
   102     fChannel.NotifyQuit();
   109 int JackEngine::AllocateRefnum()
   111     for (
int i = 0; i < CLIENT_NUM; i++) {
   112         if (!fClientTable[i]) {
   113             jack_log(
"JackEngine::AllocateRefNum ref = %ld", i);
   120 void JackEngine::ReleaseRefnum(
int refnum)
   122     fClientTable[refnum] = NULL;
   124     if (fEngineControl->fTemporary) {
   126         for (i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
   127             if (fClientTable[i]) {
   131         if (i == CLIENT_NUM) {
   133             jack_log(
"JackEngine::ReleaseRefnum server quit");
   134             fEngineControl->fTemporary = 
false;
   135             throw JackTemporaryException();
   144 void JackEngine::ProcessNext(jack_time_t cur_cycle_begin)
   146     fLastSwitchUsecs = cur_cycle_begin;
   147     if (fGraphManager->RunNextGraph())  {   
   148         fChannel.Notify(ALL_CLIENTS, kGraphOrderCallback, 0);
   153 void JackEngine::ProcessCurrent(jack_time_t cur_cycle_begin)
   155     if (cur_cycle_begin < fLastSwitchUsecs + 2 * fEngineControl->fPeriodUsecs) { 
   156         CheckXRun(cur_cycle_begin);
   158     fGraphManager->RunCurrentGraph();
   161 bool JackEngine::Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end)
   166     fEngineControl->CycleBegin(fClientTable, fGraphManager, cur_cycle_begin, prev_cycle_end);
   169     if (fGraphManager->IsFinishedGraph()) {
   170         ProcessNext(cur_cycle_begin);
   173         jack_log(
"Process: graph not finished!");
   174         if (cur_cycle_begin > fLastSwitchUsecs + fEngineControl->fTimeOutUsecs) {
   175             jack_log(
"Process: switch to next state delta = %ld", 
long(cur_cycle_begin - fLastSwitchUsecs));
   176             ProcessNext(cur_cycle_begin);
   179             jack_log(
"Process: waiting to switch delta = %ld", 
long(cur_cycle_begin - fLastSwitchUsecs));
   180             ProcessCurrent(cur_cycle_begin);
   186     fEngineControl->CycleEnd(fClientTable);
   195 static const char* State2String(jack_client_state_t state)
   199             return "NotTriggered";
   211 void JackEngine::CheckXRun(jack_time_t callback_usecs)  
   213     for (
int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
   214         JackClientInterface* client = fClientTable[i];
   215         if (client && client->GetClientControl()->fActive) {
   216             JackClientTiming* timing = fGraphManager->GetClientTiming(i);
   217             jack_client_state_t status = timing->fStatus;
   218             jack_time_t finished_date = timing->fFinishedAt;
   220             if (status != NotTriggered && status != Finished) {
   221                 jack_error(
"JackEngine::XRun: client = %s was not finished, state = %s", client->GetClientControl()->fName, State2String(status));
   222                 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);  
   225             if (status == Finished && (
long)(finished_date - callback_usecs) > 0) {
   226                 jack_error(
"JackEngine::XRun: client %s finished after current callback", client->GetClientControl()->fName);
   227                 fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);  
   233 int JackEngine::ComputeTotalLatencies()
   235     std::vector<jack_int_t> sorted;
   236     std::vector<jack_int_t>::iterator it;
   237     std::vector<jack_int_t>::reverse_iterator rit;
   239     fGraphManager->TopologicalSort(sorted);
   245     for (it = sorted.begin(); it != sorted.end(); it++) {
   246         NotifyClient(*it, kLatencyCallback, 
true, 
"", 0, 0);
   251     for (rit = sorted.rbegin(); rit != sorted.rend(); rit++) {
   252         NotifyClient(*rit, kLatencyCallback, 
true, 
"", 1, 0);
   262 int JackEngine::ClientNotify(JackClientInterface* client, 
int refnum, 
const char* name, 
int notify, 
int sync, 
const char* message, 
int value1, 
int value2)
   265     if (!client->GetClientControl()->fCallback[notify]) {
   266         jack_log(
"JackEngine::ClientNotify: no callback for notification = %ld", notify);
   273     if (dynamic_cast<JackExternalClient*>(client)) {
   274        res1 = client->ClientNotify(refnum, name, notify, sync, message, value1, value2);
   277         bool res2 = Unlock();
   278         res1 = client->ClientNotify(refnum, name, notify, sync, message, value1, value2);
   285         jack_error(
"ClientNotify fails name = %s notification = %ld val1 = %ld val2 = %ld", name, notify, value1, value2);
   290 void JackEngine::NotifyClient(
int refnum, 
int event, 
int sync, 
const char* message, 
int value1, 
int value2)
   292     JackClientInterface* client = fClientTable[refnum];
   294         ClientNotify(client, refnum, client->GetClientControl()->fName, event, sync, message, value1, value2);
   298 void JackEngine::NotifyClients(
int event, 
int sync, 
const char* message, 
int value1, 
int value2)
   300     for (
int i = 0; i < CLIENT_NUM; i++) {
   301         NotifyClient(i, event, sync, message, value1, value2);
   305 int JackEngine::NotifyAddClient(JackClientInterface* new_client, 
const char* new_name, 
int refnum)
   307     jack_log(
"JackEngine::NotifyAddClient: name = %s", new_name);
   310     for (
int i = 0; i < CLIENT_NUM; i++) {
   311         JackClientInterface* old_client = fClientTable[i];
   312         if (old_client && old_client != new_client) {
   313             char* old_name = old_client->GetClientControl()->fName;
   314             if (ClientNotify(old_client, refnum, new_name, kAddClient, 
false, 
"", 0, 0) < 0) {
   315                 jack_error(
"NotifyAddClient old_client fails name = %s", old_name);
   318             if (ClientNotify(new_client, i, old_name, kAddClient, 
true, 
"", 0, 0) < 0) {
   319                 jack_error(
"NotifyAddClient new_client fails name = %s", new_name);
   328 void JackEngine::NotifyRemoveClient(
const char* name, 
int refnum)
   331     for (
int i = 0; i < CLIENT_NUM; i++) {
   332         JackClientInterface* client = fClientTable[i];
   334             ClientNotify(client, refnum, name, kRemoveClient, 
false, 
"", 0, 0);
   340 void JackEngine::NotifyDriverXRun()
   343     fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
   346 void JackEngine::NotifyClientXRun(
int refnum)
   348     if (refnum == ALL_CLIENTS) {
   349         NotifyClients(kXRunCallback, 
false, 
"", 0, 0);
   351         NotifyClient(refnum, kXRunCallback, 
false, 
"", 0, 0);
   355 void JackEngine::NotifyGraphReorder()
   357     ComputeTotalLatencies();
   358     NotifyClients(kGraphOrderCallback, 
false, 
"", 0, 0);
   361 void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size)
   363     NotifyClients(kBufferSizeCallback, 
true, 
"", buffer_size, 0);
   366 void JackEngine::NotifySampleRate(jack_nframes_t sample_rate)
   368     NotifyClients(kSampleRateCallback, 
true, 
"", sample_rate, 0);
   371 void JackEngine::NotifyFailure(
int code, 
const char* reason)
   373     NotifyClients(kShutDownCallback, 
false, reason, code, 0);
   376 void JackEngine::NotifyFreewheel(
bool onoff)
   380         fEngineControl->fSavedRealTime = fEngineControl->fRealTime;
   381         fEngineControl->fRealTime = 
false;
   384         fEngineControl->fRealTime = fEngineControl->fSavedRealTime;
   385         fEngineControl->fSavedRealTime = 
false;
   387     NotifyClients((onoff ? kStartFreewheelCallback : kStopFreewheelCallback), 
true, 
"", 0, 0);
   390 void JackEngine::NotifyPortRegistation(jack_port_id_t port_index, 
bool onoff)
   392     NotifyClients((onoff ? kPortRegistrationOnCallback : kPortRegistrationOffCallback), 
false, 
"", port_index, 0);
   395 void JackEngine::NotifyPortRename(jack_port_id_t port, 
const char* old_name)
   397     NotifyClients(kPortRenameCallback, 
false, old_name, port, 0);
   400 void JackEngine::NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, 
bool onoff)
   402     NotifyClients((onoff ? kPortConnectCallback : kPortDisconnectCallback), 
false, 
"", src, dst);
   405 void JackEngine::NotifyActivate(
int refnum)
   407     NotifyClient(refnum, kActivateClient, 
true, 
"", 0, 0);
   414 int JackEngine::GetInternalClientName(
int refnum, 
char* name_res)
   416     JackClientInterface* client = fClientTable[refnum];
   418     strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE);
   422 int JackEngine::InternalClientHandle(
const char* client_name, 
int* status, 
int* int_ref)
   427     for (
int i = 0; i < CLIENT_NUM; i++) {
   428         JackClientInterface* client = fClientTable[i];
   429         if (client && dynamic_cast<JackLoadableInternalClient*>(client) && (strcmp(client->GetClientControl()->fName, client_name) == 0)) {
   430             jack_log(
"InternalClientHandle found client name = %s ref = %ld",  client_name, i);
   436     *status |= (JackNoSuchClient | JackFailure);
   440 int JackEngine::InternalClientUnload(
int refnum, 
int* status)
   442     JackClientInterface* client = fClientTable[refnum];
   444         int res = client->Close();
   449         *status = (JackNoSuchClient | JackFailure);
   458 int JackEngine::ClientCheck(
const char* name, 
int uuid, 
char* name_res, 
int protocol, 
int options, 
int* status)
   462     strcpy(name_res, name);
   464     jack_log(
"Check protocol client = %ld server = %ld", protocol, JACK_PROTOCOL_VERSION);
   466     if (protocol != JACK_PROTOCOL_VERSION) {
   467         *status |= (JackFailure | JackVersionError);
   468         jack_error(
"JACK protocol mismatch (%d vs %d)", protocol, JACK_PROTOCOL_VERSION);
   472     std::map<int,std::string>::iterator res = fReservationMap.find(uuid);
   474     if (res != fReservationMap.end()) {
   475         strncpy(name_res, res->second.c_str(), JACK_CLIENT_NAME_SIZE);
   476     } 
else if (ClientCheckName(name)) {
   478         *status |= JackNameNotUnique;
   480         if (options & JackUseExactName) {
   481             jack_error(
"cannot create new client; %s already exists", name);
   482             *status |= JackFailure;
   486         if (GenerateUniqueName(name_res)) {
   487             *status |= JackFailure;
   495 bool JackEngine::GenerateUniqueName(
char* name)
   498     int length = strlen(name);
   500     if (length > JACK_CLIENT_NAME_SIZE - 4) {
   501         jack_error(
"%s exists and is too long to make unique", name);
   506     name[length++] = 
'-';
   513     while (ClientCheckName(name)) {
   514         if (name[ones] == 
'9') {
   515             if (name[tens] == 
'9') {
   516                 jack_error(
"client %s has 99 extra instances already", name);
   528 bool JackEngine::ClientCheckName(
const char* name)
   530     for (
int i = 0; i < CLIENT_NUM; i++) {
   531         JackClientInterface* client = fClientTable[i];
   532         if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
   537     for (std::map<int,std::string>::iterator i = fReservationMap.begin(); i != fReservationMap.end(); i++) {
   538         if (i->second == name) {
   546 int JackEngine::GetNewUUID()
   551 void JackEngine::EnsureUUID(
int uuid)
   553     if (uuid > fMaxUUID) {
   557     for (
int i = 0; i < CLIENT_NUM; i++) {
   558         JackClientInterface* client = fClientTable[i];
   559         if (client && (client->GetClientControl()->fSessionID == uuid)) {
   560             client->GetClientControl()->fSessionID = GetNewUUID();
   565 int JackEngine::GetClientPID(
const char* name)
   567     for (
int i = 0; i < CLIENT_NUM; i++) {
   568         JackClientInterface* client = fClientTable[i];
   569         if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
   570             return client->GetClientControl()->fPID;
   577 int JackEngine::GetClientRefNum(
const char* name)
   579     for (
int i = 0; i < CLIENT_NUM; i++) {
   580         JackClientInterface* client = fClientTable[i];
   581         if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
   582             return client->GetClientControl()->fRefNum;
   590 int JackEngine::ClientExternalOpen(
const char* name, 
int pid, 
int uuid, 
int* ref, 
int* shared_engine, 
int* shared_client, 
int* shared_graph_manager)
   592     char real_name[JACK_CLIENT_NAME_SIZE + 1];
   596         strncpy(real_name, name, JACK_CLIENT_NAME_SIZE);
   598         std::map<int, std::string>::iterator res = fReservationMap.find(uuid);
   599         if (res != fReservationMap.end()) {
   600             strncpy(real_name, res->second.c_str(), JACK_CLIENT_NAME_SIZE);
   601             fReservationMap.erase(uuid);
   603             strncpy(real_name, name, JACK_CLIENT_NAME_SIZE);
   608     jack_log(
"JackEngine::ClientExternalOpen: uuid = %d, name = %s", uuid, real_name);
   610     int refnum = AllocateRefnum();
   616     JackExternalClient* client = 
new JackExternalClient();
   618     if (!fSynchroTable[refnum].Allocate(real_name, fEngineControl->fServerName, 0)) {
   623     if (client->Open(real_name, pid, refnum, uuid, shared_client) < 0) {
   628     if (!fSignal.LockedTimedWait(DRIVER_OPEN_TIMEOUT * 1000000)) {
   634     fClientTable[refnum] = client;
   636     if (NotifyAddClient(client, real_name, refnum) < 0) {
   641     fGraphManager->InitRefNum(refnum);
   642     fEngineControl->ResetRollingUsecs();
   643     *shared_engine = fEngineControl->GetShmIndex();
   644     *shared_graph_manager = fGraphManager->GetShmIndex();
   650     fSynchroTable[refnum].Destroy();
   651     fClientTable[refnum] = 0;
   658 int JackEngine::ClientInternalOpen(
const char* name, 
int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, 
bool wait)
   660     jack_log(
"JackEngine::ClientInternalOpen: name = %s", name);
   662     int refnum = AllocateRefnum();
   668     if (!fSynchroTable[refnum].Allocate(name, fEngineControl->fServerName, 0)) {
   673     if (wait && !fSignal.LockedTimedWait(DRIVER_OPEN_TIMEOUT * 1000000)) {
   679     fClientTable[refnum] = client;
   681     if (NotifyAddClient(client, name, refnum) < 0) {
   686     fGraphManager->InitRefNum(refnum);
   687     fEngineControl->ResetRollingUsecs();
   688     *shared_engine = fEngineControl;
   689     *shared_manager = fGraphManager;
   695     fSynchroTable[refnum].Destroy();
   696     fClientTable[refnum] = 0;
   701 int JackEngine::ClientExternalClose(
int refnum)
   703     jack_log(
"JackEngine::ClientExternalClose ref = %ld", refnum);
   704     JackClientInterface* client = fClientTable[refnum];
   706     int res = ClientCloseAux(refnum, 
true);
   713 int JackEngine::ClientInternalClose(
int refnum, 
bool wait)
   715     jack_log(
"JackEngine::ClientInternalClose ref = %ld", refnum);
   716     return ClientCloseAux(refnum, wait);
   719 int JackEngine::ClientCloseAux(
int refnum, 
bool wait)
   721     jack_log(
"JackEngine::ClientCloseAux ref = %ld", refnum);
   723     JackClientInterface* client = fClientTable[refnum];
   724     fEngineControl->fTransport.ResetTimebase(refnum);
   727     jack_int_t ports[PORT_NUM_FOR_CLIENT];
   730     fGraphManager->GetInputPorts(refnum, ports);
   731     for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) {
   732         PortUnRegister(refnum, ports[i]);
   735     fGraphManager->GetOutputPorts(refnum, ports);
   736     for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) {
   737         PortUnRegister(refnum, ports[i]);
   741     ReleaseRefnum(refnum);
   744     fGraphManager->RemoveAllPorts(refnum);
   748         if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 2)) { 
   749             jack_error(
"JackEngine::ClientCloseAux wait error ref = %ld", refnum);
   754     NotifyRemoveClient(client->GetClientControl()->fName, refnum);
   757     fSynchroTable[refnum].Destroy();
   758     fEngineControl->ResetRollingUsecs();
   762 int JackEngine::ClientActivate(
int refnum, 
bool is_real_time)
   764     JackClientInterface* client = fClientTable[refnum];
   765     jack_log(
"JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
   768         fGraphManager->Activate(refnum);
   772     if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) {
   773         jack_error(
"JackEngine::ClientActivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName);
   776         jack_int_t input_ports[PORT_NUM_FOR_CLIENT];
   777         jack_int_t output_ports[PORT_NUM_FOR_CLIENT];
   778         fGraphManager->GetInputPorts(refnum, input_ports);
   779         fGraphManager->GetOutputPorts(refnum, output_ports);
   782         NotifyActivate(refnum);
   785         for (
int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) {
   786             NotifyPortRegistation(input_ports[i], 
true);
   788         for (
int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) {
   789             NotifyPortRegistation(output_ports[i], 
true);
   797 int JackEngine::ClientDeactivate(
int refnum)
   799     JackClientInterface* client = fClientTable[refnum];
   800     jack_log(
"JackEngine::ClientDeactivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
   802     jack_int_t input_ports[PORT_NUM_FOR_CLIENT];
   803     jack_int_t output_ports[PORT_NUM_FOR_CLIENT];
   804     fGraphManager->GetInputPorts(refnum, input_ports);
   805     fGraphManager->GetOutputPorts(refnum, output_ports);
   808     for (
int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) {
   809         PortDisconnect(-1, input_ports[i], ALL_PORTS);
   811     for (
int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) {
   812         PortDisconnect(-1, output_ports[i], ALL_PORTS);
   816     for (
int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) {
   817         NotifyPortRegistation(input_ports[i], 
false);
   819     for (
int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) {
   820         NotifyPortRegistation(output_ports[i], 
false);
   823     fGraphManager->Deactivate(refnum);
   824     fLastSwitchUsecs = 0; 
   827     if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) {
   828         jack_error(
"JackEngine::ClientDeactivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName);
   835 void JackEngine::ClientKill(
int refnum)
   837     jack_log(
"JackEngine::ClientKill ref = %ld", refnum);
   838     if (ClientDeactivate(refnum) < 0) {
   839         jack_error(
"JackEngine::ClientKill ref = %ld cannot be removed from the graph !!", refnum);
   841     if (ClientExternalClose(refnum) < 0) {
   842         jack_error(
"JackEngine::ClientKill ref = %ld cannot be closed", refnum);
   850 int JackEngine::PortRegister(
int refnum, 
const char* name, 
const char *type, 
unsigned int flags, 
unsigned int buffer_size, jack_port_id_t* port_index)
   852     jack_log(
"JackEngine::PortRegister ref = %ld name = %s type = %s flags = %d buffer_size = %d", refnum, name, type, flags, buffer_size);
   853     JackClientInterface* client = fClientTable[refnum];
   856     if (fGraphManager->GetPort(name) != NO_PORT) {
   857         jack_error(
"port_name \"%s\" already exists", name);
   862     *port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize);
   863     if (*port_index != NO_PORT) {
   864         if (client->GetClientControl()->fActive) {
   865             NotifyPortRegistation(*port_index, 
true);
   873 int JackEngine::PortUnRegister(
int refnum, jack_port_id_t port_index)
   875     jack_log(
"JackEngine::PortUnRegister ref = %ld port_index = %ld", refnum, port_index);
   876     JackClientInterface* client = fClientTable[refnum];
   880     PortDisconnect(-1, port_index, ALL_PORTS);
   882     if (fGraphManager->ReleasePort(refnum, port_index) == 0) {
   883         if (client->GetClientControl()->fActive) {
   884             NotifyPortRegistation(port_index, 
false);
   894 int JackEngine::CheckPortsConnect(
int refnum, jack_port_id_t src, jack_port_id_t dst)
   896     if (fSelfConnectMode == 
' ') 
return 1;
   898     JackPort* src_port = fGraphManager->GetPort(src);
   899     JackPort* dst_port = fGraphManager->GetPort(dst);
   901     jack_log(
"JackEngine::CheckPortsConnect(ref = %d, src = %d, dst = %d)", refnum, src_port->GetRefNum(), dst_port->GetRefNum());
   906     int src_self = src_port->GetRefNum() == refnum ? 1 : 0;
   907     int dst_self = dst_port->GetRefNum() == refnum ? 1 : 0;
   915     int sum = src_self + dst_self;
   917     if (sum == 0) 
return 1;
   918     char lmode = tolower(fSelfConnectMode);
   920     if (sum == 2 && lmode == 
'e') 
return 1;
   921     bool fail = lmode != fSelfConnectMode; 
   925         "%s port self connect request%s (%s -> %s)",
   926         fail ? 
"rejecting" : 
"ignoring",
   927         sum == 1 ? 
" to external port" : 
"",
   929         dst_port->GetName());
   931     return fail ? -1 : 0;
   934 int JackEngine::PortConnect(
int refnum, 
const char* src, 
const char* dst)
   936     jack_log(
"JackEngine::PortConnect ref = %d src = %s dst = %s", refnum, src, dst);
   937     jack_port_id_t port_src, port_dst;
   939     return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
   941            : PortConnect(refnum, port_src, port_dst);
   944 int JackEngine::PortConnect(
int refnum, jack_port_id_t src, jack_port_id_t dst)
   946     jack_log(
"JackEngine::PortConnect ref = %d src = %d dst = %d", refnum, src, dst);
   947     JackClientInterface* client;
   950     if (fGraphManager->CheckPorts(src, dst) < 0) {
   954     ref = fGraphManager->GetOutputRefNum(src);
   956     client = fClientTable[ref];
   958     if (!client->GetClientControl()->fActive) {
   959         jack_error(
"Cannot connect ports owned by inactive clients:"   960                    " \"%s\" is not active", client->GetClientControl()->fName);
   964     ref = fGraphManager->GetInputRefNum(dst);
   966     client = fClientTable[ref];
   968     if (!client->GetClientControl()->fActive) {
   969         jack_error(
"Cannot connect ports owned by inactive clients:"   970                    " \"%s\" is not active", client->GetClientControl()->fName);
   974     int res = CheckPortsConnect(refnum, src, dst);
   979     res = fGraphManager->Connect(src, dst);
   981         NotifyPortConnect(src, dst, 
true);
   986 int JackEngine::PortDisconnect(
int refnum, 
const char* src, 
const char* dst)
   988     jack_log(
"JackEngine::PortDisconnect ref = %d src = %s dst = %s", refnum, src, dst);
   989     jack_port_id_t port_src, port_dst;
   991     return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
   993            : PortDisconnect(refnum, port_src, port_dst);
   996 int JackEngine::PortDisconnect(
int refnum, jack_port_id_t src, jack_port_id_t dst)
   998     jack_log(
"JackEngine::PortDisconnect ref = %d src = %d dst = %d", refnum, src, dst);
  1000     if (dst == ALL_PORTS) {
  1002         jack_int_t connections[CONNECTION_NUM_FOR_PORT];
  1003         fGraphManager->GetConnections(src, connections);
  1005         JackPort* port = fGraphManager->GetPort(src);
  1007         if (port->GetFlags() & JackPortIsOutput) {
  1008             for (
int i = 0; (i < CONNECTION_NUM_FOR_PORT) && (connections[i] != EMPTY); i++) {
  1009                 if (PortDisconnect(refnum, src, connections[i]) != 0) {
  1014             for (
int i = 0; (i < CONNECTION_NUM_FOR_PORT) && (connections[i] != EMPTY); i++) {
  1015                 if (PortDisconnect(refnum, connections[i], src) != 0) {
  1024     if (fGraphManager->CheckPorts(src, dst) < 0) {
  1028     int res = CheckPortsConnect(refnum, src, dst);
  1033     res = fGraphManager->Disconnect(src, dst);
  1035         NotifyPortConnect(src, dst, 
false);
  1039 int JackEngine::PortRename(
int refnum, jack_port_id_t port, 
const char* name)
  1041     char old_name[REAL_JACK_PORT_NAME_SIZE+1];
  1042     strcpy(old_name, fGraphManager->GetPort(port)->GetName());
  1043     fGraphManager->GetPort(port)->SetName(name);
  1044     NotifyPortRename(port, old_name);
  1052 void JackEngine::SessionNotify(
int refnum, 
const char *target, jack_session_event_type_t type, 
const char *path, detail::JackChannelTransactionInterface *socket, JackSessionNotifyResult** result)
  1054     if (fSessionPendingReplies != 0) {
  1055         JackSessionNotifyResult res(-1);
  1057         jack_log(
"JackEngine::SessionNotify ... busy");
  1058         if (result != NULL) *result = NULL;
  1062     for (
int i = 0; i < CLIENT_NUM; i++) {
  1063         JackClientInterface* client = fClientTable[i];
  1064         if (client && (client->GetClientControl()->fSessionID < 0)) {
  1065             client->GetClientControl()->fSessionID = GetNewUUID();
  1068     fSessionResult = 
new JackSessionNotifyResult();
  1070     for (
int i = 0; i < CLIENT_NUM; i++) {
  1071         JackClientInterface* client = fClientTable[i];
  1072         if (client && client->GetClientControl()->fCallback[kSessionCallback]) {
  1075             if (target != NULL && strlen(target) != 0) {
  1076                 if (strcmp(target, client->GetClientControl()->fName)) {
  1081             char path_buf[JACK_PORT_NAME_SIZE];
  1082             if (path[strlen(path) - 1] == DIR_SEPARATOR) {
  1083                snprintf(path_buf, 
sizeof path_buf, 
"%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR);
  1085                snprintf(path_buf, 
sizeof path_buf, 
"%s%c%s%c", path, DIR_SEPARATOR, client->GetClientControl()->fName, DIR_SEPARATOR);
  1088             int res = JackTools::MkDir(path_buf);
  1089             if (res) 
jack_error(
"JackEngine::SessionNotify: can not create session directory '%s'", path_buf);
  1091             int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, 
true, path_buf, (int)type, 0);
  1093             if (result == kPendingSessionReply) {
  1094                 fSessionPendingReplies += 1;
  1095             } 
else if (result == kImmediateSessionReply) {
  1096                 char uuid_buf[JACK_UUID_SIZE];
  1097                 snprintf(uuid_buf, 
sizeof(uuid_buf), 
"%d", client->GetClientControl()->fSessionID);
  1098                 fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf,
  1099                                                                         client->GetClientControl()->fName,
  1100                                                                         client->GetClientControl()->fSessionCommand,
  1101                                                                         client->GetClientControl()->fSessionFlags));
  1106     if (result != NULL) *result = fSessionResult;
  1108     if (fSessionPendingReplies == 0) {
  1109         fSessionResult->Write(socket);
  1110         if (result == NULL) 
delete fSessionResult;
  1111         fSessionResult = NULL;
  1113         fSessionTransaction = socket;
  1117 int JackEngine::SessionReply(
int refnum)
  1119     JackClientInterface* client = fClientTable[refnum];
  1121     char uuid_buf[JACK_UUID_SIZE];
  1122     snprintf(uuid_buf, 
sizeof(uuid_buf), 
"%d", client->GetClientControl()->fSessionID);
  1123     fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf,
  1124                                                             client->GetClientControl()->fName,
  1125                                                             client->GetClientControl()->fSessionCommand,
  1126                                                             client->GetClientControl()->fSessionFlags));
  1127     fSessionPendingReplies -= 1;
  1129     if (fSessionPendingReplies == 0) {
  1130         fSessionResult->Write(fSessionTransaction);
  1131         if (fSessionTransaction != NULL) {
  1132             delete fSessionResult;
  1134         fSessionResult = NULL;
  1140 int JackEngine::GetUUIDForClientName(
const char *client_name, 
char *uuid_res)
  1142     for (
int i = 0; i < CLIENT_NUM; i++) {
  1143         JackClientInterface* client = fClientTable[i];
  1145         if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) {
  1146             snprintf(uuid_res, JACK_UUID_SIZE, 
"%d", client->GetClientControl()->fSessionID);
  1154 int JackEngine::GetClientNameForUUID(
const char *uuid, 
char *name_res)
  1156     for (
int i = 0; i < CLIENT_NUM; i++) {
  1157         JackClientInterface* client = fClientTable[i];
  1163         char uuid_buf[JACK_UUID_SIZE];
  1164         snprintf(uuid_buf, JACK_UUID_SIZE, 
"%d", client->GetClientControl()->fSessionID);
  1166         if (strcmp(uuid,uuid_buf) == 0) {
  1167             strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE);
  1175 int JackEngine::ReserveClientName(
const char *name, 
const char *uuid)
  1177     jack_log(
"JackEngine::ReserveClientName ( name = %s, uuid = %s )", name, uuid);
  1179     if (ClientCheckName(name)) {
  1184     EnsureUUID(atoi(uuid));
  1185     fReservationMap[atoi(uuid)] = name;
  1189 int JackEngine::ClientHasSessionCallback(
const char *name)
  1191     JackClientInterface* client = NULL;
  1192     for (
int i = 0; i < CLIENT_NUM; i++) {
  1193         client = fClientTable[i];
  1194         if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) {
  1200         return client->GetClientControl()->fCallback[kSessionCallback];
 SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)
SERVER_EXPORT void jack_log(const char *fmt,...)