partial support for metadata: --list-properties v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 11 Oct 2020 17:13:02 +0200
branchv_0
changeset 15 463ce61415f1
parent 14 cde9bb07ea0a
child 16 79520ded76f0
partial support for metadata: --list-properties tested with Jack1 and jalv.qt5 http://gareus.org/oss/lv2/fil4#stereo
bash-completion.sh
src/CLIParser.h
src/Configuration.h
src/JackCommand.h
--- a/bash-completion.sh	Thu Oct 08 17:23:07 2020 +0200
+++ b/bash-completion.sh	Sun Oct 11 17:13:02 2020 +0200
@@ -48,6 +48,7 @@
 	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-properties"                               ]];    then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
 	elif [[ "$w1" == "--list-midi-messages"                            ]];    then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
 	else
 		OPTIONS=(
@@ -59,6 +60,7 @@
 			"--required-connections"
 			"--list-ports"
 			"--list-connections"
+			"--list-properties"
 			"--list-midi-messages"
 		)
 		COMPREPLY=($(compgen -W "${OPTIONS[*]}" -- "$w0"))
--- a/src/CLIParser.h	Thu Oct 08 17:23:07 2020 +0200
+++ b/src/CLIParser.h	Sun Oct 11 17:13:02 2020 +0200
@@ -56,6 +56,7 @@
 	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_PROPERTIES;
 	static const relpipe::common::type::StringX OPTION_LIST_MIDI_MESSAGES;
 
 	Configuration parse(const std::vector<relpipe::common::type::StringX>& arguments) {
@@ -78,6 +79,8 @@
 				c.listPorts = parseBoolean(readNext(arguments, i));
 			} else if (option == OPTION_LIST_CONNECTIONS) {
 				c.listConnections = parseBoolean(readNext(arguments, i));
+			} else if (option == OPTION_LIST_PROPERTIES) {
+				c.listProperties = 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);
@@ -98,6 +101,7 @@
 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_PROPERTIES = L"--list-properties";
 const relpipe::common::type::StringX CLIParser::OPTION_LIST_MIDI_MESSAGES = L"--list-midi-messages";
 
 }
--- a/src/Configuration.h	Thu Oct 08 17:23:07 2020 +0200
+++ b/src/Configuration.h	Sun Oct 11 17:13:02 2020 +0200
@@ -47,6 +47,7 @@
 	int requiredConnections = 0;
 	relpipe::common::type::Boolean listPorts = false;
 	relpipe::common::type::Boolean listConnections = false;
+	relpipe::common::type::Boolean listProperties = false;
 	relpipe::common::type::Boolean listMidiMessages = true;
 
 	virtual ~Configuration() {
--- a/src/JackCommand.h	Thu Oct 08 17:23:07 2020 +0200
+++ b/src/JackCommand.h	Sun Oct 11 17:13:02 2020 +0200
@@ -29,6 +29,8 @@
 #include <regex>
 
 #include <jack/jack.h>
+#include <jack/metadata.h>
+#include <jack/uuid.h>
 #include <jack/midiport.h>
 #include <jack/ringbuffer.h>
 
@@ -177,6 +179,7 @@
 		vector<AttributeMetadata> metadata;
 
 		metadata.push_back({L"name", TypeId::STRING});
+		metadata.push_back({L"uuid", TypeId::STRING});
 		metadata.push_back({L"input", TypeId::BOOLEAN});
 		metadata.push_back({L"output", TypeId::BOOLEAN});
 		metadata.push_back({L"physical", TypeId::BOOLEAN});
@@ -204,6 +207,7 @@
 			bool isMidi = std::regex_search(portType, midiTypePattern);
 
 			writer->writeAttribute(convertor.from_bytes(*portName));
+			writer->writeAttribute(convertor.from_bytes(uuidToString(jack_port_uuid(port))));
 			writer->writeAttribute(&isInput, typeid (isInput));
 			writer->writeAttribute(&isOuputput, typeid (isOuputput));
 			writer->writeAttribute(&isPhysical, typeid (isPhysical));
@@ -246,6 +250,42 @@
 		jack_free(sourcePortNames);
 	}
 
+	std::string uuidToString(jack_uuid_t uuid) {
+		char buffer[JACK_UUID_STRING_SIZE] = {0};
+		jack_uuid_unparse(uuid, buffer);
+		return buffer;
+	}
+
+	void listProperties(std::shared_ptr<relpipe::writer::RelationalWriter> writer) {
+		using namespace relpipe::writer;
+		vector<AttributeMetadata> metadata;
+
+		metadata.push_back({L"uuid", TypeId::STRING});
+		//metadata.push_back({L"port", TypeId::STRING}); // TODO: port name
+		metadata.push_back({L"name", TypeId::STRING});
+		metadata.push_back({L"type", TypeId::STRING});
+		metadata.push_back({L"value", TypeId::STRING});
+		writer->startRelation(L"property", metadata, true);
+
+		jack_description_t* descriptions = nullptr;
+
+		int descriptionsCount = jack_get_all_properties(&descriptions);
+
+		for (int i = 0; i < descriptionsCount; i++) {
+			jack_description_t* description = &descriptions[i];
+			for (uint32_t j = 0; j < description->property_cnt; j++) {
+				jack_property_t* property = &description->properties[j];
+				writer->writeAttribute(convertor.from_bytes(uuidToString(description->subject)));
+				//writer->writeAttribute(L"TODO: port name"); // TODO: port name
+				writer->writeAttribute(convertor.from_bytes(property->key));
+				writer->writeAttribute(convertor.from_bytes(property->type));
+				writer->writeAttribute(convertor.from_bytes(property->data)); // TODO: format value (some in HEX), according to .type
+			}
+			jack_free_description(description, false);
+		}
+		jack_free(descriptions);
+	}
+
 	void applyConnectionRecipes() {
 		for (Configuration::ConnectionRecipe recipe : configuration.connectionRecipes) {
 			auto operation = recipe.connected ? jack_connect : jack_disconnect;
@@ -323,6 +363,7 @@
 
 		if (configuration.listPorts) listPorts(writer);
 		if (configuration.listConnections) listConnections(writer);
+		if (configuration.listProperties) listProperties(writer);
 		if (!configuration.listMidiMessages) return;
 
 		metadata.push_back({L"event", TypeId::STRING});