int JackEngine::Close() { jack_log("JackEngine::Close"); fChannel.Close(); // Close remaining clients (RT is stopped) for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) { if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) { jack_log("JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName); loadable_client->Close(); fClientTable[i] = NULL; delete loadable_client; } else if (JackExternalClient* external_client = dynamic_cast<JackExternalClient*>(fClientTable[i])) { jack_log("JackEngine::Close external client = %s", external_client->GetClientControl()->fName); external_client->Close(); fClientTable[i] = NULL; delete external_client; } } return 0; }
void JackSocketServerChannel::ClientRemove(detail::JackChannelTransactionInterface* socket_aux, int refnum) { JackClientSocket* socket = dynamic_cast<JackClientSocket*>(socket_aux); assert(socket); int fd = GetFd(socket); assert(fd >= 0); jack_log("JackSocketServerChannel::ClientRemove ref = %d fd = %d", refnum, fd); fSocketTable.erase(fd); socket->Close(); delete socket; fRebuild = true; }
void JackSocketServerChannel::ClientAdd(detail::JackChannelTransactionInterface* socket_aux, JackClientOpenRequest* req, JackClientOpenResult *res) { int refnum = -1; res->fResult = fServer->GetEngine()->ClientExternalOpen(req->fName, req->fPID, req->fUUID, &refnum, &res->fSharedEngine, &res->fSharedClient, &res->fSharedGraph); if (res->fResult == 0) { JackClientSocket* socket = dynamic_cast<JackClientSocket*>(socket_aux); assert(socket); int fd = GetFd(socket); assert(fd >= 0); fSocketTable[fd].first = refnum; fRebuild = true; jack_log("JackSocketServerChannel::ClientAdd ref = %d fd = %d", refnum, fd); #ifdef __APPLE__ int on = 1; if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) { jack_log("JackSocketServerChannel::ClientAdd : setsockopt SO_NOSIGPIPE fd = %ld err = %s", fd, strerror(errno)); } #endif } else { jack_error("Cannot create new client"); } }
int JackServer::Close() { jack_log("JackServer::Close"); fRequestChannel.Close(); fAudioDriver->Detach(); fAudioDriver->Close(); fFreewheelDriver->Close(); fEngine->Close(); // TODO: move that in reworked JackServerGlobals::Destroy() JackMessageBuffer::Destroy(); EndTime(); return 0; }
int JackMidiDriver::Attach() { JackPort* port; jack_port_id_t port_index; char name[REAL_JACK_PORT_NAME_SIZE]; char alias[REAL_JACK_PORT_NAME_SIZE]; int i; jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); for (i = 0; i < fCaptureChannels; i++) { snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1); if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { jack_error("driver: cannot register port for %s", name); return -1; } port = fGraphManager->GetPort(port_index); port->SetAlias(alias); fCapturePortList[i] = port_index; jack_log("JackMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index); } for (i = 0; i < fPlaybackChannels; i++) { snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1); snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1); if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { jack_error("driver: cannot register port for %s", name); return -1; } port = fGraphManager->GetPort(port_index); port->SetAlias(alias); fPlaybackPortList[i] = port_index; jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); } UpdateLatencies(); return 0; }
/* create a new SHM registry segment * * sets up global registry pointers, if successful * * returns: 0 if registry created successfully * nonzero error code if unable to allocate a new registry */ static int jack_create_registry (jack_shm_info_t *ri) { /* registry must be locked */ int shm_fd; strncpy (registry_id, "/jack-shm-registry", sizeof (registry_id)); if ((shm_fd = shm_open (registry_id, O_RDWR|O_CREAT, 0666)) < 0) { int rc = errno; jack_error ("Cannot create shm registry segment (%s)", strerror (errno)); return rc; } /* Previous shm_open result depends of the actual value of umask, force correct file permisssion here */ if (fchmod(shm_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) < 0) { jack_log("Cannot chmod jack-shm-registry (%s) %d %d", strerror (errno)); } /* Set the desired segment size. NOTE: the non-conformant Mac * OS X POSIX shm only allows ftruncate() on segment creation. */ if (ftruncate (shm_fd, JACK_SHM_REGISTRY_SIZE) < 0) { int rc = errno; jack_error ("Cannot set registry size (%s)", strerror (errno)); jack_remove_shm (®istry_id); close (shm_fd); return rc; } if ((ri->ptr.attached_at = mmap (0, JACK_SHM_REGISTRY_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0)) == MAP_FAILED) { jack_error ("Cannot mmap shm registry segment (%s)", strerror (errno)); jack_remove_shm (®istry_id); close (shm_fd); return EINVAL; } /* set up global pointers */ ri->index = JACK_SHM_REGISTRY_INDEX; jack_shm_header = ri->ptr.attached_at; jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1); /* initialize registry contents */ jack_shm_init_registry (); close (shm_fd); return 0; }
int JackInternalClient::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) { int result; char name_res[JACK_CLIENT_NAME_SIZE + 1]; jack_log("JackInternalClient::Open name = %s", name); strncpy(fServerName, server_name, sizeof(fServerName)); fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); if (result < 0) { int status1 = *status; if (status1 & JackVersionError) jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION); else jack_error("Client name = %s conflits with another running client", name); goto error; } strcpy(fClientControl.fName, name_res); // Require new client fChannel->ClientOpen(name_res, &fClientControl.fRefNum, &fEngineControl, &fGraphManager, this, &result); if (result < 0) { jack_error("Cannot open client name = %s", name_res); goto error; } SetupDriverSync(false); JackGlobals::fClientTable[fClientControl.fRefNum] = this; JackGlobals::fServerRunning = true; jack_log("JackInternalClient::Open name = %s refnum = %ld", name_res, fClientControl.fRefNum); return 0; error: fChannel->Stop(); fChannel->Close(); return -1; }
int JackServer::Stop() { jack_log("JackServer::Stop"); fEngine->NotifyQuit(); fChannel.Stop(); fEngine->ShutDown(); if (fFreewheel) { return fThreadedFreewheelDriver->Stop(); } else { return fAudioDriver->Stop(); } }
bool JackNetAdapter::Init() { jack_log("JackNetAdapter::Init"); //init network connection if (!JackNetSlaveInterface::Init()) { jack_error("JackNetSlaveInterface::Init() error..."); return false; } //then set global parameters if (!SetParams()) { jack_error("SetParams error..."); return false; } //set buffers if (fCaptureChannels > 0) { fSoftCaptureBuffer = new sample_t*[fCaptureChannels]; for (int port_index = 0; port_index < fCaptureChannels; port_index++) { fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize]; fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]); } } if (fPlaybackChannels > 0) { fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels]; for (int port_index = 0; port_index < fPlaybackChannels; port_index++) { fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize]; fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]); } } //set audio adapter parameters SetAdaptedBufferSize(fParams.fPeriodSize); SetAdaptedSampleRate(fParams.fSampleRate); // Will do "something" on OSX only... fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) { jack_error("AcquireSelfRealTime error"); } else { set_threaded_log_function(); } //init done, display parameters SessionParamsDisplay(&fParams); return true; }
// Server to client int JackSocketNotifyChannel::Open(const char* name) { jack_log("JackSocketNotifyChannel::Open name = %s", name); // Connect to client listen socket if (fNotifySocket.Connect(jack_client_dir, name, 0) < 0) { jack_error("Cannot connect client socket"); return -1; } // Use a time out for notifications fNotifySocket.SetReadTimeOut(SOCKET_TIME_OUT); return 0; }
// 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 JackWinThread::Kill() { if (fThread != (HANDLE)NULL) { // If thread has been started TerminateThread(fThread, 0); WaitForSingleObject(fThread, INFINITE); CloseHandle(fThread); jack_log("JackWinThread::Kill"); fThread = (HANDLE)NULL; fStatus = kIdle; return 0; } else { return -1; } }
void JackClient::ShutDown(jack_status_t code, const char* message) { jack_log("JackClient::ShutDown"); // If "fInfoShutdown" callback, then call it if (fInfoShutdown) { fInfoShutdown(code, message, fInfoShutdownArg); fInfoShutdown = NULL; // Otherwise possibly call the normal "fShutdown" } else if (fShutdown) { fShutdown(fShutdownArg); fShutdown = NULL; } }
bool JackNetSlaveInterface::SetParams() { jack_log("JackNetSlaveInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d", fParams.fSendAudioChannels, fParams.fReturnAudioChannels, fParams.fSendMidiChannels, fParams.fReturnMidiChannels); JackNetInterface::SetParams(); fTxHeader.fDataStream = 'r'; fRxHeader.fDataStream = 's'; // midi net buffers if (fParams.fSendMidiChannels > 0) { fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fRxData); } if (fParams.fReturnMidiChannels > 0) { fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fTxData); } try { // audio net buffers if (fParams.fSendAudioChannels > 0) { fNetAudioCaptureBuffer = AudioBufferFactory(fParams.fSendAudioChannels, fRxData); assert(fNetAudioCaptureBuffer); } if (fParams.fReturnAudioChannels > 0) { fNetAudioPlaybackBuffer = AudioBufferFactory(fParams.fReturnAudioChannels, fTxData); assert(fNetAudioPlaybackBuffer); } } catch (exception&) { jack_error("NetAudioBuffer on slave allocation error..."); return false; } // set the new buffer sizes if (SetNetBufferSize() == SOCKET_ERROR) { jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); goto error; } return true; error: FreeNetworkBuffers(); return false; }
int JackPosixThread::Kill() { if (fThread != (jack_native_thread_t)NULL) { // If thread has been started jack_log("JackPosixThread::Kill"); void* status; pthread_cancel(fThread); pthread_join(fThread, &status); fStatus = kIdle; fThread = (jack_native_thread_t)NULL; return 0; } else { return -1; } }
void JackClient::SetupRealTime() { jack_log("JackClient::Init : period = %ld computation = %ld constraint = %ld", long(int64_t(GetEngineControl()->fPeriod) / 1000.0f), long(int64_t(GetEngineControl()->fComputation) / 1000.0f), long(int64_t(GetEngineControl()->fConstraint) / 1000.0f)); // Will do "something" on OSX only... fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) { jack_error("JackClient::AcquireSelfRealTime error"); } }
int JackMMCSS::MMCSSDropRealTime(jack_native_thread_t thread) { if (fHandleTable.find(thread) != fHandleTable.end()) { HANDLE task = fHandleTable[thread]; if (ffMMCSSFun3(task) == 0) { jack_error("AvRevertMmThreadCharacteristics error : %d", GetLastError()); } else { jack_log("AvRevertMmThreadCharacteristics success"); } return 0; } else { return -1; } }
int JackWinNamedPipeServerChannel::Open(const char* server_name, JackServer* server) { jack_log("JackWinNamedPipeServerChannel::Open"); snprintf(fServerName, sizeof(fServerName), server_name); // Needed for internal connection from JackWinNamedPipeServerNotifyChannel object if (ClientListen()) { fServer = server; return 0; } else { jack_error("JackWinNamedPipeServerChannel::Open : cannot create result listen pipe"); return -1; } }
// Server side : destroy the JackGlobals void JackMachSemaphore::Destroy() { kern_return_t res; if (fSemaphore > 0) { jack_log("JackMachSemaphore::Destroy name = %s", fName); if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) { jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res)); } fSemaphore = 0; } else { jack_error("JackMachSemaphore::Destroy semaphore < 0"); } }
int JackWinThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg) { DWORD id; *thread = CreateThread(NULL, 0, start_routine, arg, 0, &id); if (*thread == NULL) { jack_error("Cannot create thread error = %d", GetLastError()); return -1; } if (realtime) { jack_log("JackWinThread::StartImp : create RT thread"); if (!SetThreadPriority(*thread, THREAD_PRIORITY_TIME_CRITICAL)) { jack_error("Cannot set priority class = %d", GetLastError()); return -1; } } else { jack_log("JackWinThread::StartImp : create non RT thread"); } return 0; }
int JackClient::PortDisconnect(const char* src, const char* dst) { jack_log("JackClient::Disconnect src = %s dst = %s", src, dst); if (strlen(src) >= REAL_JACK_PORT_NAME_SIZE) { jack_error("\"%s\" is too long to be used as a JACK port name.\n", src); return -1; } if (strlen(dst) >= REAL_JACK_PORT_NAME_SIZE) { jack_error("\"%s\" is too long to be used as a JACK port name.\n", src); return -1; } int result = -1; fChannel->PortDisconnect(GetClientControl()->fRefNum, src, dst, &result); return result; }
int JackClient::PortUnRegister(jack_port_id_t port_index) { jack_log("JackClient::PortUnRegister port_index = %ld", port_index); list<jack_port_id_t>::iterator it = find(fPortList.begin(), fPortList.end(), port_index); if (it != fPortList.end()) { fPortList.erase(it); int result = -1; fChannel->PortUnRegister(GetClientControl()->fRefNum, port_index, &result); return result; } else { jack_error("unregistering a port %ld that is not own by the client", port_index); return -1; } }
/*! \brief Need to stop thread after deactivating in the server. */ int JackClient::Deactivate() { jack_log("JackClient::Deactivate"); if (!IsActive()) { return 0; } GetClientControl()->fActive = false; // Transport related callback become "unactive" GetClientControl()->fTransportSync = false; GetClientControl()->fTransportTimebase = false; // We need to wait for the new engine cycle before stopping the RT thread, but this is done by ClientDeactivate int result = -1; fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); jack_log("JackClient::Deactivate res = %ld", result); // RT thread is stopped only when needed... if (IsRealTime()) { fThread.Kill(); } return result; }
int JackClient::SessionReply(jack_session_event_t* ev) { if (ev->command_line) { strncpy(GetClientControl()->fSessionCommand, ev->command_line, sizeof(GetClientControl()->fSessionCommand)); } else { GetClientControl()->fSessionCommand[0] = '\0'; } GetClientControl()->fSessionFlags = ev->flags; jack_log("JackClient::SessionReply... we are here"); if (fChannel->IsChannelThread()) { jack_log("JackClient::SessionReply... in callback reply"); // OK, immediate reply... fSessionReply = kImmediateSessionReply; return 0; } jack_log("JackClient::SessionReply... out of cb"); int result = -1; fChannel->SessionReply(GetClientControl()->fRefNum, &result); return result; }
bool JackPosixSemaphore::Disconnect() { if (fSemaphore) { jack_log("JackPosixSemaphore::Disconnect name = %s", fName); if (sem_close(fSemaphore) != 0) { jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno)); return false; } else { fSemaphore = NULL; return true; } } else { return true; } }
bool JackFifo::Disconnect() { if (fFifo >= 0) { jack_log("JackFifo::Disconnect %s", fName); if (close(fFifo) != 0) { jack_error("Disconnect: can't disconnect named fifo name = %s err = %s", fName, strerror(errno)); return false; } else { fFifo = -1; return true; } } else { return true; } }
net_status_t JackNetSlaveInterface::SendStartToMaster() { jack_log("JackNetSlaveInterface::SendStartToMaster"); // tell the master to start session_params_t net_params; memset(&net_params, 0, sizeof(session_params_t)); SetPacketType(&fParams, START_MASTER); SessionParamsHToN(&fParams, &net_params); if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR) { jack_error("Error in send : %s", StrError(NET_ERROR_CODE)); return (fSocket.GetError() == NET_CONN_ERROR) ? NET_ERROR : NET_SEND_ERROR; } return NET_ROLLING; }
int JackMidiDriver::Detach() { int i; jack_log("JackMidiDriver::Detach"); for (i = 0; i < fCaptureChannels; i++) { fEngine->PortUnRegister(fClientControl.fRefNum, fCapturePortList[i]); } for (i = 0; i < fPlaybackChannels; i++) { fEngine->PortUnRegister(fClientControl.fRefNum, fPlaybackPortList[i]); } return 0; }
// Client side : get the published semaphore from server bool JackAndroidSemaphore::ConnectInput(const char* name, const char* server_name) { pthread_mutex_lock (&mutex); BuildName(name, server_name, fName, sizeof(fName)); jack_log("JackAndroidSemaphore::Connect name = %s", fName); // Temporary... if (fSemaphore) { jack_log("Already connected name = %s", name); pthread_mutex_unlock (&mutex); return true; } android::sp<android::IAndroidShm> service = android::Shm::getShmService(); if(service == NULL){ jack_error("shm service is null"); return false; } fSemaphoreMemory = service->InitSemaphore(fName); if(fSemaphoreMemory != NULL){ fSemaphore = (sem_t*)(fSemaphoreMemory->getBase()); } if(fSemaphore == NULL) { jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno)); pthread_mutex_unlock (&mutex); return false; } else { int val = 0; sem_getvalue(fSemaphore, &val); jack_log("JackAndroidSemaphore::Connect sem_getvalue %ld", val); pthread_mutex_unlock (&mutex); return true; } }
void JackSocketServerChannel::BuildPoolTable() { if (fRebuild) { fRebuild = false; delete[] fPollTable; fPollTable = new pollfd[fSocketTable.size() + 1]; jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1); // First fd is the server request socket fPollTable[0].fd = fRequestListenSocket.GetFd(); fPollTable[0].events = POLLIN | POLLERR; // Next fd for clients map<int, pair<int, JackClientSocket*> >::iterator it; int i; for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) { jack_log("JackSocketServerChannel::BuildPoolTable fSocketTable i = %ld fd = %ld", i, it->first); fPollTable[i].fd = it->first; fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; } } }