add option --list-connections for listing JACK connections v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Thu, 08 Oct 2020 16:45:50 +0200
branchv_0
changeset 13 326935d1bfab
parent 12 e8aae4d42c01
child 14 cde9bb07ea0a
add option --list-connections for listing JACK connections the output can be later sent to the relpipe-out-jack to restore the connection graph
bash-completion.sh
src/CLIParser.h
src/Configuration.h
src/JackCommand.h
--- a/bash-completion.sh	Wed Oct 07 22:29:38 2020 +0200
+++ b/bash-completion.sh	Thu Oct 08 16:45:50 2020 +0200
@@ -43,6 +43,7 @@
 	elif [[ "$w1" == "--connect-to"                                    ]];    then COMPREPLY=($(compgen -W "$(_relpipe_in_jack_completion_ports)" -- "$w0"))
 	elif [[ "$w1" == "--required-connections"         && "x$w0" == "x" ]];    then COMPREPLY=("0")
 	elif [[ "$w1" == "--list-ports"                                    ]];    then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+	elif [[ "$w1" == "--list-connections"                              ]];    then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
 	elif [[ "$w1" == "--list-midi-messages"                            ]];    then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
 	else
 		OPTIONS=(
@@ -51,6 +52,7 @@
 			"--connect-to"
 			"--required-connections"
 			"--list-ports"
+			"--list-connections"
 			"--list-midi-messages"
 		)
 		COMPREPLY=($(compgen -W "${OPTIONS[*]}" -- "$w0"))
--- a/src/CLIParser.h	Wed Oct 07 22:29:38 2020 +0200
+++ b/src/CLIParser.h	Thu Oct 08 16:45:50 2020 +0200
@@ -53,6 +53,7 @@
 	static const relpipe::common::type::StringX OPTION_CONNECT_TO;
 	static const relpipe::common::type::StringX OPTION_REQUIRED_CONNECTIONS;
 	static const relpipe::common::type::StringX OPTION_LIST_PORTS;
+	static const relpipe::common::type::StringX OPTION_LIST_CONNECTIONS;
 	static const relpipe::common::type::StringX OPTION_LIST_MIDI_MESSAGES;
 
 	Configuration parse(const std::vector<relpipe::common::type::StringX>& arguments) {
@@ -71,6 +72,8 @@
 				c.requiredConnections = std::stoi(readNext(arguments, i));
 			} else if (option == OPTION_LIST_PORTS) {
 				c.listPorts = parseBoolean(readNext(arguments, i));
+			} else if (option == OPTION_LIST_CONNECTIONS) {
+				c.listConnections = parseBoolean(readNext(arguments, i));
 			} else if (option == OPTION_LIST_MIDI_MESSAGES) {
 				c.listMidiMessages = parseBoolean(readNext(arguments, i));
 			} else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
@@ -88,6 +91,7 @@
 const relpipe::common::type::StringX CLIParser::OPTION_CONNECT_TO = L"--connect-to";
 const relpipe::common::type::StringX CLIParser::OPTION_REQUIRED_CONNECTIONS = L"--required-connections";
 const relpipe::common::type::StringX CLIParser::OPTION_LIST_PORTS = L"--list-ports";
+const relpipe::common::type::StringX CLIParser::OPTION_LIST_CONNECTIONS = L"--list-connections";
 const relpipe::common::type::StringX CLIParser::OPTION_LIST_MIDI_MESSAGES = L"--list-midi-messages";
 
 }
--- a/src/Configuration.h	Wed Oct 07 22:29:38 2020 +0200
+++ b/src/Configuration.h	Thu Oct 08 16:45:50 2020 +0200
@@ -39,6 +39,7 @@
 	std::vector<relpipe::common::type::StringX> connectTo;
 	int requiredConnections = 0;
 	relpipe::common::type::Boolean listPorts = false;
+	relpipe::common::type::Boolean listConnections = false;
 	relpipe::common::type::Boolean listMidiMessages = true;
 
 	virtual ~Configuration() {
--- a/src/JackCommand.h	Wed Oct 07 22:29:38 2020 +0200
+++ b/src/JackCommand.h	Thu Oct 08 16:45:50 2020 +0200
@@ -187,7 +187,7 @@
 		writer->startRelation(L"port", metadata, true);
 
 		const char** portNames = jack_get_ports(realTimeContext.jackClient, nullptr, nullptr, 0);
-		
+
 		std::regex midiTypePattern(".*midi$");
 
 		for (const char** portName = portNames; *portName; portName++) {
@@ -216,6 +216,36 @@
 		jack_free(portNames);
 	}
 
+	void listConnections(std::shared_ptr<relpipe::writer::RelationalWriter> writer) {
+		using namespace relpipe::writer;
+		vector<AttributeMetadata> metadata;
+
+		metadata.push_back({L"event", TypeId::STRING});
+		metadata.push_back({L"source_port", TypeId::STRING});
+		metadata.push_back({L"destination_port", TypeId::STRING});
+		writer->startRelation(L"connection", metadata, true);
+
+		const relpipe::common::type::StringX event = L"connect";
+
+		const char** sourcePortNames = jack_get_ports(realTimeContext.jackClient, nullptr, nullptr, JackPortFlags::JackPortIsOutput);
+
+		for (const char** sourcePortName = sourcePortNames; *sourcePortName; sourcePortName++) {
+			jack_port_t* sourcePort = jack_port_by_name(realTimeContext.jackClient, *sourcePortName);
+
+			const char** destinationPortNames = jack_port_get_all_connections(realTimeContext.jackClient, sourcePort);
+
+			for (const char** destinationPortName = destinationPortNames; destinationPortNames && *destinationPortName; destinationPortName++) {
+				writer->writeAttribute(event);
+				writer->writeAttribute(convertor.from_bytes(*sourcePortName));
+				writer->writeAttribute(convertor.from_bytes(*destinationPortName));
+			}
+
+			jack_free(destinationPortNames);
+		}
+
+		jack_free(sourcePortNames);
+	}
+
 	static void jackErrorCallback(const char * message) {
 		std::wstring_convert < std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding
 		std::wcerr << L"JACK: " << convertor.from_bytes(message) << std::endl;
@@ -282,6 +312,7 @@
 		vector<AttributeMetadata> metadata;
 
 		if (configuration.listPorts) listPorts(writer);
+		if (configuration.listConnections) listConnections(writer);
 		if (!configuration.listMidiMessages) return;
 
 		metadata.push_back({L"event", TypeId::STRING});