diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp index 074078c4..272c1e66 100644 --- a/common/JackAudioDriver.cpp +++ b/common/JackAudioDriver.cpp @@ -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)); diff --git a/common/JackAudioDriver.h b/common/JackAudioDriver.h index 3127f4c1..8eaca692 100644 --- a/common/JackAudioDriver.h +++ b/common/JackAudioDriver.h @@ -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); diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp index df52735d..4ff69adc 100644 --- a/common/JackControlAPI.cpp +++ b/common/JackControlAPI.cpp @@ -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; } diff --git a/common/JackControlAPI.h b/common/JackControlAPI.h index d0b0cbc1..8e87d513 100644 --- a/common/JackControlAPI.h +++ b/common/JackControlAPI.h @@ -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( diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index a2c6ccd6..657524bd 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -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::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::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; diff --git a/common/JackDriver.h b/common/JackDriver.h index 6f230831..68f937c2 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -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 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 }; diff --git a/common/JackServer.cpp b/common/JackServer.cpp index 90baca3f..cd1915fb 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -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 slave_list = fAudioDriver->GetSlaves(); - std::list::const_iterator it; + // Get slaves list + std::list slave_list = fAudioDriver->GetSlaves(); + std::list::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(); } //---------------------- diff --git a/common/JackServer.h b/common/JackServer.h index 9c737d53..bdbd8ea8 100644 --- a/common/JackServer.h +++ b/common/JackServer.h @@ -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); diff --git a/common/JackThreadedDriver.cpp b/common/JackThreadedDriver.cpp index 52e49197..88323fe5 100644 --- a/common/JackThreadedDriver.cpp +++ b/common/JackThreadedDriver.cpp @@ -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; diff --git a/common/JackThreadedDriver.h b/common/JackThreadedDriver.h index f7bbf2d0..92ec1d26 100644 --- a/common/JackThreadedDriver.h +++ b/common/JackThreadedDriver.h @@ -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 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(); diff --git a/common/Jackdmp.cpp b/common/Jackdmp.cpp index 2e8a78e7..602aca31 100644 --- a/common/Jackdmp.cpp +++ b/common/Jackdmp.cpp @@ -244,6 +244,10 @@ int main(int argc, char* argv[]) std::list slaves_list; std::list::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 @@ -469,7 +474,7 @@ int main(int argc, char* argv[]) jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); if (slave_driver_ctl == NULL) { fprintf(stderr, "Unknown driver \"%s\"\n", *it); - goto fail_free2; + goto close_server; } jackctl_server_add_slave(server_ctl, slave_driver_ctl); } @@ -477,6 +482,8 @@ int main(int argc, char* argv[]) // Loopback driver if (loopback > 0) { loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback"); + + // XX: What if this fails? if (loopback_driver_ctl != NULL) { const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl); param = jackctl_get_parameter(loopback_parameters, "channels"); @@ -486,6 +493,13 @@ int main(int argc, char* argv[]) } jackctl_server_add_slave(server_ctl, loopback_driver_ctl); } + + } + + // Start the server + if (!jackctl_server_start(server_ctl)) { + fprintf(stderr, "Failed to start server\n"); + goto close_server; } // Internal clients @@ -493,30 +507,28 @@ int main(int argc, char* argv[]) jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); if (internal_driver_ctl == NULL) { fprintf(stderr, "Unknown internal \"%s\"\n", *it); - goto fail_free2; + goto stop_server; } jackctl_server_load_internal(server_ctl, internal_driver_ctl); } notify_server_start(server_name); + notify_sent = true; + return_value = 0; // Waits for signal jackctl_wait_signals(signals); - if (!jackctl_server_stop(server_ctl)) + stop_server: + if (! jackctl_server_stop(server_ctl)) { fprintf(stderr, "Cannot stop server...\n"); - - jackctl_server_destroy(server_ctl); - notify_server_stop(server_name); - return 0; - -fail_free1: - jackctl_server_destroy(server_ctl); - return -1; - -fail_free2: - jackctl_server_stop(server_ctl); + } + if (notify_sent) { + notify_server_stop(server_name); + } + close_server: + jackctl_server_close(server_ctl); + destroy_server: jackctl_server_destroy(server_ctl); - notify_server_stop(server_name); - return -1; + return return_value; } diff --git a/common/jack/control.h b/common/jack/control.h index caeb931d..b2c53ab0 100644 --- a/common/jack/control.h +++ b/common/jack/control.h @@ -4,7 +4,7 @@ Copyright (C) 2008 Nedko Arnaudov Copyright (C) 2008 GRAME - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. @@ -86,10 +86,10 @@ extern "C" { * @{ */ -/** +/** * Call this function to setup process signal handling. As a general * rule, it is required for proper operation for the server object. - * + * * @param flags signals setup flags, use 0 for none. Currently no * flags are defined * @@ -99,9 +99,9 @@ sigset_t jackctl_setup_signals( unsigned int flags); -/** +/** * Call this function to wait on a signal set. - * + * * @param signals signals set to wait on */ void @@ -123,43 +123,65 @@ jackctl_server_create( bool (* on_device_acquire)(const char * device_name), void (* on_device_release)(const char * device_name)); -/** +/** * Call this function to destroy server object. - * + * * @param server server object handle to destroy */ void jackctl_server_destroy( jackctl_server_t * server); -/** - * Call this function to start JACK server - * +/** + * Call this function to open JACK server + * * @param server server object handle * @param driver driver to use - * + * * @return success status: true - success, false - fail */ bool -jackctl_server_start( +jackctl_server_open( jackctl_server_t * server, jackctl_driver_t * driver); -/** +/** + * Call this function to start JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_start( + jackctl_server_t * server); + +/** * Call this function to stop JACK server - * + * * @param server server object handle - * + * * @return success status: true - success, false - fail */ bool jackctl_server_stop( jackctl_server_t * server); -/** +/** + * Call this function to close JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_close( + jackctl_server_t * server); + +/** * Call this function to get list of available drivers. List node data * pointers is a driver object handle (::jackctl_driver_t). - * + * * @param server server object handle to get drivers for * * @return Single linked list of driver object handles. Must not be @@ -169,10 +191,10 @@ const JSList * jackctl_server_get_drivers_list( jackctl_server_t * server); -/** +/** * Call this function to get list of server parameters. List node data * pointers is a parameter object handle (::jackctl_parameter_t). - * + * * @param server server object handle to get parameters for * * @return Single linked list of parameter object handles. Must not be @@ -182,10 +204,10 @@ const JSList * jackctl_server_get_parameters( jackctl_server_t * server); -/** +/** * Call this function to get list of available internal clients. List node data * pointers is a internal client object handle (::jackctl_internal_t). - * + * * @param server server object handle to get internal clients for * * @return Single linked list of internal client object handles. Must not be @@ -195,12 +217,13 @@ const JSList * jackctl_server_get_internals_list( jackctl_server_t * server); -/** +/** * Call this function to load one internal client. - * + * (can be used when the server is running) + * * @param server server object handle * @param internal internal to use - * + * * @return success status: true - success, false - fail */ bool @@ -208,12 +231,13 @@ jackctl_server_load_internal( jackctl_server_t * server, jackctl_internal_t * internal); -/** +/** * Call this function to unload one internal client. - * + * (can be used when the server is running) + * * @param server server object handle * @param internal internal to unload - * + * * @return success status: true - success, false - fail */ bool @@ -221,46 +245,50 @@ jackctl_server_unload_internal( jackctl_server_t * server, jackctl_internal_t * internal); -/** +/** * Call this function to add a slave in the driver slave list. - * + * (cannot be used when the server is running that is between + * jackctl_server_start and jackctl_server_stop) + * * @param server server object handle * @param driver driver to add in the driver slave list. - * + * * @return success status: true - success, false - fail - */ -bool + */ +bool jackctl_server_add_slave(jackctl_server_t * server, jackctl_driver_t * driver); -/** +/** * Call this function to remove a slave from the driver slave list. - * + * (cannot be used when the server is running that is between + * jackctl_server_start and jackctl_server_stop) + * * @param server server object handle * @param driver driver to remove from the driver slave list. - * + * * @return success status: true - success, false - fail - */ -bool + */ +bool jackctl_server_remove_slave(jackctl_server_t * server, jackctl_driver_t * driver); -/** +/** * Call this function to switch master driver. - * + * * @param server server object handle * @param driver driver to switch to - * + * * @return success status: true - success, false - fail - */ -bool + */ +bool jackctl_server_switch_master(jackctl_server_t * server, jackctl_driver_t * driver); - -/** + +/** * Call this function to get name of driver. - * + * * @param driver driver object handle to get name of * * @return driver name. Must not be modified. Always same for same @@ -270,10 +298,10 @@ const char * jackctl_driver_get_name( jackctl_driver_t * driver); -/** +/** * Call this function to get list of driver parameters. List node data * pointers is a parameter object handle (::jackctl_parameter_t). - * + * * @param driver driver object handle to get parameters for * * @return Single linked list of parameter object handles. Must not be @@ -283,9 +311,9 @@ const JSList * jackctl_driver_get_parameters( jackctl_driver_t * driver); -/** +/** * Call this function to get name of internal client. - * + * * @param internal internal object handle to get name of * * @return internal name. Must not be modified. Always same for same @@ -295,10 +323,10 @@ const char * jackctl_internal_get_name( jackctl_internal_t * internal); -/** +/** * Call this function to get list of internal parameters. List node data * pointers is a parameter object handle (::jackctl_parameter_t). - * + * * @param internal internal object handle to get parameters for * * @return Single linked list of parameter object handles. Must not be @@ -308,9 +336,9 @@ const JSList * jackctl_internal_get_parameters( jackctl_internal_t * internal); -/** +/** * Call this function to get parameter name. - * + * * @param parameter parameter object handle to get name of * * @return parameter name. Must not be modified. Always same for same @@ -320,9 +348,9 @@ const char * jackctl_parameter_get_name( jackctl_parameter_t * parameter); -/** +/** * Call this function to get parameter short description. - * + * * @param parameter parameter object handle to get short description of * * @return parameter short description. Must not be modified. Always @@ -332,9 +360,9 @@ const char * jackctl_parameter_get_short_description( jackctl_parameter_t * parameter); -/** +/** * Call this function to get parameter long description. - * + * * @param parameter parameter object handle to get long description of * * @return parameter long description. Must not be modified. Always @@ -344,9 +372,9 @@ const char * jackctl_parameter_get_long_description( jackctl_parameter_t * parameter); -/** +/** * Call this function to get parameter type. - * + * * @param parameter parameter object handle to get type of * * @return parameter type. Always same for same parameter object. @@ -355,21 +383,21 @@ jackctl_param_type_t jackctl_parameter_get_type( jackctl_parameter_t * parameter); -/** +/** * Call this function to get parameter character. - * + * * @param parameter parameter object handle to get character of * - * @return character. + * @return character. */ char jackctl_parameter_get_id( jackctl_parameter_t * parameter); -/** +/** * Call this function to check whether parameter has been set, or its * default value is being used. - * + * * @param parameter parameter object handle to check * * @return true - parameter is set, false - parameter is using default @@ -379,9 +407,9 @@ bool jackctl_parameter_is_set( jackctl_parameter_t * parameter); -/** +/** * Call this function to reset parameter to its default value. - * + * * @param parameter parameter object handle to reset value of * * @return success status: true - success, false - fail @@ -390,9 +418,9 @@ bool jackctl_parameter_reset( jackctl_parameter_t * parameter); -/** +/** * Call this function to get parameter value. - * + * * @param parameter parameter object handle to get value of * * @return parameter value. @@ -401,9 +429,9 @@ union jackctl_parameter_value jackctl_parameter_get_value( jackctl_parameter_t * parameter); -/** +/** * Call this function to set parameter value. - * + * * @param parameter parameter object handle to get value of * @param value_ptr pointer to variable containing parameter value * @@ -414,9 +442,9 @@ jackctl_parameter_set_value( jackctl_parameter_t * parameter, const union jackctl_parameter_value * value_ptr); -/** +/** * Call this function to get parameter default value. - * + * * @param parameter parameter object handle to get default value of * * @return parameter default value. @@ -424,10 +452,10 @@ jackctl_parameter_set_value( union jackctl_parameter_value jackctl_parameter_get_default_value( jackctl_parameter_t * parameter); - -/** + +/** * Call this function check whether parameter has range constraint. - * + * * @param parameter object handle of parameter to check * * @return whether parameter has range constraint. @@ -436,9 +464,9 @@ bool jackctl_parameter_has_range_constraint( jackctl_parameter_t * parameter); -/** +/** * Call this function check whether parameter has enumeration constraint. - * + * * @param parameter object handle of parameter to check * * @return whether parameter has enumeration constraint. @@ -447,9 +475,9 @@ bool jackctl_parameter_has_enum_constraint( jackctl_parameter_t * parameter); -/** +/** * Call this function get how many enumeration values parameter has. - * + * * @param parameter object handle of parameter * * @return number of enumeration values @@ -458,9 +486,9 @@ uint32_t jackctl_parameter_get_enum_constraints_count( jackctl_parameter_t * parameter); -/** +/** * Call this function to get parameter enumeration value. - * + * * @param parameter object handle of parameter * @param index index of parameter enumeration value * @@ -471,9 +499,9 @@ jackctl_parameter_get_enum_constraint_value( jackctl_parameter_t * parameter, uint32_t index); -/** +/** * Call this function to get parameter enumeration value description. - * + * * @param parameter object handle of parameter * @param index index of parameter enumeration value * @@ -484,9 +512,9 @@ jackctl_parameter_get_enum_constraint_description( jackctl_parameter_t * parameter, uint32_t index); -/** +/** * Call this function to get parameter range. - * + * * @param parameter object handle of parameter * @param min_ptr pointer to variable receiving parameter minimum value * @param max_ptr pointer to variable receiving parameter maximum value @@ -497,10 +525,10 @@ jackctl_parameter_get_range_constraint( union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr); -/** +/** * Call this function to check whether parameter constraint is strict, * i.e. whether supplying non-matching value will not work for sure. - * + * * @param parameter parameter object handle to check * * @return whether parameter constraint is strict. @@ -509,11 +537,11 @@ bool jackctl_parameter_constraint_is_strict( jackctl_parameter_t * parameter); -/** +/** * Call this function to check whether parameter has fake values, * i.e. values have no user meaningful meaning and only value * description is meaningful to user. - * + * * @param parameter parameter object handle to check * * @return whether parameter constraint is strict. @@ -522,9 +550,9 @@ bool jackctl_parameter_constraint_is_fake_value( jackctl_parameter_t * parameter); -/** +/** * Call this function to log an error message. - * + * * @param format string */ void @@ -532,9 +560,9 @@ jack_error( const char *format, ...); -/** +/** * Call this function to log an information message. - * + * * @param format string */ void @@ -542,10 +570,10 @@ jack_info( const char *format, ...); -/** +/** * Call this function to log an information message but only when * verbose mode is enabled. - * + * * @param format string */ void diff --git a/dbus/controller.c b/dbus/controller.c index 9c2bf3a5..77acef39 100644 --- a/dbus/controller.c +++ b/dbus/controller.c @@ -153,14 +153,21 @@ jack_controller_start_server( controller_ptr->xruns = 0; - if (!jackctl_server_start( + if (!jackctl_server_open( controller_ptr->server, controller_ptr->driver)) { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server"); goto fail; } + if (!jackctl_server_start( + controller_ptr->server)) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); + goto fail_close_server; + } + controller_ptr->client = jack_client_open( "dbusapi", JackNoStartServer, @@ -213,6 +220,12 @@ fail_stop_server: jack_error("failed to stop jack server"); } +fail_close_server: + if (!jackctl_server_close(controller_ptr->server)) + { + jack_error("failed to close jack server"); + } + fail: return FALSE; } @@ -250,6 +263,12 @@ jack_controller_stop_server( return FALSE; } + if (!jackctl_server_close(controller_ptr->server)) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to close server"); + return FALSE; + } + controller_ptr->started = false; return TRUE; diff --git a/example-clients/server_control.cpp b/example-clients/server_control.cpp index 64ec977c..46efa1bc 100644 --- a/example-clients/server_control.cpp +++ b/example-clients/server_control.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2008 Grame - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -74,23 +74,23 @@ jackctl_get_parameter( static void print_value(union jackctl_parameter_value value, jackctl_param_type_t type) { switch (type) { - + case JackParamInt: printf("parameter value = %d\n", value.i); break; - + case JackParamUInt: printf("parameter value = %u\n", value.ui); break; - + case JackParamChar: printf("parameter value = %c\n", value.c); break; - + case JackParamString: printf("parameter value = %s\n", value.str); break; - + case JackParamBool: printf("parameter value = %d\n", value.b); break; @@ -115,7 +115,7 @@ static void print_driver(jackctl_driver_t * driver) printf("\n--------------------------\n"); printf("driver = %s\n", jackctl_driver_get_name(driver)); printf("-------------------------- \n"); - print_parameters(jackctl_driver_get_parameters(driver)); + print_parameters(jackctl_driver_get_parameters(driver)); } static void print_internal(jackctl_internal_t * internal) @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) {"driver", 1, 0, 'd'}, {"client", 1, 0, 'c'}, }; - + while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { switch (opt) { case 'd': @@ -166,10 +166,10 @@ int main(int argc, char *argv[]) exit(0); } } - + server = jackctl_server_create(NULL, NULL); parameters = jackctl_server_get_parameters(server); - + /* jackctl_parameter_t* param; union jackctl_parameter_value value; @@ -179,58 +179,63 @@ int main(int argc, char *argv[]) jackctl_parameter_set_value(param, &value); } */ - + printf("\n========================== \n"); printf("List of server parameters \n"); printf("========================== \n"); - + print_parameters(parameters); - + printf("\n========================== \n"); printf("List of drivers \n"); printf("========================== \n"); - + drivers = jackctl_server_get_drivers_list(server); node_ptr = drivers; while (node_ptr != NULL) { print_driver((jackctl_driver_t *)node_ptr->data); node_ptr = jack_slist_next(node_ptr); } - + printf("\n========================== \n"); printf("List of internal clients \n"); printf("========================== \n"); - + internals = jackctl_server_get_internals_list(server); node_ptr = internals; while (node_ptr != NULL) { print_internal((jackctl_internal_t *)node_ptr->data); node_ptr = jack_slist_next(node_ptr); } - - jackctl_server_start(server, jackctl_server_get_driver(server, driver_name)); + + // No error checking in this simple example... + + jackctl_server_open(server, jackctl_server_get_driver(server, driver_name)); + jackctl_server_start(server); + jackctl_server_load_internal(server, jackctl_server_get_internal(server, client_name)); - + /* // Switch master test - + jackctl_driver_t* master; - + usleep(5000000); printf("jackctl_server_load_master\n"); master = jackctl_server_get_driver(server, "coreaudio"); jackctl_server_switch_master(server, master); - + usleep(5000000); printf("jackctl_server_load_master\n"); master = jackctl_server_get_driver(server, "dummy"); jackctl_server_switch_master(server, master); - + */ - + signals = jackctl_setup_signals(0); jackctl_wait_signals(signals); - + jackctl_server_stop(server); + jackctl_server_close(server); jackctl_server_destroy(server); return 0; } diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index 3cbe271a..b9f8c175 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -332,13 +332,23 @@ int JackAlsaDriver::Close() int JackAlsaDriver::Start() { - JackAudioDriver::Start(); - return alsa_driver_start((alsa_driver_t *)fDriver); + int res = JackAudioDriver::Start(); + if (res >= 0) { + res = alsa_driver_start((alsa_driver_t *)fDriver); + if (res < 0) { + JackAudioDriver::Stop(); + } + } + return res; } int JackAlsaDriver::Stop() { - return alsa_driver_stop((alsa_driver_t *)fDriver); + int res = alsa_driver_stop((alsa_driver_t *)fDriver); + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackAlsaDriver::Read() diff --git a/linux/firewire/JackFFADODriver.cpp b/linux/firewire/JackFFADODriver.cpp index 55bf70ce..2f855f37 100644 --- a/linux/firewire/JackFFADODriver.cpp +++ b/linux/firewire/JackFFADODriver.cpp @@ -653,13 +653,23 @@ int JackFFADODriver::Close() int JackFFADODriver::Start() { - JackAudioDriver::Start(); - return ffado_driver_start((ffado_driver_t *)fDriver); + int res = JackAudioDriver::Start(); + if (res >= 0) { + res = ffado_driver_start((ffado_driver_t *)fDriver); + if (res < 0) { + JackAudioDriver::Stop(); + } + } + return res; } int JackFFADODriver::Stop() { - return ffado_driver_stop((ffado_driver_t *)fDriver); + int res = ffado_driver_stop((ffado_driver_t *)fDriver); + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackFFADODriver::Read() diff --git a/linux/freebob/JackFreebobDriver.cpp b/linux/freebob/JackFreebobDriver.cpp index 96131d0b..03a26893 100644 --- a/linux/freebob/JackFreebobDriver.cpp +++ b/linux/freebob/JackFreebobDriver.cpp @@ -841,13 +841,23 @@ int JackFreebobDriver::Close() int JackFreebobDriver::Start() { - JackAudioDriver::Start(); - return freebob_driver_start((freebob_driver_t *)fDriver); + int res = JackAudioDriver::Start(); + if (res >= 0) { + res = freebob_driver_start((freebob_driver_t *)fDriver); + if (res < 0) { + JackAudioDriver::Stop(); + } + } + return res; } int JackFreebobDriver::Stop() { - return freebob_driver_stop((freebob_driver_t *)fDriver); + int res = freebob_driver_stop((freebob_driver_t *)fDriver); + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackFreebobDriver::Read() diff --git a/macosx/coreaudio/JackCoreAudioDriver.cpp b/macosx/coreaudio/JackCoreAudioDriver.cpp index 14ba69f4..83806646 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.cpp +++ b/macosx/coreaudio/JackCoreAudioDriver.cpp @@ -1678,33 +1678,38 @@ int JackCoreAudioDriver::Attach() int JackCoreAudioDriver::Start() { jack_log("JackCoreAudioDriver::Start"); - JackAudioDriver::Start(); + if (JackAudioDriver::Start() >= 0) { + OSStatus err = AudioOutputUnitStart(fAUHAL); + if (err == noErr) { - OSStatus err = AudioOutputUnitStart(fAUHAL); - if (err != noErr) - return -1; + // Waiting for Measure callback to be called (= driver has started) + fState = false; + int count = 0; + while (!fState && count++ < WAIT_COUNTER) { + usleep(100000); + jack_log("JackCoreAudioDriver::Start wait count = %d", count); + } - // Waiting for Measure callback to be called (= driver has started) - fState = false; - int count = 0; - while (!fState && count++ < WAIT_COUNTER) { - usleep(100000); - jack_log("JackCoreAudioDriver::Start wait count = %d", count); - } + if (count < WAIT_COUNTER) { + jack_info("CoreAudio driver is running..."); + return 0; + } - if (count < WAIT_COUNTER) { - jack_info("CoreAudio driver is running..."); - return 0; - } else { - jack_error("CoreAudio driver cannot start..."); - return -1; + jack_error("CoreAudio driver cannot start..."); + } + JackAudioDriver::Stop(); } + return -1; } int JackCoreAudioDriver::Stop() { jack_log("JackCoreAudioDriver::Stop"); - return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1; + int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1; + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) diff --git a/windows/portaudio/JackPortAudioDriver.cpp b/windows/portaudio/JackPortAudioDriver.cpp index 1732102f..41a3deb2 100644 --- a/windows/portaudio/JackPortAudioDriver.cpp +++ b/windows/portaudio/JackPortAudioDriver.cpp @@ -191,16 +191,25 @@ error: int JackPortAudioDriver::Start() { jack_log("JackPortAudioDriver::Start"); - JackAudioDriver::Start(); - PaError err = Pa_StartStream(fStream); - return (err == paNoError) ? 0 : -1; + if (JackAudioDriver::Start() >= 0) { + PaError err = Pa_StartStream(fStream); + if (err == paNoError) { + return 0; + } + JackAudioDriver::Stop(); + } + return -1; } int JackPortAudioDriver::Stop() { jack_log("JackPortAudioDriver::Stop"); PaError err = Pa_StopStream(fStream); - return (err == paNoError) ? 0 : -1; + int res = (err == paNoError) ? 0 : -1; + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)