Commit c8f9a50d authored by sletz's avatar sletz
Browse files

Merge branch 'server-ctl-proposal'

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4219 0c269be4-1314-0410-8aa9-9f06e86f4224
parents f8d78dc7 991167f5
......@@ -312,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);
......
......@@ -826,6 +826,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;
......@@ -853,7 +858,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)
{
......@@ -913,18 +918,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;
......@@ -946,6 +941,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;
......@@ -1202,8 +1210,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;
}
......@@ -1212,9 +1225,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(
......
......@@ -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()
......@@ -288,6 +290,7 @@ int JackDriver::ProcessSlaves()
JackDriverInterface* slave = *it;
if (slave->Process() < 0)
res = -1;
}
return res;
}
......@@ -324,15 +327,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
};
......
......@@ -49,7 +49,16 @@ JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int prio
fGraphManager = JackGraphManager::Allocate(port_max);
fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name);
fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl);
fFreewheelDriver = new JackThreadedDriver(new JackFreewheelDriver(fEngine, GetSynchroTable()));
// A distinction is made between the threaded freewheel driver and the
// regular freewheel driver because the freewheel driver needs to run in
// threaded mode when freewheel mode is active and needs to run as a slave
// when freewheel mode isn't active.
JackFreewheelDriver *freewheelDriver =
new JackFreewheelDriver(fEngine, GetSynchroTable());
fThreadedFreewheelDriver = new JackThreadedDriver(freewheelDriver);
fFreewheelDriver = freewheelDriver;
fDriverInfo = new JackDriverInfo();
fAudioDriver = NULL;
fFreewheel = false;
......@@ -62,7 +71,7 @@ JackServer::~JackServer()
{
JackGraphManager::Destroy(fGraphManager);
delete fDriverInfo;
delete fFreewheelDriver;
delete fThreadedFreewheelDriver;
delete fEngine;
delete fEngineControl;
}
......@@ -87,8 +96,8 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
goto fail_close3;
}
if (fFreewheelDriver->Open() < 0) { // before engine open
jack_error("Cannot open driver");
if (fFreewheelDriver->Open() < 0) {
jack_error("Cannot open freewheel driver");
goto fail_close4;
}
......@@ -99,7 +108,7 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
fFreewheelDriver->SetMaster(false);
fAudioDriver->SetMaster(true);
fAudioDriver->AddSlave(fFreewheelDriver); // After ???
fAudioDriver->AddSlave(fFreewheelDriver);
InitTime();
SetClockSource(fEngineControl->fClockSource);
return 0;
......@@ -179,7 +188,18 @@ int JackServer::Start()
int JackServer::Stop()
{
jack_log("JackServer::Stop");
return fAudioDriver->Stop();
if (fFreewheel) {
return fThreadedFreewheelDriver->Stop();
} else {
return fAudioDriver->Stop();
}
}
bool JackServer::IsRunning()
{
jack_log("JackServer::IsRunning");
assert(fAudioDriver);
return fAudioDriver->IsRunning();
}
int JackServer::SetBufferSize(jack_nframes_t buffer_size)
......@@ -237,10 +257,11 @@ int JackServer::SetFreewheel(bool onoff)
return -1;
} else {
fFreewheel = false;
fFreewheelDriver->Stop();
fThreadedFreewheelDriver->Stop();
fGraphManager->Restore(&fConnectionState); // Restore previous connection state
fEngine->NotifyFreewheel(onoff);
fFreewheelDriver->SetMaster(false);
fAudioDriver->SetMaster(true);
return fAudioDriver->Start();
}
} else {
......@@ -250,8 +271,9 @@ int JackServer::SetFreewheel(bool onoff)
fGraphManager->Save(&fConnectionState); // Save connection state
fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum);
fEngine->NotifyFreewheel(onoff);
fAudioDriver->SetMaster(false);
fFreewheelDriver->SetMaster(true);
return fFreewheelDriver->Start();
return fThreadedFreewheelDriver->Start();
} else {
return -1;
}
......@@ -270,7 +292,6 @@ void JackServer::Notify(int refnum, int notify, int value)
case kXRunCallback:
fEngine->NotifyXRun(refnum);
break;
}
}
......@@ -296,11 +317,11 @@ JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* dr
if (slave == NULL) {
delete info;
return NULL;
} else {
slave->Attach();
fAudioDriver->AddSlave(slave);
return info;
}
slave->Attach();
slave->SetMaster(false);
fAudioDriver->AddSlave(slave);
return info;
}
void JackServer::RemoveSlave(JackDriverInfo* info)
......@@ -325,28 +346,27 @@ int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_par
if (master == NULL) {
delete info;
return -1;
} else {
}
// Get slaves list
std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves();
std::list<JackDriverInterface*>::const_iterator it;
// Get slaves list
std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves();
std::list<JackDriverInterface*>::const_iterator it;
// Move slaves in new master
for (it = slave_list.begin(); it != slave_list.end(); it++) {
JackDriverInterface* slave = *it;
master->AddSlave(slave);
}
// Move slaves in new master
for (it = slave_list.begin(); it != slave_list.end(); it++) {
JackDriverInterface* slave = *it;
master->AddSlave(slave);
}
// Delete old master
delete fDriverInfo;
// Delete old master
delete fDriverInfo;
// Activate master
fAudioDriver = master;
fDriverInfo = info;
fAudioDriver->Attach();
fAudioDriver->SetMaster(true);
return fAudioDriver->Start();
}
// Activate master
fAudioDriver = master;
fDriverInfo = info;
fAudioDriver->Attach();
fAudioDriver->SetMaster(true);
return fAudioDriver->Start();
}
//----------------------
......
......@@ -50,6 +50,7 @@ class SERVER_EXPORT JackServer
JackDriverInfo* fDriverInfo;
JackDriverClientInterface* fAudioDriver;
JackDriverClientInterface* fFreewheelDriver;
JackDriverClientInterface* fThreadedFreewheelDriver;
JackLockedEngine* fEngine;
JackEngineControl* fEngineControl;
JackGraphManager* fGraphManager;
......@@ -70,6 +71,7 @@ class SERVER_EXPORT JackServer
int Start();
int Stop();
bool IsRunning();
// RT thread
void Notify(int refnum, int notify, int value);
......
......@@ -152,6 +152,11 @@ bool JackThreadedDriver::IsRealTime() const
return fDriver->IsRealTime();
}
bool JackThreadedDriver::IsRunning() const
{
return fDriver->IsRunning();
}
int JackThreadedDriver::Start()
{
jack_log("JackThreadedDriver::Start");
......@@ -171,9 +176,9 @@ int JackThreadedDriver::Start()
int JackThreadedDriver::Stop()
{
jack_log("JackThreadedDriver::Stop");
switch (fThread.GetStatus()) {
// Kill the thread in Init phase
case JackThread::kStarting:
case JackThread::kIniting:
......@@ -182,15 +187,15 @@ int JackThreadedDriver::Stop()
return -1;
}
break;
// Stop when the thread cycle is finished
case JackThread::kRunning:
if (fThread.Stop() < 0) {
jack_error("Cannot stop thread");
jack_error("Cannot stop thread");
return -1;
}
break;
default:
break;
}
......@@ -218,7 +223,7 @@ bool JackThreadedDriver::Init()
if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
jack_error("AcquireSelfRealTime error");
} else {
set_threaded_log_function();
set_threaded_log_function();
}
}
return true;
......
......@@ -38,14 +38,14 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi
JackThread fThread;
JackDriver* fDriver;
public:
JackThreadedDriver(JackDriver* driver);
virtual ~JackThreadedDriver();
virtual int Open();
virtual int Open (bool capturing,
bool playing,
int inchannels,
......@@ -54,7 +54,7 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi
const char* capture_driver_name,
const char* playback_driver_name,
jack_nframes_t capture_latency,
jack_nframes_t playback_latency)
jack_nframes_t playback_latency)
{
return -1;
}
......@@ -70,34 +70,35 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi
jack_nframes_t capture_latency,
jack_nframes_t playback_latency);
virtual int Close();
virtual int Process();
virtual int ProcessNull();
virtual int Attach();
virtual int Detach();
virtual int Read();
virtual int Write();
virtual int Start();
virtual int Stop();
virtual bool IsFixedBufferSize();
virtual int SetBufferSize(jack_nframes_t buffer_size);
virtual int SetSampleRate(jack_nframes_t sample_rate);
virtual void SetMaster(bool onoff);
virtual bool GetMaster();
virtual void AddSlave(JackDriverInterface* slave);
virtual void RemoveSlave(JackDriverInterface* slave);
virtual std::list<JackDriverInterface*> GetSlaves();
virtual int ProcessSlaves();
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);
virtual JackClientControl* GetClientControl() const;
virtual bool IsRealTime() const;
virtual bool IsRunning() const;
// JackRunnableInterface interface
virtual bool Execute();
virtual bool Init();
......
......@@ -244,6 +244,10 @@ int main(int argc, char* argv[])
std::list<char*> slaves_list;
std::list<char*>::iterator it;
// Assume that we fail.
int return_value = -1;
bool notify_sent = false;
copyright(stdout);
#if defined(JACK_DBUS) && defined(__linux__)
server_ctl = jackctl_server_create(audio_acquire, audio_release);
......@@ -285,7 +289,7 @@ int main(int argc, char* argv[])
jackctl_parameter_set_value(param, &value);
} else {
usage(stdout);
goto fail_free1;
goto destroy_server;
}
}
break;
......@@ -402,7 +406,7 @@ int main(int argc, char* argv[])
case 'h':
usage(stdout);
goto fail_free1;
goto destroy_server;
}
}
......@@ -423,14 +427,14 @@ int main(int argc, char* argv[])
if (!master_driver_name) {
usage(stderr);
goto fail_free1;
goto destroy_server;
}
// Master driver
master_driver_ctl = jackctl_server_get_driver(server_ctl, master_driver_name);
if (master_driver_ctl == NULL) {
fprintf(stderr, "Unknown driver \"%s\"\n", master_driver_name);
goto fail_free1;
goto destroy_server;
}
if (optind < argc) {
......@@ -442,7 +446,7 @@ int main(int argc, char* argv[])
if (master_driver_nargs == 0) {
fprintf(stderr, "No driver specified ... hmm. JACK won't do"
" anything when run like this.\n");
goto fail_free1;
goto destroy_server;
}
master_driver_args = (char **) malloc(sizeof(char *) * master_driver_nargs);
......@@ -453,15 +457,16 @@ int main(int argc, char* argv[])
}
if (jackctl_parse_driver_params(master_driver_ctl, master_driver_nargs, master_driver_args)) {
goto fail_free1;
goto destroy_server;
}
// Setup signals then start server
// Setup signals
signals = jackctl_setup_signals(0);
if (!jackctl_server_start(server_ctl, master_driver_ctl)) {
fprintf(stderr, "Failed to start server\n");
goto fail_free1;
// Open server
if (! jackctl_server_open(server_ctl, master_driver_ctl)) {
fprintf(stderr, "Failed to open server\n");
goto destroy_server;
}
// Slave drivers