diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp index 6789d987..7a58f6de 100644 --- a/common/JackAPI.cpp +++ b/common/JackAPI.cpp @@ -277,6 +277,8 @@ extern "C" LIB_EXPORT void jack_uuid_unparse(jack_uuid_t, char buf[JACK_UUID_STRING_SIZE]); LIB_EXPORT int jack_uuid_empty(jack_uuid_t); + LIB_EXPORT int jack_client_reload_master(jack_client_t* ext_client); + #ifdef __cplusplus } #endif @@ -2140,3 +2142,17 @@ LIB_EXPORT int jack_uuid_empty(jack_uuid_t u) { return u == JACK_UUID_EMPTY_INITIALIZER; } + +LIB_EXPORT int jack_client_reload_master(jack_client_t* ext_client) +{ + JackGlobals::CheckContext("jack_client_reload_master"); + + JackClient* client = (JackClient*)ext_client; + if (client == NULL) { + jack_error("jack_client_reload_master called with a NULL client"); + return -1; + } else { + WaitGraphChange(); + return client->ClientReloadMaster(); + } +} diff --git a/common/JackChannel.h b/common/JackChannel.h index 56687043..35aeda8f 100644 --- a/common/JackChannel.h +++ b/common/JackChannel.h @@ -137,6 +137,9 @@ class JackClientChannelInterface virtual void ClientDeactivate(int refnum, int* result) {} + virtual void ClientReloadMaster(int* result) + {} + virtual void PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result) {} virtual void PortUnRegister(int refnum, jack_port_id_t port_index, int* result) diff --git a/common/JackClient.cpp b/common/JackClient.cpp index b8303ab0..01a00dee 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -502,6 +502,13 @@ int JackClient::Deactivate() if (IsRealTime()) { fThread.Kill(); } + return result; +} + +int JackClient::ClientReloadMaster() +{ + int result = -1; + fChannel->ClientReloadMaster(&result); return result; } diff --git a/common/JackClient.h b/common/JackClient.h index a0e506e7..d18fd774 100644 --- a/common/JackClient.h +++ b/common/JackClient.h @@ -145,6 +145,8 @@ class SERVER_EXPORT JackClient : public JackClientInterface, public JackRunnable virtual int Activate(); virtual int Deactivate(); + virtual int ClientReloadMaster(); + // Context virtual int SetBufferSize(jack_nframes_t buffer_size); virtual int SetFreeWheel(int onoff); diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index 8700b1c9..fb4bbf36 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -351,6 +351,11 @@ int JackDriver::Stop() return StopSlaves(); } +int JackDriver::Reload() +{ + return 0; +} + int JackDriver::StartSlaves() { int res = 0; diff --git a/common/JackDriver.h b/common/JackDriver.h index c66e2500..9caa884a 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -72,6 +72,7 @@ class SERVER_EXPORT JackDriverInterface virtual int Start() = 0; virtual int Stop() = 0; + virtual int Reload() = 0; virtual bool IsFixedBufferSize() = 0; virtual int SetBufferSize(jack_nframes_t buffer_size) = 0; @@ -227,6 +228,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface virtual int Start(); virtual int Stop(); + virtual int Reload(); // For "master" driver int ProcessReadSlaves(); diff --git a/common/JackGenericClientChannel.cpp b/common/JackGenericClientChannel.cpp index 96401d29..c8151240 100644 --- a/common/JackGenericClientChannel.cpp +++ b/common/JackGenericClientChannel.cpp @@ -137,6 +137,13 @@ void JackGenericClientChannel::ClientDeactivate(int refnum, int* result) ServerSyncCall(&req, &res, result); } +void JackGenericClientChannel::ClientReloadMaster(int *result) +{ + JackClientReloadMasterRequest req; + JackResult res; + ServerSyncCall(&req, &res, result); +} + void JackGenericClientChannel::PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result) { JackPortRegisterRequest req(refnum, name, type, flags, buffer_size); diff --git a/common/JackGenericClientChannel.h b/common/JackGenericClientChannel.h index b2c7b4ad..a82b4a61 100644 --- a/common/JackGenericClientChannel.h +++ b/common/JackGenericClientChannel.h @@ -62,6 +62,8 @@ class JackGenericClientChannel : public detail::JackClientChannelInterface void ClientActivate(int refnum, int is_real_time, int* result); void ClientDeactivate(int refnum, int* result); + void ClientReloadMaster(int* result); + void PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result); void PortUnRegister(int refnum, jack_port_id_t port_index, int* result); diff --git a/common/JackRequest.h b/common/JackRequest.h index 3c2c8bef..2048ef5b 100644 --- a/common/JackRequest.h +++ b/common/JackRequest.h @@ -91,6 +91,7 @@ struct JackRequest kClientHasSessionCallback = 38, kComputeTotalLatencies = 39, kPropertyChangeNotify = 40, + kClientReloadMaster = 41, }; RequestType fType; @@ -1736,6 +1737,31 @@ struct JackClientNotification }; +/*! +\brief Restart Master Backend Request. +*/ + +struct JackClientReloadMasterRequest : public JackRequest +{ + JackClientReloadMasterRequest(): JackRequest(JackRequest::kClientReloadMaster) + { + } + + int Read(detail::JackChannelTransactionInterface* trans) + { + CheckSize(); + return 0; + } + + int Write(detail::JackChannelTransactionInterface* trans) + { + CheckRes(JackRequest::Write(trans, Size())); + return 0; + } + + int Size() { return 0; } +}; + } // end of namespace #endif diff --git a/common/JackRequestDecoder.cpp b/common/JackRequestDecoder.cpp index 46bbd1f3..533d2e50 100644 --- a/common/JackRequestDecoder.cpp +++ b/common/JackRequestDecoder.cpp @@ -346,6 +346,16 @@ int JackRequestDecoder::HandleRequest(detail::JackChannelTransactionInterface* s break; } + case JackRequest::kClientReloadMaster: { + jack_log("JackRequest::ClientReloadMaster"); + JackClientReloadMasterRequest req; + JackResult res; + CheckRead(req, socket); + res.fResult = fServer->ReloadMaster(); + CheckWrite("JackRequest::ClientReloadMaster", socket); + break; + } + default: jack_error("Unknown request %ld", type); return -1; diff --git a/common/JackServer.cpp b/common/JackServer.cpp index 5cee13fb..0f9b4cd3 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -430,6 +430,11 @@ error: return -1; } +int JackServer::ReloadMaster() +{ + return fAudioDriver->Reload(); +} + //---------------------- // Transport management //---------------------- diff --git a/common/JackServer.h b/common/JackServer.h index 71192e9e..c7921b03 100644 --- a/common/JackServer.h +++ b/common/JackServer.h @@ -98,6 +98,7 @@ class SERVER_EXPORT JackServer JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params); void RemoveSlave(JackDriverInfo* info); int SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params); + int ReloadMaster(); // Object access JackLockedEngine* GetEngine(); diff --git a/common/JackThreadedDriver.cpp b/common/JackThreadedDriver.cpp index b56a7343..40d03e52 100644 --- a/common/JackThreadedDriver.cpp +++ b/common/JackThreadedDriver.cpp @@ -239,6 +239,28 @@ int JackThreadedDriver::Stop() return 0; } +int JackThreadedDriver::Reload() +{ + if (Stop() < 0) { + jack_error("JackThreadedDriver::Reload stop failed"); + return -1; + } + + // not able to use Close() and Open() since we dont have original Open() parameters, these + // are internal to fDriver, reload should reopen with same parameters + if (fDriver->Reload() < 0) { + jack_error("JackThreadedDriver::Reload reload failed"); + return -1; + } + + if (Start() < 0) { + jack_error("JackThreadedDriver::Reload start failed"); + return -1; + } + + return 0; +} + bool JackThreadedDriver::Execute() { return (Process() == 0); diff --git a/common/JackThreadedDriver.h b/common/JackThreadedDriver.h index cdf10abb..1f83ecad 100644 --- a/common/JackThreadedDriver.h +++ b/common/JackThreadedDriver.h @@ -70,6 +70,7 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi virtual int Start(); virtual int Stop(); + virtual int Reload(); virtual bool IsFixedBufferSize(); virtual int SetBufferSize(jack_nframes_t buffer_size); diff --git a/common/jack/jack.h b/common/jack/jack.h index e982b6df..c5eb27ed 100644 --- a/common/jack/jack.h +++ b/common/jack/jack.h @@ -139,6 +139,22 @@ int jack_client_close (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; */ int jack_client_name_size (void) JACK_OPTIONAL_WEAK_EXPORT; +/** + * Reloads audio backend. + * + * This is useful when client wants audio backend to reload its state. + * Currently used only for alsa audio backend. + * + * Alsa backend will close or open audio devices on reload depending on + * the state of the ports asociated with audio device. If all ports + * are disconnected audio device is closed, opened otherwise. This + * behaviour is modifiable by alsa backend options provided to jackd + * on startup. + * + * @return 0 if successful. + */ +int jack_client_reload_master(jack_client_t* ext_client) JACK_OPTIONAL_WEAK_EXPORT; + /** * @return pointer to actual client name. This is useful when @ref * JackUseExactName is not specified on open and @ref