partial support for metadata: --list-properties
tested with Jack1 and jalv.qt5 http://gareus.org/oss/lv2/fil4#stereo
--- 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});