diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index 6c581c37..8984306a 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -594,14 +594,14 @@ string JackDriver::MatchPortName(const char* name, const char** ports, int alias return ""; } -void JackDriver::RestoreConnections(int alias, bool full_name) +void JackDriver::LoadConnections(int alias, bool full_name) { list > >::const_iterator it; if (full_name) { for (it = fConnections.begin(); it != fConnections.end(); it++) { pair connection = (*it).second; - jack_info("Restore connection: %s %s", connection.first.c_str(), connection.second.c_str()); + jack_info("Load connection: %s %s", connection.first.c_str(), connection.second.c_str()); fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str()); } } else { @@ -613,7 +613,7 @@ void JackDriver::RestoreConnections(int alias, bool full_name) string real_input = MatchPortName(connection.first.c_str(), outputs, alias, (*it).first); string real_output = MatchPortName(connection.second.c_str(), inputs, alias, (*it).first); if ((real_input != "") && (real_output != "")) { - jack_info("Restore connection: %s %s", real_input.c_str(), real_output.c_str()); + jack_info("Load connection: %s %s", real_input.c_str(), real_output.c_str()); fEngine->PortConnect(fClientControl.fRefNum, real_input.c_str(), real_output.c_str()); } } diff --git a/common/JackDriver.h b/common/JackDriver.h index 4b676858..724bc5da 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -130,6 +130,8 @@ class SERVER_EXPORT JackDriverClientInterface : public JackDriverInterface, publ #define PlaybackDriverFlags static_cast(JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal) #define MonitorDriverFlags static_cast(JackPortIsOutput) +typedef std::list > > driver_connections_list_t; // [type : (src, dst)] + class SERVER_EXPORT JackDriver : public JackDriverClientInterface { @@ -169,7 +171,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface jack_port_id_t fPlaybackPortList[DRIVER_PORT_NUM]; jack_port_id_t fMonitorPortList[DRIVER_PORT_NUM]; - std::list > > fConnections; // Connections list + driver_connections_list_t fConnections; // Connections list void CycleIncTime(); void CycleTakeBeginTime(); @@ -183,7 +185,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface void NotifyFailure(int code, const char* reason); // Failure notification sent by the driver virtual void SaveConnections(int alias); - virtual void RestoreConnections(int alias, bool full_name = true); + virtual void LoadConnections(int alias, bool full_name = true); std::string MatchPortName(const char* name, const char** ports, int alias, const std::string& type); virtual int StartSlaves(); diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index d213aac4..46f70feb 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -29,7 +29,8 @@ namespace Jack { JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports, - char* net_name, uint transport_sync, int network_latency, int celt_encoding, int opus_encoding) + char* net_name, uint transport_sync, int network_latency, + int celt_encoding, int opus_encoding, bool auto_save) : JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) { jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port); @@ -66,6 +67,7 @@ namespace Jack fMidiPlaybackPortList = NULL; fWantedAudioCaptureChannels = -1; fWantedAudioPlaybackChannels = -1; + fAutoSave = auto_save; #ifdef JACK_MONITOR fNetTimeMon = NULL; fRcvSyncUst = 0; @@ -137,7 +139,9 @@ namespace Jack bool JackNetDriver::Initialize() { jack_log("JackNetDriver::Initialize"); - SaveConnections(0); + if (fAutoSave) { + SaveConnections(0); + } FreePorts(); // New loading, but existing socket, restart the driver @@ -237,7 +241,9 @@ namespace Jack // Transport engine parametering fEngineControl->fTransport.SetNetworkSync(fParams.fTransportSync); - RestoreConnections(0); + if (fAutoSave) { + LoadConnections(0); + } return true; } @@ -687,6 +693,10 @@ namespace Jack #endif strcpy(value.str, "'hostname'"); jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); + + value.i = false; + jack_driver_descriptor_add_parameter(desc, &filler, "auto-save", 's', JackDriverParamBool, &value, NULL, "Save/restore connection state when restarting", NULL); + /* Deactivated for now.. @@ -720,6 +730,7 @@ Deactivated for now.. int network_latency = 5; const JSList* node; const jack_driver_param_t* param; + bool auto_save = false; // Possibly use env variable for UDP port const char* default_udp_port = getenv("JACK_NETJACK_PORT"); @@ -768,6 +779,9 @@ Deactivated for now.. case 'n' : strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE); break; + case 's': + auto_save = param->value.i; + break; /* Deactivated for now.. case 't' : @@ -790,7 +804,7 @@ Deactivated for now.. new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, midi_input_ports, midi_output_ports, net_name, transport_sync, - network_latency, celt_encoding, opus_encoding)); + network_latency, celt_encoding, opus_encoding, auto_save)); if (driver->Open(period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0) == 0) { return driver; } else { diff --git a/common/JackNetDriver.h b/common/JackNetDriver.h index 20a266cd..dc0d8529 100644 --- a/common/JackNetDriver.h +++ b/common/JackNetDriver.h @@ -50,6 +50,8 @@ namespace Jack int fWantedMIDICaptureChannels; int fWantedMIDIPlaybackChannels; + + bool fAutoSave; //monitoring #ifdef JACK_MONITOR @@ -78,7 +80,8 @@ namespace Jack JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, - char* net_name, uint transport_sync, int network_latency, int celt_encoding, int opus_encoding); + char* net_name, uint transport_sync, int network_latency, int celt_encoding, + int opus_encoding, bool auto_save); virtual ~JackNetDriver(); int Open(jack_nframes_t buffer_size, diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index 843e3890..7f96d2cc 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackArgParser.h" #include "JackServerGlobals.h" #include "JackLockedEngine.h" +#include "thread.h" using namespace std; @@ -556,6 +557,65 @@ namespace Jack #endif return 0; } + + void JackNetMaster::SaveConnections(connections_list_t& connections) + { + // Audio + for (int i = 0; i < fParams.fSendAudioChannels; i++) { + const char** connected_port = jack_port_get_all_connections(fClient, fAudioCapturePorts[i]); + if (connected_port != NULL) { + for (int port = 0; connected_port[port]; port++) { + connections.push_back(make_pair(connected_port[port], jack_port_name(fAudioCapturePorts[i]))); + jack_log("INPUT %s ==> %s", connected_port[port], jack_port_name(fAudioCapturePorts[i])); + } + jack_free(connected_port); + } + } + + for (int i = 0; i < fParams.fReturnAudioChannels; i++) { + const char** connected_port = jack_port_get_all_connections(fClient, fAudioPlaybackPorts[i]); + if (connected_port != NULL) { + for (int port = 0; connected_port[port]; port++) { + connections.push_back(make_pair(jack_port_name(fAudioPlaybackPorts[i]), connected_port[port])); + jack_log("OUTPUT %s ==> %s", jack_port_name(fAudioPlaybackPorts[i]), connected_port[port]); + } + jack_free(connected_port); + } + } + + // MIDI + for (int i = 0; i < fParams.fSendMidiChannels; i++) { + const char** connected_port = jack_port_get_all_connections(fClient, fMidiCapturePorts[i]); + if (connected_port != NULL) { + for (int port = 0; connected_port[port]; port++) { + connections.push_back(make_pair(connected_port[port], jack_port_name(fMidiCapturePorts[i]))); + jack_log("INPUT %s ==> %s", connected_port[port], jack_port_name(fMidiCapturePorts[i])); + } + jack_free(connected_port); + } + } + + for (int i = 0; i < fParams.fReturnMidiChannels; i++) { + const char** connected_port = jack_port_get_all_connections(fClient, fMidiPlaybackPorts[i]); + if (connected_port != NULL) { + for (int port = 0; connected_port[port]; port++) { + connections.push_back(make_pair(jack_port_name(fMidiPlaybackPorts[i]), connected_port[port])); + jack_log("OUTPUT %s ==> %s", jack_port_name(fMidiPlaybackPorts[i]), connected_port[port]); + } + jack_free(connected_port); + } + } + } + + void JackNetMaster::LoadConnections(const connections_list_t& connections) + { + list >::const_iterator it; + for (it = connections.begin(); it != connections.end(); it++) { + pair connection = *it; + jack_connect(fClient, connection.first.c_str(), connection.second.c_str()); + } + } + //JackNetMasterManager*********************************************************************************************** @@ -568,6 +628,7 @@ namespace Jack fGlobalID = 0; fRunning = true; fAutoConnect = false; + fAutoSave = false; const JSList* node; const jack_driver_param_t* param; @@ -604,6 +665,10 @@ namespace Jack case 'c': fAutoConnect = param->value.i; break; + + case 's': + fAutoSave = param->value.i; + break; } } @@ -652,7 +717,7 @@ namespace Jack } master_list_t::iterator it; for (it = fMasterList.begin(); it != fMasterList.end(); it++) { - delete(*it); + delete (*it); } fMasterList.clear(); fSocket.Close(); @@ -811,10 +876,14 @@ namespace Jack JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP); if (master->Init(fAutoConnect)) { fMasterList.push_back(master); + if (fAutoSave && fMasterConnectionList.find(params.fName) != fMasterConnectionList.end()) { + master->LoadConnections(fMasterConnectionList[params.fName]); + } return master; + } else { + delete master; + return NULL; } - delete master; - return NULL; } master_list_it_t JackNetMasterManager::FindMaster(uint32_t id) @@ -834,10 +903,14 @@ namespace Jack { jack_log("JackNetMasterManager::KillMaster ID = %u", params->fID); - master_list_it_t master = FindMaster(params->fID); - if (master != fMasterList.end()) { - fMasterList.erase(master); - delete *master; + master_list_it_t master_it = FindMaster(params->fID); + if (master_it != fMasterList.end()) { + if (fAutoSave) { + fMasterConnectionList[params->fName].clear(); + (*master_it)->SaveConnections(fMasterConnectionList[params->fName]); + } + fMasterList.erase(master_it); + delete (*master_it); return 1; } return 0; @@ -868,6 +941,9 @@ extern "C" value.i = false; jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", NULL); + value.i = false; + jack_driver_descriptor_add_parameter(desc, &filler, "auto-save", 's', JackDriverParamBool, &value, NULL, "Save/restore netmaster connection state when restarted", NULL); + return desc; } diff --git a/common/JackNetManager.h b/common/JackNetManager.h index b3a481b2..1d76e8b2 100644 --- a/common/JackNetManager.h +++ b/common/JackNetManager.h @@ -21,10 +21,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #define __JACKNETMANAGER_H__ #include "JackNetInterface.h" -#include "thread.h" #include "jack.h" -#include "jslist.h" #include +#include namespace Jack { @@ -33,6 +32,8 @@ namespace Jack /** \Brief This class describes a Net Master */ + + typedef std::list > connections_list_t; class JackNetMaster : public JackNetMasterInterface { @@ -78,6 +79,9 @@ namespace Jack void TimebaseCallback(jack_position_t* pos); void ConnectPorts(); void ConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect); + + void SaveConnections(connections_list_t& connections); + void LoadConnections(const connections_list_t& connections); public: @@ -89,6 +93,7 @@ namespace Jack typedef std::list master_list_t; typedef master_list_t::iterator master_list_it_t; + typedef std::map master_connections_list_t; /** \Brief This class describer the Network Manager @@ -110,9 +115,11 @@ namespace Jack JackNetSocket fSocket; jack_native_thread_t fThread; master_list_t fMasterList; + master_connections_list_t fMasterConnectionList; uint32_t fGlobalID; bool fRunning; bool fAutoConnect; + bool fAutoSave; void Run(); JackNetMaster* InitMaster(session_params_t& params); diff --git a/macosx/coremidi/JackCoreMidiDriver.cpp b/macosx/coremidi/JackCoreMidiDriver.cpp index 1b34567d..753a7675 100644 --- a/macosx/coremidi/JackCoreMidiDriver.cpp +++ b/macosx/coremidi/JackCoreMidiDriver.cpp @@ -529,7 +529,7 @@ JackCoreMidiDriver::Restart() Attach(); Start(); // Use first alias and partial port naming - RestoreConnections(1, false); + LoadConnections(1, false); } void