Commit 185f245a authored by Nedko Arnaudov's avatar Nedko Arnaudov
Browse files

Merge branch 'master' into no-self-connect

Conflicts:
	common/JackServer.cpp
parents 1685eec0 ed525406
This diff is collapsed.
......@@ -138,14 +138,13 @@ int JackAudioDriver::Attach()
// Monitor ports
if (fWithMonitorPorts) {
jack_log("Create monitor port ");
jack_log("Create monitor port");
snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1);
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) {
jack_error("Cannot register monitor port for %s", name);
return -1;
} else {
port = fGraphManager->GetPort(port_index);
port->SetAlias(alias);
range.min = range.max = fEngineControl->fBufferSize;
port->SetLatencyRange(JackCaptureLatency, &range);
fMonitorPortList[i] = port_index;
......@@ -313,6 +312,26 @@ int JackAudioDriver::ProcessGraphSync()
return res;
}
int JackAudioDriver::Start()
{
int res = JackDriver::Start();
if ((res >= 0) && fIsMaster) {
res = StartSlaves();
}
return res;
}
int JackAudioDriver::Stop()
{
int res = JackDriver::Stop();
if (fIsMaster) {
if (StopSlaves() < 0) {
res = -1;
}
}
return res;
}
void JackAudioDriver::WaitUntilNextCycle()
{
int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f));
......
......@@ -92,6 +92,9 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver
virtual int Attach();
virtual int Detach();
virtual int Start();
virtual int Stop();
virtual int Write();
virtual int SetBufferSize(jack_nframes_t buffer_size);
......
......@@ -496,8 +496,8 @@ bool JackClient::Init()
// Setup RT
if (GetEngineControl()->fRealTime) {
if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) {
jack_error("JackClient::AcquireRealTime error");
if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
jack_error("JackClient::AcquireSelfRealTime error");
}
}
......
......@@ -44,7 +44,7 @@ struct JackEngineControl;
\brief The base class for clients: share part of the implementation for JackInternalClient and JackLibClient.
*/
class JackClient : public JackClientInterface, public JackRunnableInterface
class SERVER_EXPORT JackClient : public JackClientInterface, public JackRunnableInterface
{
friend class JackDebugClient;
......@@ -195,15 +195,15 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
// RT Thread
jack_nframes_t CycleWait();
void CycleSignal(int status);
int SetProcessThread(JackThreadCallback fun, void *arg);
virtual int SetProcessThread(JackThreadCallback fun, void *arg);
// Session API
virtual jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path);
virtual int SessionReply(jack_session_event_t* ev);
char* GetUUIDForClientName(const char* client_name);
char* GetClientNameByUUID(const char* uuid);
int ReserveClientName(const char* client_name, const char* uuid);
int ClientHasSessionCallback(const char* client_name);
virtual char* GetUUIDForClientName(const char* client_name);
virtual char* GetClientNameByUUID(const char* uuid);
virtual int ReserveClientName(const char* client_name, const char* uuid);
virtual int ClientHasSessionCallback(const char* client_name);
// JackRunnableInterface interface
bool Init();
......
......@@ -463,21 +463,21 @@ sigset_t
jackctl_setup_signals(
unsigned int flags)
{
if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) {
jack_error("CreateEvent fails err = %ld", GetLastError());
return 0;
}
(void) signal(SIGINT, do_nothing_handler);
(void) signal(SIGINT, do_nothing_handler);
(void) signal(SIGABRT, do_nothing_handler);
(void) signal(SIGTERM, do_nothing_handler);
return (sigset_t)waitEvent;
return (sigset_t)waitEvent;
}
void jackctl_wait_signals(sigset_t signals)
{
if (WaitForSingleObject(waitEvent, INFINITE) != WAIT_OBJECT_0) {
if (WaitForSingleObject(waitEvent, INFINITE) != WAIT_OBJECT_0) {
jack_error("WaitForSingleObject fails err = %ld", GetLastError());
}
}
......@@ -552,7 +552,7 @@ jackctl_setup_signals(
* explicitly reset it
*/
pthread_sigmask(SIG_BLOCK, &signals, 0);
pthread_sigmask(SIG_BLOCK, &signals, 0);
/* install a do-nothing handler because otherwise pthreads
behaviour is undefined when we enter sigwait.
......@@ -873,6 +873,11 @@ EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr
EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
{
server_ptr->engine->Stop();
return true;
}
EXPORT bool jackctl_server_close(jackctl_server *server_ptr)
{
server_ptr->engine->Close();
delete server_ptr->engine;
......@@ -900,7 +905,7 @@ EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
}
EXPORT bool
jackctl_server_start(
jackctl_server_open(
jackctl_server *server_ptr,
jackctl_driver *driver_ptr)
{
......@@ -983,18 +988,8 @@ jackctl_server_start(
goto fail_delete;
}
rc = server_ptr->engine->Start();
if (rc < 0)
{
jack_error("JackServer::Start() failed with %d", rc);
goto fail_close;
}
return true;
fail_close:
server_ptr->engine->Close();
fail_delete:
delete server_ptr->engine;
server_ptr->engine = NULL;
......@@ -1016,6 +1011,19 @@ fail:
return false;
}
EXPORT bool
jackctl_server_start(
jackctl_server *server_ptr)
{
int rc = server_ptr->engine->Start();
bool result = rc >= 0;
if (! result)
{
jack_error("JackServer::Start() failed with %d", rc);
}
return result;
}
EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
{
return driver_ptr->desc_ptr->name;
......@@ -1272,8 +1280,13 @@ EXPORT bool jackctl_server_unload_internal(
EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
{
if (server_ptr->engine != NULL) {
driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters);
return (driver_ptr->info != 0);
if (server_ptr->engine->IsRunning()) {
jack_error("cannot add a slave in a running server");
return false;
} else {
driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters);
return (driver_ptr->info != 0);
}
} else {
return false;
}
......@@ -1282,9 +1295,14 @@ EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver
EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
{
if (server_ptr->engine != NULL) {
server_ptr->engine->RemoveSlave(driver_ptr->info);
delete driver_ptr->info;
return true;
if (server_ptr->engine->IsRunning()) {
jack_error("cannot remove a slave from a running server");
return false;
} else {
server_ptr->engine->RemoveSlave(driver_ptr->info);
delete driver_ptr->info;
return true;
}
} else {
return false;
}
......
......@@ -101,13 +101,21 @@ jackctl_server_get_drivers_list(
jackctl_server_t * server);
EXPORT bool
jackctl_server_start(
jackctl_server_open(
jackctl_server_t * server,
jackctl_driver_t * driver);
EXPORT bool
jackctl_server_start(
jackctl_server_t * server);
EXPORT bool
jackctl_server_stop(
jackctl_server_t * server);
jackctl_server_t * server);
EXPORT bool
jackctl_server_close(
jackctl_server_t * server);
EXPORT const JSList *
jackctl_server_get_parameters(
......
......@@ -505,6 +505,54 @@ int JackDebugClient::SetPortRenameCallback(JackPortRenameCallback callback, void
return fClient->SetPortRenameCallback(callback, arg);
}
int JackDebugClient::SetSessionCallback(JackSessionCallback callback, void *arg)
{
CheckClient("SetSessionCallback");
return fClient->SetSessionCallback(callback, arg);
}
int JackDebugClient::SetLatencyCallback(JackLatencyCallback callback, void *arg)
{
CheckClient("SetLatencyCallback");
return fClient->SetLatencyCallback(callback, arg);
}
jack_session_command_t* JackDebugClient::SessionNotify(const char* target, jack_session_event_type_t type, const char* path)
{
CheckClient("SessionNotify");
return fClient->SessionNotify(target, type, path);
}
int JackDebugClient::SessionReply(jack_session_event_t* ev)
{
CheckClient("SessionReply");
return fClient->SessionReply(ev);
}
char* JackDebugClient::GetUUIDForClientName(const char* client_name)
{
CheckClient("GetUUIDForClientName");
return fClient->GetUUIDForClientName(client_name);
}
char* JackDebugClient::GetClientNameByUUID(const char* uuid)
{
CheckClient("GetClientNameByUUID");
return fClient->GetClientNameByUUID(uuid);
}
int JackDebugClient::ReserveClientName(const char* client_name, const char* uuid)
{
CheckClient("ReserveClientName");
return fClient->ReserveClientName(client_name, uuid);
}
int JackDebugClient::ClientHasSessionCallback(const char* client_name)
{
CheckClient("ClientHasSessionCallback");
return fClient->ClientHasSessionCallback(client_name);
}
JackClientControl* JackDebugClient::GetClientControl() const
{
CheckClient("GetClientControl");
......
......@@ -46,7 +46,7 @@ PortFollower;
\brief A "decorator" debug client to validate API use.
*/
class JackDebugClient : public JackClient
class SERVER_EXPORT JackDebugClient : public JackClient
{
protected:
......@@ -121,6 +121,8 @@ class JackDebugClient : public JackClient
int SetPortRegistrationCallback(JackPortRegistrationCallback callback, void* arg);
int SetPortConnectCallback(JackPortConnectCallback callback, void *arg);
int SetPortRenameCallback(JackPortRenameCallback callback, void *arg);
int SetSessionCallback(JackSessionCallback callback, void *arg);
int SetLatencyCallback(JackLatencyCallback callback, void *arg);
// Internal clients
char* GetInternalClientName(int ref);
......@@ -128,6 +130,14 @@ class JackDebugClient : public JackClient
int InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va);
void InternalClientUnload(int ref, jack_status_t* status);
// Session API
jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path);
int SessionReply(jack_session_event_t* ev);
char* GetUUIDForClientName(const char* client_name);
char* GetClientNameByUUID(const char* uuid);
int ReserveClientName(const char* client_name, const char* uuid);
int ClientHasSessionCallback(const char* client_name);
JackClientControl* GetClientControl() const;
void CheckClient(const char* function_name) const;
......
......@@ -47,6 +47,7 @@ JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* en
fBeginDateUst = 0;
fDelayedUsecs = 0.f;
fIsMaster = true;
fIsRunning = false;
}
JackDriver::JackDriver()
......@@ -56,6 +57,7 @@ JackDriver::JackDriver()
fGraphManager = NULL;
fBeginDateUst = 0;
fIsMaster = true;
fIsRunning = false;
}
JackDriver::~JackDriver()
......@@ -80,7 +82,7 @@ int JackDriver::Open()
return 0;
}
int JackDriver::Open (bool capturing,
int JackDriver::Open(bool capturing,
bool playing,
int inchannels,
int outchannels,
......@@ -93,6 +95,15 @@ int JackDriver::Open (bool capturing,
jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
int refnum = -1;
char name_res[JACK_CLIENT_NAME_SIZE + 1];
int status;
// Check name and possibly rename
if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
jack_error("Client name = %s conflits with another running client", fClientControl.fName);
return -1;
}
strcpy(fClientControl.fName, name_res);
if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
jack_error("Cannot allocate internal client for driver");
......@@ -135,6 +146,15 @@ int JackDriver::Open(jack_nframes_t buffer_size,
jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name);
jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name);
int refnum = -1;
char name_res[JACK_CLIENT_NAME_SIZE + 1];
int status;
// Check name and possibly rename
if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) {
jack_error("Client name = %s conflits with another running client", fClientControl.fName);
return -1;
}
strcpy(fClientControl.fName, name_res);
if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) {
jack_error("Cannot allocate internal client for driver");
......@@ -288,6 +308,7 @@ int JackDriver::ProcessSlaves()
JackDriverInterface* slave = *it;
if (slave->Process() < 0)
res = -1;
}
return res;
}
......@@ -324,15 +345,49 @@ int JackDriver::Write()
int JackDriver::Start()
{
fEngineControl->InitFrameTime();
if (fIsMaster) {
fEngineControl->InitFrameTime();
}
fIsRunning = true;
return 0;
}
int JackDriver::StartSlaves()
{
int res = 0;
list<JackDriverInterface*>::const_iterator it;
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
JackDriverInterface* slave = *it;
if (slave->Start() < 0) {
res = -1;
// XXX: We should attempt to stop all of the slaves that we've
// started here.
break;
}
}
return res;
}
int JackDriver::Stop()
{
fIsRunning = false;
return 0;
}
int JackDriver::StopSlaves()
{
int res = 0;
list<JackDriverInterface*>::const_iterator it;
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
JackDriverInterface* slave = *it;
if (slave->Stop() < 0)
res = -1;
}
return res;
}
bool JackDriver::IsFixedBufferSize()
{
return true;
......
......@@ -97,6 +97,7 @@ class SERVER_EXPORT JackDriverInterface
virtual int ProcessSlaves() = 0;
virtual bool IsRealTime() const = 0;
virtual bool IsRunning() const = 0;
};
/*!
......@@ -134,6 +135,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface
JackClientControl fClientControl;
std::list<JackDriverInterface*> fSlaveList;
bool fIsMaster;
bool fIsRunning;
void CycleIncTime();
void CycleTakeBeginTime();
......@@ -198,7 +200,9 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface
virtual int Write();
virtual int Start();
virtual int StartSlaves();
virtual int Stop();
virtual int StopSlaves();
virtual bool IsFixedBufferSize();
virtual int SetBufferSize(jack_nframes_t buffer_size);
......@@ -208,6 +212,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface
virtual JackClientControl* GetClientControl() const;
virtual bool IsRealTime() const;
virtual bool IsRunning() const { return fIsRunning; }
virtual bool Initialize(); // To be called by the wrapping thread Init method when the driver is a "blocking" one
};
......
......@@ -119,7 +119,7 @@ jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSL
desc->name);
}
printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name);
jack_log("Parameters for driver '%s' (all parameters are optional):", desc->name);
jack_print_driver_options (desc, stdout);
return 1;
}
......@@ -263,7 +263,7 @@ jackctl_parse_driver_params (jackctl_driver *driver_ptr, int argc, char* argv[])
desc->name);
}
printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name);
jack_log("Parameters for driver '%s' (all parameters are optional):", desc->name);
jack_print_driver_options (desc, stdout);
return 1;
}
......
......@@ -225,7 +225,6 @@ int JackEngine::ComputeTotalLatencies()
*/
for (it = sorted.begin(); it != sorted.end(); it++) {
jack_log("Sorted %d", *it);
NotifyClient(*it, kLatencyCallback, true, "", 0, 0);
}
......@@ -324,8 +323,8 @@ void JackEngine::NotifyXRun(int refnum)
void JackEngine::NotifyGraphReorder()
{
ComputeTotalLatencies();
NotifyClients(kGraphOrderCallback, false, "", 0, 0);
ComputeTotalLatencies();
}
void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size)
......@@ -522,7 +521,7 @@ void JackEngine::EnsureUUID(int uuid)
for (int i = 0; i < CLIENT_NUM; i++) {
JackClientInterface* client = fClientTable[i];
if (client && (client->GetClientControl()->fSessionID==uuid)) {
if (client && (client->GetClientControl()->fSessionID == uuid)) {
client->GetClientControl()->fSessionID = GetNewUUID();
}
}
......@@ -553,13 +552,13 @@ int JackEngine::GetClientRefNum(const char* name)
// Used for external clients
int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager)
{
char real_name[JACK_CLIENT_NAME_SIZE+1];
char real_name[JACK_CLIENT_NAME_SIZE + 1];
if (uuid < 0) {
uuid = GetNewUUID();
strncpy(real_name, name, JACK_CLIENT_NAME_SIZE);
} else {
std::map<int,std::string>::iterator res = fReservationMap.find(uuid);
std::map<int, std::string>::iterator res = fReservationMap.find(uuid);
if (res != fReservationMap.end()) {
strncpy(real_name, res->second.c_str(), JACK_CLIENT_NAME_SIZE);
fReservationMap.erase(uuid);
......@@ -570,7 +569,7 @@ int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref
EnsureUUID(uuid);
}
jack_log("JackEngine::ClientExternalOpen: uuid=%d, name = %s ", uuid, real_name);
jack_log("JackEngine::ClientExternalOpen: uuid = %d, name = %s ", uuid, real_name);
int refnum = AllocateRefnum();
if (refnum < 0) {
......@@ -764,7 +763,7 @@ int JackEngine::ClientDeactivate(int refnum)
fGraphManager->GetInputPorts(refnum, input_ports);
fGraphManager->GetOutputPorts(refnum, output_ports);
// First disconnect all ports and remove their JackPortIsActive state
// First disconnect all ports
for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) {
PortDisconnect(-1, input_ports[i], ALL_PORTS);
}
......@@ -1038,7 +1037,7 @@ void JackEngine::SessionNotify(int refnum, const char *target, jack_session_even
if (client && client->GetClientControl()->fCallback[kSessionCallback]) {
// check if this is a notification to a specific client.
if (target!=NULL && strlen(target)!=0) {
if (target != NULL && strlen(target) != 0) {
if (strcmp(target, client->GetClientControl()->fName)) {
continue;
}
......@@ -1098,7 +1097,7 @@ void JackEngine::GetUUIDForClientName(const char *client_name, char *uuid_res, i
for (int i = 0; i < CLIENT_NUM; i++) {
JackClientInterface* client = fClientTable[i];
if (client && (strcmp(client_name, client->GetClientControl()->fName)==0)) {
if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) {
snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID);
*result = 0;
return;
......
......@@ -123,7 +123,7 @@ int JackLoadableInternalClient::Init(const char* so_name)
{
char path_to_so[JACK_PATH_MAX + 1];
BuildClientPath(path_to_so, sizeof(path_to_so), so_name);
fHandle = LoadJackModule(path_to_so);
jack_log("JackLoadableInternalClient::JackLoadableInternalClient path_to_so = %s", path_to_so);
......@@ -151,7 +151,7 @@ int JackLoadableInternalClient1::Init(const char* so_name)
if (JackLoadableInternalClient::Init(so_name) < 0) {
return -1;
}
fInitialize = (InitializeCallback)GetJackProc(fHandle, "jack_initialize");
if (fInitialize == NULL) {
UnloadJackModule(fHandle);
......@@ -167,7 +167,7 @@ int JackLoadableInternalClient2::Init(const char* so_name)
if (JackLoadableInternalClient::Init(so_name) < 0) {
return -1;
}
fInitialize = (InternalInitializeCallback)GetJackProc(fHandle, "jack_internal_initialize");
if (fInitialize == NULL) {
UnloadJackModule(fHandle);
......@@ -181,7 +181,7 @@ int JackLoadableInternalClient2::Init(const char* so_name)
JackLoadableInternalClient1::JackLoadableInternalClient1(JackServer* server, JackSynchro* table, const char* object_data)
: JackLoadableInternalClient(server, table)
{
strncpy(fObjectData, object_data, JACK_LOAD_INIT_LIMIT);
strncpy(fObjectData, object_data, JACK_LOAD_INIT_LIMIT);
}
JackLoadableInternalClient2::JackLoadableInternalClient2(JackServer* server, JackSynchro* table, const JSList* parameters)
......@@ -201,7 +201,7 @@ JackLoadableInternalClient::~JackLoadableInternalClient()
int JackLoadableInternalClient1::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status)