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