int JackEngine::GetClientRefNum(const char* name) { for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { return client->GetClientControl()->fRefNum; } } return -1; }
int JackEngine::GetUUIDForClientName(const char *client_name, char *uuid_res) { for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) { snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); return 0; } } // Did not find name. return -1; }
void JackEngine::EnsureUUID(int uuid) { if (uuid > fMaxUUID) { fMaxUUID = uuid + 1; } for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && (client->GetClientControl()->fSessionID == uuid)) { client->GetClientControl()->fSessionID = GetNewUUID(); } } }
int JackEngine::GetInternalClientName(int refnum, char* name_res) { JackClientInterface* client = fClientTable[refnum]; assert(client); strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE); return 0; }
int JackEngine::ClientActivate(int refnum, bool is_real_time) { JackClientInterface* client = fClientTable[refnum]; jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); if (is_real_time) { fGraphManager->Activate(refnum); } // Wait for graph state change to be effective if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) { jack_error("JackEngine::ClientActivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName); return -1; } else { jack_int_t input_ports[PORT_NUM_FOR_CLIENT]; jack_int_t output_ports[PORT_NUM_FOR_CLIENT]; fGraphManager->GetInputPorts(refnum, input_ports); fGraphManager->GetOutputPorts(refnum, output_ports); // Notify client NotifyActivate(refnum); // Then issue port registration notification for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { NotifyPortRegistation(input_ports[i], true); } for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { NotifyPortRegistation(output_ports[i], true); } return 0; } }
int JackEngine::ClientHasSessionCallback(const char *name) { JackClientInterface* client = NULL; for (int i = 0; i < CLIENT_NUM; i++) { client = fClientTable[i]; if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { break; } } if (client) { return client->GetClientControl()->fCallback[kSessionCallback]; } else { return -1; } }
void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2) { JackClientInterface* client = fClientTable[refnum]; if (client) { ClientNotify(client, refnum, client->GetClientControl()->fName, event, sync, message, value1, value2); } }
int JackEngine::ClientCloseAux(int refnum, bool wait) { jack_log("JackEngine::ClientCloseAux ref = %ld", refnum); JackClientInterface* client = fClientTable[refnum]; fEngineControl->fTransport.ResetTimebase(refnum); // Unregister all ports ==> notifications are sent jack_int_t ports[PORT_NUM_FOR_CLIENT]; int i; fGraphManager->GetInputPorts(refnum, ports); for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) { PortUnRegister(refnum, ports[i]); } fGraphManager->GetOutputPorts(refnum, ports); for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) { PortUnRegister(refnum, ports[i]); } // Remove the client from the table ReleaseRefnum(refnum); // Remove all ports fGraphManager->RemoveAllPorts(refnum); // Wait until next cycle to be sure client is not used anymore if (wait) { if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 2)) { // Must wait at least until a switch occurs in Process, even in case of graph end failure jack_error("JackEngine::ClientCloseAux wait error ref = %ld", refnum); } } // Notify running clients NotifyRemoveClient(client->GetClientControl()->fName, client->GetClientControl()->fRefNum); // Cleanup... fSynchroTable[refnum].Destroy(); fEngineControl->ResetRollingUsecs(); return 0; }
int JackEngine::GetClientNameForUUID(const char *uuid, char *name_res) { for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (!client) { continue; } char uuid_buf[JACK_UUID_SIZE]; snprintf(uuid_buf, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); if (strcmp(uuid,uuid_buf) == 0) { strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE); return 0; } } // Did not find uuid. return -1; }
void JackEngineControl::CalcCPULoad(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) { fPrevCycleTime = fCurCycleTime; fCurCycleTime = cur_cycle_begin; jack_time_t last_cycle_end = prev_cycle_end; // In Asynchronous mode, last cycle end is the max of client end dates if (!fSyncMode) { for (int i = fDriverNum; i < CLIENT_NUM; i++) { JackClientInterface* client = table[i]; JackClientTiming* timing = manager->GetClientTiming(i); if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) { last_cycle_end = JACK_MAX(last_cycle_end, timing->fFinishedAt); } } } // Store the execution time for later averaging if (last_cycle_end > 0) { fRollingClientUsecs[fRollingClientUsecsIndex++] = last_cycle_end - fPrevCycleTime; } if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) { fRollingClientUsecsIndex = 0; } // Each time we have a full set of iterations, recompute the current // usage from the latest JACK_ENGINE_ROLLING_COUNT client entries. if (fRollingClientUsecsCnt && (fRollingClientUsecsIndex == 0)) { jack_time_t avg_usecs = 0; jack_time_t max_usecs = 0; for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) { avg_usecs += fRollingClientUsecs[i]; // This is really a running total to be averaged later max_usecs = JACK_MAX(fRollingClientUsecs[i], max_usecs); } fMaxUsecs = JACK_MAX(fMaxUsecs, max_usecs); if (max_usecs < ((fPeriodUsecs * 95) / 100)) { // Average the values from our JACK_ENGINE_ROLLING_COUNT array fSpareUsecs = (jack_time_t)(fPeriodUsecs - (avg_usecs / JACK_ENGINE_ROLLING_COUNT)); } else { // Use the 'worst case' value (or zero if we exceeded 'fPeriodUsecs') fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0); } fCPULoad = ((1.f - (float(fSpareUsecs) / float(fPeriodUsecs))) * 50.f + (fCPULoad * 0.5f)); } fRollingClientUsecsCnt++; }
int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) { jack_log("JackEngine::PortConnect ref = %d src = %d dst = %d", refnum, src, dst); JackClientInterface* client; int ref; if (fGraphManager->CheckPorts(src, dst) < 0) { return -1; } ref = fGraphManager->GetOutputRefNum(src); assert(ref >= 0); client = fClientTable[ref]; assert(client); if (!client->GetClientControl()->fActive) { jack_error("Cannot connect ports owned by inactive clients:" " \"%s\" is not active", client->GetClientControl()->fName); return -1; } ref = fGraphManager->GetInputRefNum(dst); assert(ref >= 0); client = fClientTable[ref]; assert(client); if (!client->GetClientControl()->fActive) { jack_error("Cannot connect ports owned by inactive clients:" " \"%s\" is not active", client->GetClientControl()->fName); return -1; } int res = CheckPortsConnect(refnum, src, dst); if (res != 1) { return res; } res = fGraphManager->Connect(src, dst); if (res == 0) { NotifyPortConnect(src, dst, true); } return res; }
// RT bool JackTransportEngine::CheckAllRolling(JackClientInterface** table) { for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) { JackClientInterface* client = table[i]; if (client && client->GetClientControl()->fTransportState != JackTransportRolling) { jack_log("CheckAllRolling ref = %ld is not rolling", i); return false; } } jack_log("CheckAllRolling"); return true; }
int JackEngine::SessionReply(int refnum) { JackClientInterface* client = fClientTable[refnum]; char uuid_buf[JACK_UUID_SIZE]; snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID); fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf, client->GetClientControl()->fName, client->GetClientControl()->fSessionCommand, client->GetClientControl()->fSessionFlags)); fSessionPendingReplies -= 1; if (fSessionPendingReplies == 0) { fSessionResult->Write(fSessionTransaction); if (fSessionTransaction != NULL) { delete fSessionResult; } fSessionResult = NULL; } return 0; }
// RT void JackTransportEngine::MakeAllLocating(JackClientInterface** table) { for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) { JackClientInterface* client = table[i]; if (client) { JackClientControl* control = client->GetClientControl(); control->fTransportState = JackTransportStopped; control->fTransportSync = true; control->fTransportTimebase = true; jack_log("MakeAllLocating ref = %ld", i); } } }
// RT void JackTransportEngine::MakeAllStartingLocating(JackClientInterface** table) { for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) { JackClientInterface* client = table[i]; if (client) { JackClientControl* control = client->GetClientControl(); // Inactive clients don't have their process function called at all, so they must appear as already "rolling" for the transport.... control->fTransportState = (control->fActive && control->fCallback[kRealTimeCallback]) ? JackTransportStarting : JackTransportRolling; control->fTransportSync = true; control->fTransportTimebase = true; jack_log("MakeAllStartingLocating ref = %ld", i); } } }
int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index) { jack_log("JackEngine::PortUnRegister ref = %ld port_index = %ld", refnum, port_index); JackClientInterface* client = fClientTable[refnum]; // Disconnect port ==> notification is sent PortDisconnect(refnum, port_index, ALL_PORTS); if (fGraphManager->ReleasePort(refnum, port_index) == 0) { if (client->GetClientControl()->fActive) { NotifyPortRegistation(port_index, false); } return 0; } else { return -1; } }
bool JackEngine::ClientCheckName(const char* name) { for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { return true; } } for (std::map<int,std::string>::iterator i = fReservationMap.begin(); i != fReservationMap.end(); i++) { if (i->second == name) { return true; } } return false; }
int JackEngine::InternalClientHandle(const char* client_name, int* status, int* int_ref) { // Clear status *status = 0; for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && dynamic_cast<JackLoadableInternalClient*>(client) && (strcmp(client->GetClientControl()->fName, client_name) == 0)) { jack_log("InternalClientHandle found client name = %s ref = %ld", client_name, i); *int_ref = i; return 0; } } *status |= (JackNoSuchClient | JackFailure); return -1; }
void JackEngine::CheckXRun(jack_time_t callback_usecs) // REVOIR les conditions de fin { for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && client->GetClientControl()->fActive) { JackClientTiming* timing = fGraphManager->GetClientTiming(i); jack_client_state_t status = timing->fStatus; jack_time_t finished_date = timing->fFinishedAt; if (status != NotTriggered && status != Finished) { jack_error("JackEngine::XRun: client = %s was not finished, state = %s", client->GetClientControl()->fName, State2String(status)); fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); // Notify all clients } if (status == Finished && (long)(finished_date - callback_usecs) > 0) { jack_error("JackEngine::XRun: client %s finished after current callback", client->GetClientControl()->fName); fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); // Notify all clients } } } }
int JackEngine::PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index) { jack_log("JackEngine::PortRegister ref = %ld name = %s type = %s flags = %d buffer_size = %d", refnum, name, type, flags, buffer_size); JackClientInterface* client = fClientTable[refnum]; // Check if port name already exists if (fGraphManager->GetPort(name) != NO_PORT) { jack_error("port_name \"%s\" already exists", name); return -1; } // buffer_size is actually ignored... *port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize); if (*port_index != NO_PORT) { if (client->GetClientControl()->fActive) { NotifyPortRegistation(*port_index, true); } return 0; } else { return -1; } }
void JackEngineControl::CalcCPULoad(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end) { fPrevCycleTime = fCurCycleTime; fCurCycleTime = cur_cycle_begin; jack_time_t last_cycle_end = prev_cycle_end; // In Asynchronous mode, last cycle end is the max of client end dates if (!fSyncMode) { for (int i = fDriverNum; i < CLIENT_NUM; i++) { JackClientInterface* client = table[i]; JackClientTiming* timing = manager->GetClientTiming(i); if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) last_cycle_end = JACK_MAX(last_cycle_end, timing->fFinishedAt); } } // Store the execution time for later averaging fRollingClientUsecs[fRollingClientUsecsIndex++] = last_cycle_end - fPrevCycleTime; if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) fRollingClientUsecsIndex = 0; // Every so often, recompute the current maximum use over the // last JACK_ENGINE_ROLLING_COUNT client iterations. if (++fRollingClientUsecsCnt % fRollingInterval == 0) { jack_time_t max_usecs = 0; for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) max_usecs = JACK_MAX(fRollingClientUsecs[i], max_usecs); fMaxUsecs = JACK_MAX(fMaxUsecs, max_usecs); fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0); fCPULoad = ((1.f - (float(fSpareUsecs) / float(fPeriodUsecs))) * 50.f + (fCPULoad * 0.5f)); } }
// May be called without client int JackEngine::ClientDeactivate(int refnum) { JackClientInterface* client = fClientTable[refnum]; jack_log("JackEngine::ClientDeactivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); jack_int_t input_ports[PORT_NUM_FOR_CLIENT]; jack_int_t output_ports[PORT_NUM_FOR_CLIENT]; fGraphManager->GetInputPorts(refnum, input_ports); fGraphManager->GetOutputPorts(refnum, output_ports); // First disconnect all ports for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { PortDisconnect(refnum, input_ports[i], ALL_PORTS); } for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { PortDisconnect(refnum, output_ports[i], ALL_PORTS); } // Then issue port registration notification for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { NotifyPortRegistation(input_ports[i], false); } for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { NotifyPortRegistation(output_ports[i], false); } fGraphManager->Deactivate(refnum); fLastSwitchUsecs = 0; // Force switch to occur next cycle, even when called with "dead" clients // Wait for graph state change to be effective if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) { jack_error("JackEngine::ClientDeactivate wait error ref = %ld name = %s", refnum, client->GetClientControl()->fName); return -1; } else { return 0; } }
void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, detail::JackChannelTransactionInterface *socket, JackSessionNotifyResult** result) { if (fSessionPendingReplies != 0) { JackSessionNotifyResult res(-1); res.Write(socket); jack_log("JackEngine::SessionNotify ... busy"); if (result != NULL) { *result = NULL; } return; } for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && (client->GetClientControl()->fSessionID < 0)) { client->GetClientControl()->fSessionID = GetNewUUID(); } } fSessionResult = new JackSessionNotifyResult(); for (int i = 0; i < CLIENT_NUM; i++) { JackClientInterface* client = fClientTable[i]; if (client && client->GetClientControl()->fCallback[kSessionCallback]) { // check if this is a notification to a specific client. if (target != NULL && strlen(target) != 0) { if (strcmp(target, client->GetClientControl()->fName)) { continue; } } char path_buf[JACK_PORT_NAME_SIZE]; snprintf(path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR); int res = JackTools::MkDir(path_buf); if (res) { jack_error("JackEngine::SessionNotify: can not create session directory '%s'", path_buf); } int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int)type, 0); if (result == kPendingSessionReply) { fSessionPendingReplies += 1; } else if (result == kImmediateSessionReply) { char uuid_buf[JACK_UUID_SIZE]; snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID); fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf, client->GetClientControl()->fName, client->GetClientControl()->fSessionCommand, client->GetClientControl()->fSessionFlags)); } } } if (result != NULL) { *result = fSessionResult; } if (fSessionPendingReplies == 0) { fSessionResult->Write(socket); if (result == NULL) { delete fSessionResult; } fSessionResult = NULL; } else { fSessionTransaction = socket; } }