# HG changeset patch # User František Kučera # Date 1601996122 -7200 # Node ID ded44e94147cd7dceb5a8fb072f61c5d7e26842c # Parent 0d362165241e2e6078e664e0897400bf7287cfcf add --jack-connect-to-port and --required-jack-connections options diff -r 0d362165241e -r ded44e94147c bash-completion.sh --- a/bash-completion.sh Tue Oct 06 16:24:18 2020 +0200 +++ b/bash-completion.sh Tue Oct 06 16:55:22 2020 +0200 @@ -13,6 +13,24 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +_relpipe_in_jack_completion_ports() { + # TODO: simpler and faster implementation in relpipe-out-jack or relpipe-in-jack C++ code + jack_lsp -tp 2>/dev/null \ + | tr -d \\t \ + | tr \\n \\0 \ + | relpipe-in-cli \ + --relation "jack_midi_port" \ + --attribute "name" string \ + --attribute "properties" string \ + --attribute "type" string \ + --records-on-stdin true \ + | relpipe-tr-grep '.*' 'properties' 'output' \ + | relpipe-tr-grep '.*' 'type' 'midi' \ + | relpipe-tr-cut '.*' 'name' \ + | relpipe-out-nullbyte \ + | tr \\0 \\n +} + _relpipe_in_jack_completion() { local w0 w1 w2 w3 @@ -22,16 +40,14 @@ w2=${COMP_WORDS[COMP_CWORD-2]} w3=${COMP_WORDS[COMP_CWORD-3]} - BOOLEAN=( - "true" - "false" - ) - - if [[ "$w1" == "--TODO" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN[*]}" -- "$w0")) - elif [[ "$w1" == "--jack-client-name" && "x$w0" == "x" ]]; then COMPREPLY=("'relpipe-in-jack'") + if [[ "$w1" == "--jack-client-name" && "x$w0" == "x" ]]; then COMPREPLY=("'relpipe-in-jack'") + elif [[ "$w1" == "--jack-connect-to-port" ]]; then COMPREPLY=($(compgen -W "$(_relpipe_in_jack_completion_ports)" -- "$w0")) + elif [[ "$w1" == "--required-jack-connections" && "x$w0" == "x" ]]; then COMPREPLY=("0") else OPTIONS=( "--jack-client-name" + "--jack-connect-to-port" + "--required-jack-connections" ) COMPREPLY=($(compgen -W "${OPTIONS[*]}" -- "$w0")) fi diff -r 0d362165241e -r ded44e94147c src/CLIParser.h --- a/src/CLIParser.h Tue Oct 06 16:24:18 2020 +0200 +++ b/src/CLIParser.h Tue Oct 06 16:55:22 2020 +0200 @@ -49,6 +49,8 @@ public: static const relpipe::common::type::StringX OPTION_JACK_CLIENT_NAME; + static const relpipe::common::type::StringX OPTION_JACK_CONNECT_TO_PORT; + static const relpipe::common::type::StringX OPTION_REQUIRED_JACK_CONNECTIONS; Configuration parse(const std::vector& arguments) { Configuration c; @@ -58,6 +60,10 @@ if (option == OPTION_JACK_CLIENT_NAME) { c.jackClientName = readNext(arguments, i); + } else if (option == OPTION_JACK_CONNECT_TO_PORT) { + c.portsToConnect.push_back(readNext(arguments, i)); + } else if (option == OPTION_REQUIRED_JACK_CONNECTIONS) { + c.requiredJackConnections = std::stoi(readNext(arguments, i)); } else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); } @@ -69,6 +75,8 @@ }; const relpipe::common::type::StringX CLIParser::OPTION_JACK_CLIENT_NAME = L"--jack-client-name"; +const relpipe::common::type::StringX CLIParser::OPTION_JACK_CONNECT_TO_PORT = L"--jack-connect-to-port"; +const relpipe::common::type::StringX CLIParser::OPTION_REQUIRED_JACK_CONNECTIONS = L"--required-jack-connections"; } } diff -r 0d362165241e -r ded44e94147c src/Configuration.h --- a/src/Configuration.h Tue Oct 06 16:24:18 2020 +0200 +++ b/src/Configuration.h Tue Oct 06 16:55:22 2020 +0200 @@ -29,6 +29,8 @@ class Configuration { public: relpipe::common::type::StringX jackClientName = L"relpipe-in-jack"; + std::vector portsToConnect; + int requiredJackConnections = 0; virtual ~Configuration() { } @@ -36,4 +38,4 @@ } } -} \ No newline at end of file +} diff -r 0d362165241e -r ded44e94147c src/JackCommand.h --- a/src/JackCommand.h Tue Oct 06 16:24:18 2020 +0200 +++ b/src/JackCommand.h Tue Oct 06 16:55:22 2020 +0200 @@ -55,6 +55,8 @@ std::atomic continueProcessing{true}; + int maxJackPortConnections = 0; + /** * Is passed through the ring buffer * from the the jack-writing thread (callback) to the relpipe-writing thread. @@ -218,6 +220,15 @@ int jackError = jack_activate(realTimeContext.jackClient); if (jackError) failInConstructor(L"Could not activate the JACK client."); + + + // Connect to configured destination ports: + const char* jackPortName = jack_port_name(realTimeContext.jackPort); + for (auto sourcePort : configuration.portsToConnect) { + int error = jack_connect(realTimeContext.jackClient, convertor.to_bytes(sourcePort).c_str(), jackPortName); + if (error) failInConstructor(L"Connection to the JACK port failed: " + sourcePort); + } + } void processJackStream(std::shared_ptr writer, std::function relationalWriterFlush) { @@ -244,6 +255,13 @@ relationalWriterFlush(); } waitForRTCycle(); + + // Once the Configuration::requiredJackConnections count was reached, we will disconnect if the count drops under this level. + if (configuration.requiredJackConnections) { + int currentConnectionCount = jack_port_connected(realTimeContext.jackPort); + if (currentConnectionCount > maxJackPortConnections) maxJackPortConnections = currentConnectionCount; + else if (maxJackPortConnections >= configuration.requiredJackConnections && currentConnectionCount < configuration.requiredJackConnections) break; + } } }