From 663a5d01b1931b97370ed8feff3ae229a9cc7ea4 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 2 Jan 2021 14:02:44 +0100 Subject: Format all code with clang-format --- .clang-format | 127 +--- src/AlsaDriver.cpp | 793 ++++++++++++------------- src/AudioDriver.hpp | 26 +- src/Canvas.cpp | 382 ++++++------ src/Canvas.hpp | 43 +- src/CanvasModule.cpp | 170 +++--- src/CanvasModule.hpp | 56 +- src/CanvasPort.hpp | 126 ++-- src/ClientID.hpp | 139 +++-- src/ClientInfo.hpp | 5 +- src/ClientType.hpp | 7 +- src/Configuration.cpp | 506 ++++++++-------- src/Configuration.hpp | 153 +++-- src/Connector.cpp | 44 +- src/Connector.hpp | 12 +- src/Driver.hpp | 44 +- src/Event.hpp | 48 +- src/ILog.hpp | 18 +- src/JackDbusDriver.cpp | 1484 +++++++++++++++++++++++----------------------- src/JackLibDriver.cpp | 560 ++++++++--------- src/Legend.cpp | 65 +- src/Legend.hpp | 12 +- src/Metadata.cpp | 48 +- src/Metadata.hpp | 22 +- src/Options.hpp | 7 +- src/Patchage.cpp | 1069 +++++++++++++++++---------------- src/Patchage.hpp | 257 ++++---- src/PortID.hpp | 250 ++++---- src/PortInfo.hpp | 13 +- src/PortNames.hpp | 34 +- src/PortType.hpp | 13 +- src/SignalDirection.hpp | 9 +- src/TextViewLog.cpp | 69 ++- src/TextViewLog.hpp | 30 +- src/UIFile.hpp | 58 +- src/Widget.hpp | 34 +- src/event_to_string.cpp | 203 ++++--- src/handle_event.cpp | 162 ++--- src/main.cpp | 177 +++--- src/make_alsa_driver.hpp | 2 +- src/make_jack_driver.hpp | 2 +- src/warnings.hpp | 27 +- 42 files changed, 3562 insertions(+), 3744 deletions(-) diff --git a/.clang-format b/.clang-format index d14e40f..1d0cff9 100644 --- a/.clang-format +++ b/.clang-format @@ -1,126 +1,23 @@ --- -Language: Cpp -# BasedOnStyle: Mozilla -AccessModifierOffset: -4 -AlignAfterOpenBracket: Align -AlignConsecutiveMacros: true AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: true -AlignEscapedNewlines: Left -AlignOperands: true -AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true -AllowAllConstructorInitializersOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: false -AllowShortFunctionsOnASingleLine: Inline -AllowShortLambdasOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: TopLevel -AlwaysBreakAfterReturnType: TopLevel -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: false -BinPackParameters: false +AlignEscapedNewlinesLeft: true +BasedOnStyle: Mozilla BraceWrapping: - AfterCaseLabel: false - AfterClass: true - AfterControlStatement: false - AfterEnum: true - AfterFunction: true - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: true - AfterUnion: true - AfterExternBlock: true - BeforeCatch: false - BeforeElse: false - IndentBraces: false - SplitEmptyFunction: true + AfterNamespace: false + AfterClass: true + AfterEnum: false + AfterExternBlock: false + AfterFunction: true + AfterStruct: false + SplitEmptyFunction: false SplitEmptyRecord: false - SplitEmptyNamespace: true -BreakBeforeBinaryOperators: None -BreakBeforeBraces: Mozilla -BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeComma -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeComma -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true -ColumnLimit: 80 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 +BreakBeforeBraces: Custom Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - - Regex: '.*' - Priority: 1 -IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: false IndentPPDirectives: AfterHash -IndentWidth: 4 -IndentWrappedFunctionNames: false -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 4 -ObjCSpaceAfterProperty: true -ObjCSpaceBeforeProtocolList: false -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 0 -PointerAlignment: Left -ReflowComments: true -SortIncludes: true -SortUsingDeclarations: true -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false -SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -Standard: Cpp11 +KeepEmptyLinesAtTheStartOfBlocks: false +SpacesInContainerLiterals: false StatementMacros: - _Pragma -TabWidth: 4 -UseTab: ForIndentation ... - diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp index c1d2531..5fd038c 100644 --- a/src/AlsaDriver.cpp +++ b/src/AlsaDriver.cpp @@ -55,500 +55,487 @@ namespace { class AlsaDriver : public Driver { public: - explicit AlsaDriver(ILog& log, EventSink emit_event); + explicit AlsaDriver(ILog& log, EventSink emit_event); - AlsaDriver(const AlsaDriver&) = delete; - AlsaDriver& operator=(const AlsaDriver&) = delete; + AlsaDriver(const AlsaDriver&) = delete; + AlsaDriver& operator=(const AlsaDriver&) = delete; - AlsaDriver(AlsaDriver&&) = delete; - AlsaDriver& operator=(AlsaDriver&&) = delete; + AlsaDriver(AlsaDriver&&) = delete; + AlsaDriver& operator=(AlsaDriver&&) = delete; - ~AlsaDriver() override; + ~AlsaDriver() override; - void attach(bool launch_daemon) override; - void detach() override; + void attach(bool launch_daemon) override; + void detach() override; - bool is_attached() const override { return (_seq != nullptr); } + bool is_attached() const override { return (_seq != nullptr); } - void refresh(const EventSink& sink) override; + void refresh(const EventSink& sink) override; - bool connect(const PortID& tail_id, const PortID& head_id) override; + bool connect(const PortID& tail_id, const PortID& head_id) override; - bool disconnect(const PortID& tail_id, const PortID& head_id) override; + bool disconnect(const PortID& tail_id, const PortID& head_id) override; private: - bool create_refresh_port(); - static void* refresh_main(void* me); - void _refresh_main(); + bool create_refresh_port(); + static void* refresh_main(void* me); + void _refresh_main(); - ILog& _log; - snd_seq_t* _seq; - pthread_t _refresh_thread; + ILog& _log; + snd_seq_t* _seq; + pthread_t _refresh_thread; - struct SeqAddrComparator - { - bool operator()(const snd_seq_addr_t& a, const snd_seq_addr_t& b) const - { - return ((a.client < b.client) || - ((a.client == b.client) && a.port < b.port)); - } - }; + struct SeqAddrComparator { + bool operator()(const snd_seq_addr_t& a, const snd_seq_addr_t& b) const + { + return ((a.client < b.client) || + ((a.client == b.client) && a.port < b.port)); + } + }; - using Ignored = std::set; + using Ignored = std::set; - Ignored _ignored; + Ignored _ignored; - bool ignore(const snd_seq_addr_t& addr, bool add = true); + bool ignore(const snd_seq_addr_t& addr, bool add = true); }; PortID addr_to_id(const snd_seq_addr_t& addr, const bool is_input) { - return PortID::alsa(addr.client, addr.port, is_input); + return PortID::alsa(addr.client, addr.port, is_input); } SignalDirection port_direction(const snd_seq_port_info_t* const pinfo) { - const int caps = snd_seq_port_info_get_capability(pinfo); + const int caps = snd_seq_port_info_get_capability(pinfo); - if ((caps & SND_SEQ_PORT_CAP_READ) && (caps & SND_SEQ_PORT_CAP_WRITE)) { - return SignalDirection::duplex; - } + if ((caps & SND_SEQ_PORT_CAP_READ) && (caps & SND_SEQ_PORT_CAP_WRITE)) { + return SignalDirection::duplex; + } - if (caps & SND_SEQ_PORT_CAP_READ) { - return SignalDirection::output; - } + if (caps & SND_SEQ_PORT_CAP_READ) { + return SignalDirection::output; + } - if (caps & SND_SEQ_PORT_CAP_WRITE) { - return SignalDirection::input; - } + if (caps & SND_SEQ_PORT_CAP_WRITE) { + return SignalDirection::input; + } - return SignalDirection::duplex; + return SignalDirection::duplex; } ClientInfo client_info(snd_seq_client_info_t* const cinfo) { - return {snd_seq_client_info_get_name(cinfo)}; + return {snd_seq_client_info_get_name(cinfo)}; } PortInfo port_info(const snd_seq_port_info_t* const pinfo) { - const int type = snd_seq_port_info_get_type(pinfo); + const int type = snd_seq_port_info_get_type(pinfo); - return {snd_seq_port_info_get_name(pinfo), - PortType::alsa_midi, - port_direction(pinfo), - snd_seq_port_info_get_port(pinfo), - (type & SND_SEQ_PORT_TYPE_APPLICATION) == 0}; + return {snd_seq_port_info_get_name(pinfo), + PortType::alsa_midi, + port_direction(pinfo), + snd_seq_port_info_get_port(pinfo), + (type & SND_SEQ_PORT_TYPE_APPLICATION) == 0}; } AlsaDriver::AlsaDriver(ILog& log, EventSink emit_event) - : Driver{std::move(emit_event)} - , _log(log) - , _seq(nullptr) - , _refresh_thread{} + : Driver{std::move(emit_event)} + , _log(log) + , _seq(nullptr) + , _refresh_thread{} {} AlsaDriver::~AlsaDriver() { - detach(); + detach(); } void AlsaDriver::attach(bool /*launch_daemon*/) { - int ret = snd_seq_open(&_seq, "default", SND_SEQ_OPEN_DUPLEX, 0); - if (ret) { - _log.error("[ALSA] Unable to attach"); - _seq = nullptr; - } else { - _emit_event(DriverAttachmentEvent{ClientType::alsa}); - - snd_seq_set_client_name(_seq, "Patchage"); - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setstacksize(&attr, 50000); - - ret = pthread_create( - &_refresh_thread, &attr, &AlsaDriver::refresh_main, this); - if (ret) { - _log.error("[ALSA] Failed to start refresh thread"); - } - } + int ret = snd_seq_open(&_seq, "default", SND_SEQ_OPEN_DUPLEX, 0); + if (ret) { + _log.error("[ALSA] Unable to attach"); + _seq = nullptr; + } else { + _emit_event(DriverAttachmentEvent{ClientType::alsa}); + + snd_seq_set_client_name(_seq, "Patchage"); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, 50000); + + ret = + pthread_create(&_refresh_thread, &attr, &AlsaDriver::refresh_main, this); + if (ret) { + _log.error("[ALSA] Failed to start refresh thread"); + } + } } void AlsaDriver::detach() { - if (_seq) { - pthread_cancel(_refresh_thread); - pthread_join(_refresh_thread, nullptr); - snd_seq_close(_seq); - _seq = nullptr; - _emit_event(DriverDetachmentEvent{ClientType::alsa}); - } + if (_seq) { + pthread_cancel(_refresh_thread); + pthread_join(_refresh_thread, nullptr); + snd_seq_close(_seq); + _seq = nullptr; + _emit_event(DriverDetachmentEvent{ClientType::alsa}); + } } void AlsaDriver::refresh(const EventSink& sink) { - if (!is_attached() || !_seq) { - return; - } - - _ignored.clear(); - - snd_seq_client_info_t* cinfo = nullptr; - snd_seq_client_info_alloca(&cinfo); - snd_seq_client_info_set_client(cinfo, -1); - - snd_seq_port_info_t* pinfo = nullptr; - snd_seq_port_info_alloca(&pinfo); - - // Emit all clients - snd_seq_client_info_set_client(cinfo, -1); - while (snd_seq_query_next_client(_seq, cinfo) >= 0) { - const auto client_id = snd_seq_client_info_get_client(cinfo); - - assert(client_id < std::numeric_limits::max()); - sink({ClientCreationEvent{ - ClientID::alsa(static_cast(client_id)), - client_info(cinfo)}}); - } - - // Emit all ports - snd_seq_client_info_set_client(cinfo, -1); - while (snd_seq_query_next_client(_seq, cinfo) >= 0) { - const auto client_id = snd_seq_client_info_get_client(cinfo); - - snd_seq_port_info_set_client(pinfo, client_id); - snd_seq_port_info_set_port(pinfo, -1); - while (snd_seq_query_next_port(_seq, pinfo) >= 0) { - const auto addr = *snd_seq_port_info_get_addr(pinfo); - if (!ignore(addr)) { - const auto caps = snd_seq_port_info_get_capability(pinfo); - auto info = port_info(pinfo); - - if (caps & SND_SEQ_PORT_CAP_READ) { - info.direction = SignalDirection::input; - sink({PortCreationEvent{addr_to_id(addr, true), info}}); - } - - if (caps & SND_SEQ_PORT_CAP_WRITE) { - info.direction = SignalDirection::output; - sink({PortCreationEvent{addr_to_id(addr, false), info}}); - } - } - } - } - - // Emit all connections - snd_seq_client_info_set_client(cinfo, -1); - while (snd_seq_query_next_client(_seq, cinfo) >= 0) { - const auto client_id = snd_seq_client_info_get_client(cinfo); - - snd_seq_port_info_set_client(pinfo, client_id); - snd_seq_port_info_set_port(pinfo, -1); - while (snd_seq_query_next_port(_seq, pinfo) >= 0) { - const auto tail_addr = *snd_seq_port_info_get_addr(pinfo); - const auto tail_id = addr_to_id(tail_addr, false); - if (ignore(tail_addr)) { - continue; - } - - snd_seq_query_subscribe_t* sinfo = nullptr; - snd_seq_query_subscribe_alloca(&sinfo); - snd_seq_query_subscribe_set_root(sinfo, &tail_addr); - snd_seq_query_subscribe_set_index(sinfo, 0); - while (!snd_seq_query_port_subscribers(_seq, sinfo)) { - const auto head_addr = *snd_seq_query_subscribe_get_addr(sinfo); - const auto head_id = addr_to_id(head_addr, true); - - sink({ConnectionEvent{tail_id, head_id}}); - - snd_seq_query_subscribe_set_index( - sinfo, snd_seq_query_subscribe_get_index(sinfo) + 1); - } - } - } + if (!is_attached() || !_seq) { + return; + } + + _ignored.clear(); + + snd_seq_client_info_t* cinfo = nullptr; + snd_seq_client_info_alloca(&cinfo); + snd_seq_client_info_set_client(cinfo, -1); + + snd_seq_port_info_t* pinfo = nullptr; + snd_seq_port_info_alloca(&pinfo); + + // Emit all clients + snd_seq_client_info_set_client(cinfo, -1); + while (snd_seq_query_next_client(_seq, cinfo) >= 0) { + const auto client_id = snd_seq_client_info_get_client(cinfo); + + assert(client_id < std::numeric_limits::max()); + sink({ClientCreationEvent{ClientID::alsa(static_cast(client_id)), + client_info(cinfo)}}); + } + + // Emit all ports + snd_seq_client_info_set_client(cinfo, -1); + while (snd_seq_query_next_client(_seq, cinfo) >= 0) { + const auto client_id = snd_seq_client_info_get_client(cinfo); + + snd_seq_port_info_set_client(pinfo, client_id); + snd_seq_port_info_set_port(pinfo, -1); + while (snd_seq_query_next_port(_seq, pinfo) >= 0) { + const auto addr = *snd_seq_port_info_get_addr(pinfo); + if (!ignore(addr)) { + const auto caps = snd_seq_port_info_get_capability(pinfo); + auto info = port_info(pinfo); + + if (caps & SND_SEQ_PORT_CAP_READ) { + info.direction = SignalDirection::input; + sink({PortCreationEvent{addr_to_id(addr, true), info}}); + } + + if (caps & SND_SEQ_PORT_CAP_WRITE) { + info.direction = SignalDirection::output; + sink({PortCreationEvent{addr_to_id(addr, false), info}}); + } + } + } + } + + // Emit all connections + snd_seq_client_info_set_client(cinfo, -1); + while (snd_seq_query_next_client(_seq, cinfo) >= 0) { + const auto client_id = snd_seq_client_info_get_client(cinfo); + + snd_seq_port_info_set_client(pinfo, client_id); + snd_seq_port_info_set_port(pinfo, -1); + while (snd_seq_query_next_port(_seq, pinfo) >= 0) { + const auto tail_addr = *snd_seq_port_info_get_addr(pinfo); + const auto tail_id = addr_to_id(tail_addr, false); + if (ignore(tail_addr)) { + continue; + } + + snd_seq_query_subscribe_t* sinfo = nullptr; + snd_seq_query_subscribe_alloca(&sinfo); + snd_seq_query_subscribe_set_root(sinfo, &tail_addr); + snd_seq_query_subscribe_set_index(sinfo, 0); + while (!snd_seq_query_port_subscribers(_seq, sinfo)) { + const auto head_addr = *snd_seq_query_subscribe_get_addr(sinfo); + const auto head_id = addr_to_id(head_addr, true); + + sink({ConnectionEvent{tail_id, head_id}}); + + snd_seq_query_subscribe_set_index( + sinfo, snd_seq_query_subscribe_get_index(sinfo) + 1); + } + } + } } bool AlsaDriver::ignore(const snd_seq_addr_t& addr, bool add) { - if (_ignored.find(addr) != _ignored.end()) { - return true; - } - - if (!add) { - return false; - } - - snd_seq_client_info_t* cinfo = nullptr; - snd_seq_client_info_alloca(&cinfo); - snd_seq_client_info_set_client(cinfo, addr.client); - snd_seq_get_any_client_info(_seq, addr.client, cinfo); - - snd_seq_port_info_t* pinfo = nullptr; - snd_seq_port_info_alloca(&pinfo); - snd_seq_port_info_set_client(pinfo, addr.client); - snd_seq_port_info_set_port(pinfo, addr.port); - snd_seq_get_any_port_info(_seq, addr.client, addr.port, pinfo); - - const int type = snd_seq_port_info_get_type(pinfo); - const int caps = snd_seq_port_info_get_capability(pinfo); - - if (caps & SND_SEQ_PORT_CAP_NO_EXPORT) { - _ignored.insert(addr); - return true; - } - - if (!((caps & SND_SEQ_PORT_CAP_READ) || (caps & SND_SEQ_PORT_CAP_WRITE) || - (caps & SND_SEQ_PORT_CAP_DUPLEX))) { - _ignored.insert(addr); - return true; - } - - if ((snd_seq_client_info_get_type(cinfo) != SND_SEQ_USER_CLIENT) && - ((type == SND_SEQ_PORT_SYSTEM_TIMER || - type == SND_SEQ_PORT_SYSTEM_ANNOUNCE))) { - _ignored.insert(addr); - return true; - } - - return false; + if (_ignored.find(addr) != _ignored.end()) { + return true; + } + + if (!add) { + return false; + } + + snd_seq_client_info_t* cinfo = nullptr; + snd_seq_client_info_alloca(&cinfo); + snd_seq_client_info_set_client(cinfo, addr.client); + snd_seq_get_any_client_info(_seq, addr.client, cinfo); + + snd_seq_port_info_t* pinfo = nullptr; + snd_seq_port_info_alloca(&pinfo); + snd_seq_port_info_set_client(pinfo, addr.client); + snd_seq_port_info_set_port(pinfo, addr.port); + snd_seq_get_any_port_info(_seq, addr.client, addr.port, pinfo); + + const int type = snd_seq_port_info_get_type(pinfo); + const int caps = snd_seq_port_info_get_capability(pinfo); + + if (caps & SND_SEQ_PORT_CAP_NO_EXPORT) { + _ignored.insert(addr); + return true; + } + + if (!((caps & SND_SEQ_PORT_CAP_READ) || (caps & SND_SEQ_PORT_CAP_WRITE) || + (caps & SND_SEQ_PORT_CAP_DUPLEX))) { + _ignored.insert(addr); + return true; + } + + if ((snd_seq_client_info_get_type(cinfo) != SND_SEQ_USER_CLIENT) && + ((type == SND_SEQ_PORT_SYSTEM_TIMER || + type == SND_SEQ_PORT_SYSTEM_ANNOUNCE))) { + _ignored.insert(addr); + return true; + } + + return false; } bool AlsaDriver::connect(const PortID& tail_id, const PortID& head_id) { - if (tail_id.type() != PortID::Type::alsa || - head_id.type() != PortID::Type::alsa) { - _log.error("[ALSA] Attempt to connect non-ALSA ports"); - return false; - } - - const snd_seq_addr_t tail_addr = {tail_id.alsa_client(), - tail_id.alsa_port()}; - - const snd_seq_addr_t head_addr = {head_id.alsa_client(), - head_id.alsa_port()}; - - if (tail_addr.client == head_addr.client && - tail_addr.port == head_addr.port) { - _log.warning("[ALSA] Refusing to connect port to itself"); - return false; - } - - bool result = true; - - snd_seq_port_subscribe_t* subs = nullptr; - snd_seq_port_subscribe_malloc(&subs); - snd_seq_port_subscribe_set_sender(subs, &tail_addr); - snd_seq_port_subscribe_set_dest(subs, &head_addr); - snd_seq_port_subscribe_set_exclusive(subs, 0); - snd_seq_port_subscribe_set_time_update(subs, 0); - snd_seq_port_subscribe_set_time_real(subs, 0); - - // Already connected (shouldn't happen) - if (!snd_seq_get_port_subscription(_seq, subs)) { - _log.error("[ALSA] Attempt to double subscribe ports"); - result = false; - } - - int ret = snd_seq_subscribe_port(_seq, subs); - if (ret < 0) { - _log.error( - fmt::format("[ALSA] Subscription failed ({})", snd_strerror(ret))); - result = false; - } - - if (!result) { - _log.error( - fmt::format("[ALSA] Failed to connect {} => {}", tail_id, head_id)); - } - - return (!result); + if (tail_id.type() != PortID::Type::alsa || + head_id.type() != PortID::Type::alsa) { + _log.error("[ALSA] Attempt to connect non-ALSA ports"); + return false; + } + + const snd_seq_addr_t tail_addr = {tail_id.alsa_client(), tail_id.alsa_port()}; + + const snd_seq_addr_t head_addr = {head_id.alsa_client(), head_id.alsa_port()}; + + if (tail_addr.client == head_addr.client && + tail_addr.port == head_addr.port) { + _log.warning("[ALSA] Refusing to connect port to itself"); + return false; + } + + bool result = true; + + snd_seq_port_subscribe_t* subs = nullptr; + snd_seq_port_subscribe_malloc(&subs); + snd_seq_port_subscribe_set_sender(subs, &tail_addr); + snd_seq_port_subscribe_set_dest(subs, &head_addr); + snd_seq_port_subscribe_set_exclusive(subs, 0); + snd_seq_port_subscribe_set_time_update(subs, 0); + snd_seq_port_subscribe_set_time_real(subs, 0); + + // Already connected (shouldn't happen) + if (!snd_seq_get_port_subscription(_seq, subs)) { + _log.error("[ALSA] Attempt to double subscribe ports"); + result = false; + } + + int ret = snd_seq_subscribe_port(_seq, subs); + if (ret < 0) { + _log.error( + fmt::format("[ALSA] Subscription failed ({})", snd_strerror(ret))); + result = false; + } + + if (!result) { + _log.error( + fmt::format("[ALSA] Failed to connect {} => {}", tail_id, head_id)); + } + + return (!result); } bool AlsaDriver::disconnect(const PortID& tail_id, const PortID& head_id) { - if (tail_id.type() != PortID::Type::alsa || - head_id.type() != PortID::Type::alsa) { - _log.error("[ALSA] Attempt to disconnect non-ALSA ports"); - return false; - } - - const snd_seq_addr_t tail_addr = {tail_id.alsa_client(), - tail_id.alsa_port()}; - - const snd_seq_addr_t head_addr = {head_id.alsa_client(), - head_id.alsa_port()}; - - snd_seq_port_subscribe_t* subs = nullptr; - snd_seq_port_subscribe_malloc(&subs); - snd_seq_port_subscribe_set_sender(subs, &tail_addr); - snd_seq_port_subscribe_set_dest(subs, &head_addr); - snd_seq_port_subscribe_set_exclusive(subs, 0); - snd_seq_port_subscribe_set_time_update(subs, 0); - snd_seq_port_subscribe_set_time_real(subs, 0); - - // Not connected (shouldn't happen) - if (snd_seq_get_port_subscription(_seq, subs) != 0) { - _log.error( - "[ALSA] Attempt to unsubscribe ports that are not subscribed"); - return false; - } - - int ret = snd_seq_unsubscribe_port(_seq, subs); - if (ret < 0) { - _log.error(fmt::format("[ALSA] Failed to disconnect {} => {} ({})", - tail_id, - head_id, - snd_strerror(ret))); - return false; - } - - return true; + if (tail_id.type() != PortID::Type::alsa || + head_id.type() != PortID::Type::alsa) { + _log.error("[ALSA] Attempt to disconnect non-ALSA ports"); + return false; + } + + const snd_seq_addr_t tail_addr = {tail_id.alsa_client(), tail_id.alsa_port()}; + + const snd_seq_addr_t head_addr = {head_id.alsa_client(), head_id.alsa_port()}; + + snd_seq_port_subscribe_t* subs = nullptr; + snd_seq_port_subscribe_malloc(&subs); + snd_seq_port_subscribe_set_sender(subs, &tail_addr); + snd_seq_port_subscribe_set_dest(subs, &head_addr); + snd_seq_port_subscribe_set_exclusive(subs, 0); + snd_seq_port_subscribe_set_time_update(subs, 0); + snd_seq_port_subscribe_set_time_real(subs, 0); + + // Not connected (shouldn't happen) + if (snd_seq_get_port_subscription(_seq, subs) != 0) { + _log.error("[ALSA] Attempt to unsubscribe ports that are not subscribed"); + return false; + } + + int ret = snd_seq_unsubscribe_port(_seq, subs); + if (ret < 0) { + _log.error(fmt::format("[ALSA] Failed to disconnect {} => {} ({})", + tail_id, + head_id, + snd_strerror(ret))); + return false; + } + + return true; } bool AlsaDriver::create_refresh_port() { - snd_seq_port_info_t* port_info = nullptr; - snd_seq_port_info_alloca(&port_info); - snd_seq_port_info_set_name(port_info, "System Announcement Receiver"); - snd_seq_port_info_set_type(port_info, SND_SEQ_PORT_TYPE_APPLICATION); - snd_seq_port_info_set_capability(port_info, - SND_SEQ_PORT_CAP_WRITE | - SND_SEQ_PORT_CAP_SUBS_WRITE | - SND_SEQ_PORT_CAP_NO_EXPORT); - - int ret = snd_seq_create_port(_seq, port_info); - if (ret) { - _log.error( - fmt::format("[ALSA] Error creating port ({})", snd_strerror(ret))); - return false; - } - - // Subscribe the port to the system announcer - ret = snd_seq_connect_from(_seq, - snd_seq_port_info_get_port(port_info), - SND_SEQ_CLIENT_SYSTEM, - SND_SEQ_PORT_SYSTEM_ANNOUNCE); - if (ret) { - _log.error( - fmt::format("[ALSA] Failed to connect to system announce port ({})", - snd_strerror(ret))); - return false; - } - - return true; + snd_seq_port_info_t* port_info = nullptr; + snd_seq_port_info_alloca(&port_info); + snd_seq_port_info_set_name(port_info, "System Announcement Receiver"); + snd_seq_port_info_set_type(port_info, SND_SEQ_PORT_TYPE_APPLICATION); + snd_seq_port_info_set_capability(port_info, + SND_SEQ_PORT_CAP_WRITE | + SND_SEQ_PORT_CAP_SUBS_WRITE | + SND_SEQ_PORT_CAP_NO_EXPORT); + + int ret = snd_seq_create_port(_seq, port_info); + if (ret) { + _log.error( + fmt::format("[ALSA] Error creating port ({})", snd_strerror(ret))); + return false; + } + + // Subscribe the port to the system announcer + ret = snd_seq_connect_from(_seq, + snd_seq_port_info_get_port(port_info), + SND_SEQ_CLIENT_SYSTEM, + SND_SEQ_PORT_SYSTEM_ANNOUNCE); + if (ret) { + _log.error( + fmt::format("[ALSA] Failed to connect to system announce port ({})", + snd_strerror(ret))); + return false; + } + + return true; } void* AlsaDriver::refresh_main(void* me) { - auto* ad = static_cast(me); - ad->_refresh_main(); - return nullptr; + auto* ad = static_cast(me); + ad->_refresh_main(); + return nullptr; } void AlsaDriver::_refresh_main() { - if (!create_refresh_port()) { - _log.error( - "[ALSA] Could not create listen port, auto-refresh disabled"); - return; - } - - int caps = 0; - - snd_seq_client_info_t* cinfo = nullptr; - snd_seq_client_info_alloca(&cinfo); - - snd_seq_port_info_t* pinfo = nullptr; - snd_seq_port_info_alloca(&pinfo); - - snd_seq_event_t* ev = nullptr; - while (snd_seq_event_input(_seq, &ev) > 0) { - assert(ev); - - switch (ev->type) { - case SND_SEQ_EVENT_CLIENT_START: - snd_seq_get_any_client_info(_seq, ev->data.addr.client, cinfo); - _emit_event(ClientCreationEvent{ - ClientID::alsa(ev->data.addr.client), - client_info(cinfo), - }); - break; - - case SND_SEQ_EVENT_CLIENT_EXIT: - _emit_event(ClientDestructionEvent{ - ClientID::alsa(ev->data.addr.client), - }); - break; - - case SND_SEQ_EVENT_CLIENT_CHANGE: - break; - - case SND_SEQ_EVENT_PORT_START: - snd_seq_get_any_client_info(_seq, ev->data.addr.client, cinfo); - snd_seq_get_any_port_info( - _seq, ev->data.addr.client, ev->data.addr.port, pinfo); - caps = snd_seq_port_info_get_capability(pinfo); - - if (!ignore(ev->data.addr)) { - _emit_event(PortCreationEvent{ - addr_to_id(ev->data.addr, (caps & SND_SEQ_PORT_CAP_READ)), - port_info(pinfo), - }); - } - break; - - case SND_SEQ_EVENT_PORT_EXIT: - if (!ignore(ev->data.addr, false)) { - // Note: getting caps at this point does not work - // Delete both inputs and outputs (to handle duplex ports) - _emit_event( - PortDestructionEvent{addr_to_id(ev->data.addr, true)}); - _emit_event( - PortDestructionEvent{addr_to_id(ev->data.addr, false)}); - } - break; - - case SND_SEQ_EVENT_PORT_CHANGE: - break; - - case SND_SEQ_EVENT_PORT_SUBSCRIBED: - if (!ignore(ev->data.connect.sender) && - !ignore(ev->data.connect.dest)) { - _emit_event( - ConnectionEvent{addr_to_id(ev->data.connect.sender, false), - addr_to_id(ev->data.connect.dest, true)}); - } - break; - - case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: - if (!ignore(ev->data.connect.sender) && - !ignore(ev->data.connect.dest)) { - _emit_event(DisconnectionEvent{ - addr_to_id(ev->data.connect.sender, false), - addr_to_id(ev->data.connect.dest, true)}); - } - break; - - case SND_SEQ_EVENT_RESET: - default: - break; - } - } + if (!create_refresh_port()) { + _log.error("[ALSA] Could not create listen port, auto-refresh disabled"); + return; + } + + int caps = 0; + + snd_seq_client_info_t* cinfo = nullptr; + snd_seq_client_info_alloca(&cinfo); + + snd_seq_port_info_t* pinfo = nullptr; + snd_seq_port_info_alloca(&pinfo); + + snd_seq_event_t* ev = nullptr; + while (snd_seq_event_input(_seq, &ev) > 0) { + assert(ev); + + switch (ev->type) { + case SND_SEQ_EVENT_CLIENT_START: + snd_seq_get_any_client_info(_seq, ev->data.addr.client, cinfo); + _emit_event(ClientCreationEvent{ + ClientID::alsa(ev->data.addr.client), + client_info(cinfo), + }); + break; + + case SND_SEQ_EVENT_CLIENT_EXIT: + _emit_event(ClientDestructionEvent{ + ClientID::alsa(ev->data.addr.client), + }); + break; + + case SND_SEQ_EVENT_CLIENT_CHANGE: + break; + + case SND_SEQ_EVENT_PORT_START: + snd_seq_get_any_client_info(_seq, ev->data.addr.client, cinfo); + snd_seq_get_any_port_info( + _seq, ev->data.addr.client, ev->data.addr.port, pinfo); + caps = snd_seq_port_info_get_capability(pinfo); + + if (!ignore(ev->data.addr)) { + _emit_event(PortCreationEvent{ + addr_to_id(ev->data.addr, (caps & SND_SEQ_PORT_CAP_READ)), + port_info(pinfo), + }); + } + break; + + case SND_SEQ_EVENT_PORT_EXIT: + if (!ignore(ev->data.addr, false)) { + // Note: getting caps at this point does not work + // Delete both inputs and outputs (to handle duplex ports) + _emit_event(PortDestructionEvent{addr_to_id(ev->data.addr, true)}); + _emit_event(PortDestructionEvent{addr_to_id(ev->data.addr, false)}); + } + break; + + case SND_SEQ_EVENT_PORT_CHANGE: + break; + + case SND_SEQ_EVENT_PORT_SUBSCRIBED: + if (!ignore(ev->data.connect.sender) && !ignore(ev->data.connect.dest)) { + _emit_event(ConnectionEvent{addr_to_id(ev->data.connect.sender, false), + addr_to_id(ev->data.connect.dest, true)}); + } + break; + + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: + if (!ignore(ev->data.connect.sender) && !ignore(ev->data.connect.dest)) { + _emit_event( + DisconnectionEvent{addr_to_id(ev->data.connect.sender, false), + addr_to_id(ev->data.connect.dest, true)}); + } + break; + + case SND_SEQ_EVENT_RESET: + default: + break; + } + } } } // namespace @@ -556,7 +543,7 @@ AlsaDriver::_refresh_main() std::unique_ptr make_alsa_driver(ILog& log, Driver::EventSink emit_event) { - return std::unique_ptr{new AlsaDriver{log, std::move(emit_event)}}; + return std::unique_ptr{new AlsaDriver{log, std::move(emit_event)}}; } } // namespace patchage diff --git a/src/AudioDriver.hpp b/src/AudioDriver.hpp index 654b8bb..06cfe7f 100644 --- a/src/AudioDriver.hpp +++ b/src/AudioDriver.hpp @@ -28,24 +28,24 @@ namespace patchage { class AudioDriver : public Driver { public: - explicit AudioDriver(EventSink emit_event) - : Driver{std::move(emit_event)} - {} + explicit AudioDriver(EventSink emit_event) + : Driver{std::move(emit_event)} + {} - /// Return the number of xruns (dropouts) since the last reset - virtual uint32_t xruns() = 0; + /// Return the number of xruns (dropouts) since the last reset + virtual uint32_t xruns() = 0; - /// Reset the xrun count - virtual void reset_xruns() = 0; + /// Reset the xrun count + virtual void reset_xruns() = 0; - /// Return the current buffer size in frames - virtual uint32_t buffer_size() = 0; + /// Return the current buffer size in frames + virtual uint32_t buffer_size() = 0; - /// Try to set the current buffer size in frames, return true on success - virtual bool set_buffer_size(uint32_t frames) = 0; + /// Try to set the current buffer size in frames, return true on success + virtual bool set_buffer_size(uint32_t frames) = 0; - /// Return the current sample rate in Hz - virtual uint32_t sample_rate() = 0; + /// Return the current sample rate in Hz + virtual uint32_t sample_rate() = 0; }; } // namespace patchage diff --git a/src/Canvas.cpp b/src/Canvas.cpp index 306c62f..30212c7 100644 --- a/src/Canvas.cpp +++ b/src/Canvas.cpp @@ -56,293 +56,289 @@ PATCHAGE_RESTORE_WARNINGS namespace patchage { Canvas::Canvas(Connector& connector, int width, int height) - : Ganv::Canvas(width, height) - , _connector(connector) + : Ganv::Canvas(width, height) + , _connector(connector) { - signal_event.connect(sigc::mem_fun(this, &Canvas::on_event)); - signal_connect.connect(sigc::mem_fun(this, &Canvas::on_connect)); - signal_disconnect.connect(sigc::mem_fun(this, &Canvas::on_disconnect)); + signal_event.connect(sigc::mem_fun(this, &Canvas::on_event)); + signal_connect.connect(sigc::mem_fun(this, &Canvas::on_connect)); + signal_disconnect.connect(sigc::mem_fun(this, &Canvas::on_disconnect)); } CanvasPort* Canvas::create_port(Patchage& patchage, const PortID& id, const PortInfo& info) { - const auto client_id = id.client(); - - const auto port_name = - ((id.type() == PortID::Type::alsa) ? info.label : PortNames(id).port()); - - // Figure out the client name, for ALSA we need the metadata cache - std::string client_name; - if (id.type() == PortID::Type::alsa) { - const auto client_info = patchage.metadata().client(client_id); - if (!client_info) { - patchage.log().error(fmt::format( - R"(Unable to add port "{}", client "{}" is unknown)", - id, - client_id)); - - return nullptr; - } - - client_name = client_info->label; - } else { - client_name = PortNames(id).client(); - } - - // Determine the module type to place the port on in case of splitting - SignalDirection module_type = SignalDirection::duplex; - if (patchage.conf().get_module_split(client_name, info.is_terminal)) { - module_type = info.direction; - } - - // Find or create parent module - CanvasModule* parent = find_module(client_id, module_type); - if (!parent) { - parent = - new CanvasModule(&patchage, client_name, module_type, client_id); - - parent->load_location(); - add_module(client_id, parent); - } - - if (parent->get_port(id)) { - // TODO: Update existing port? - patchage.log().error(fmt::format( - R"(Module "{}" already has port "{}")", client_name, port_name)); - return nullptr; - } - - auto* const port = new CanvasPort(*parent, - info.type, - id, - port_name, - info.label, - info.direction == SignalDirection::input, - patchage.conf().get_port_color(info.type), - patchage.show_human_names(), - info.order); - - _port_index.insert(std::make_pair(id, port)); - - return port; + const auto client_id = id.client(); + + const auto port_name = + ((id.type() == PortID::Type::alsa) ? info.label : PortNames(id).port()); + + // Figure out the client name, for ALSA we need the metadata cache + std::string client_name; + if (id.type() == PortID::Type::alsa) { + const auto client_info = patchage.metadata().client(client_id); + if (!client_info) { + patchage.log().error(fmt::format( + R"(Unable to add port "{}", client "{}" is unknown)", id, client_id)); + + return nullptr; + } + + client_name = client_info->label; + } else { + client_name = PortNames(id).client(); + } + + // Determine the module type to place the port on in case of splitting + SignalDirection module_type = SignalDirection::duplex; + if (patchage.conf().get_module_split(client_name, info.is_terminal)) { + module_type = info.direction; + } + + // Find or create parent module + CanvasModule* parent = find_module(client_id, module_type); + if (!parent) { + parent = new CanvasModule(&patchage, client_name, module_type, client_id); + + parent->load_location(); + add_module(client_id, parent); + } + + if (parent->get_port(id)) { + // TODO: Update existing port? + patchage.log().error(fmt::format( + R"(Module "{}" already has port "{}")", client_name, port_name)); + return nullptr; + } + + auto* const port = new CanvasPort(*parent, + info.type, + id, + port_name, + info.label, + info.direction == SignalDirection::input, + patchage.conf().get_port_color(info.type), + patchage.show_human_names(), + info.order); + + _port_index.insert(std::make_pair(id, port)); + + return port; } CanvasModule* Canvas::find_module(const ClientID& id, const SignalDirection type) { - auto i = _module_index.find(id); + auto i = _module_index.find(id); - CanvasModule* io_module = nullptr; - for (; i != _module_index.end() && i->first == id; ++i) { - if (i->second->type() == type) { - return i->second; - } + CanvasModule* io_module = nullptr; + for (; i != _module_index.end() && i->first == id; ++i) { + if (i->second->type() == type) { + return i->second; + } - if (i->second->type() == SignalDirection::duplex) { - io_module = i->second; - } - } + if (i->second->type() == SignalDirection::duplex) { + io_module = i->second; + } + } - // Return InputOutput module for Input or Output (or nullptr if not found) - return io_module; + // Return InputOutput module for Input or Output (or nullptr if not found) + return io_module; } void Canvas::remove_module(const ClientID& id) { - auto i = _module_index.find(id); - while (i != _module_index.end()) { - CanvasModule* mod = i->second; - _module_index.erase(i); - i = _module_index.find(id); - delete mod; - } + auto i = _module_index.find(id); + while (i != _module_index.end()) { + CanvasModule* mod = i->second; + _module_index.erase(i); + i = _module_index.find(id); + delete mod; + } } CanvasPort* Canvas::find_port(const PortID& id) { - auto i = _port_index.find(id); - if (i != _port_index.end()) { - assert(i->second->get_module()); - return i->second; - } + auto i = _port_index.find(id); + if (i != _port_index.end()) { + assert(i->second->get_module()); + return i->second; + } - return nullptr; + return nullptr; } void Canvas::remove_port(const PortID& id) { - CanvasPort* const port = find_port(id); - _port_index.erase(id); - delete port; + CanvasPort* const port = find_port(id); + _port_index.erase(id); + delete port; } -struct RemovePortsData -{ - using Predicate = bool (*)(const CanvasPort*); +struct RemovePortsData { + using Predicate = bool (*)(const CanvasPort*); - explicit RemovePortsData(Predicate p) - : pred(p) - {} + explicit RemovePortsData(Predicate p) + : pred(p) + {} - Predicate pred; - std::set empty; + Predicate pred; + std::set empty; }; static void delete_port_if_matches(GanvPort* port, void* cdata) { - auto* data = static_cast(cdata); - auto* pport = dynamic_cast(Glib::wrap(port)); - if (pport && data->pred(pport)) { - delete pport; - } + auto* data = static_cast(cdata); + auto* pport = dynamic_cast(Glib::wrap(port)); + if (pport && data->pred(pport)) { + delete pport; + } } static void remove_ports_matching(GanvNode* node, void* cdata) { - if (!GANV_IS_MODULE(node)) { - return; - } + if (!GANV_IS_MODULE(node)) { + return; + } - Ganv::Module* cmodule = Glib::wrap(GANV_MODULE(node)); - auto* pmodule = dynamic_cast(cmodule); - if (!pmodule) { - return; - } + Ganv::Module* cmodule = Glib::wrap(GANV_MODULE(node)); + auto* pmodule = dynamic_cast(cmodule); + if (!pmodule) { + return; + } - auto* data = static_cast(cdata); + auto* data = static_cast(cdata); - pmodule->for_each_port(delete_port_if_matches, data); + pmodule->for_each_port(delete_port_if_matches, data); - if (pmodule->num_ports() == 0) { - data->empty.insert(pmodule); - } + if (pmodule->num_ports() == 0) { + data->empty.insert(pmodule); + } } void Canvas::remove_ports(bool (*pred)(const CanvasPort*)) { - RemovePortsData data(pred); - - for_each_node(remove_ports_matching, &data); - - for (auto i = _port_index.begin(); i != _port_index.end();) { - auto next = i; - ++next; - if (pred(i->second)) { - _port_index.erase(i); - } - i = next; - } - - for (CanvasModule* m : data.empty) { - delete m; - } + RemovePortsData data(pred); + + for_each_node(remove_ports_matching, &data); + + for (auto i = _port_index.begin(); i != _port_index.end();) { + auto next = i; + ++next; + if (pred(i->second)) { + _port_index.erase(i); + } + i = next; + } + + for (CanvasModule* m : data.empty) { + delete m; + } } void Canvas::on_connect(Ganv::Node* port1, Ganv::Node* port2) { - auto* const p1 = dynamic_cast(port1); - auto* const p2 = dynamic_cast(port2); - - if (p1 && p2) { - if (p1->is_output() && p2->is_input()) { - _connector.connect(p1->id(), p2->id()); - } else if (p2->is_output() && p1->is_input()) { - _connector.connect(p2->id(), p1->id()); - } - } + auto* const p1 = dynamic_cast(port1); + auto* const p2 = dynamic_cast(port2); + + if (p1 && p2) { + if (p1->is_output() && p2->is_input()) { + _connector.connect(p1->id(), p2->id()); + } else if (p2->is_output() && p1->is_input()) { + _connector.connect(p2->id(), p1->id()); + } + } } void Canvas::on_disconnect(Ganv::Node* port1, Ganv::Node* port2) { - auto* const p1 = dynamic_cast(port1); - auto* const p2 = dynamic_cast(port2); - - if (p1 && p2) { - if (p1->is_output() && p2->is_input()) { - _connector.disconnect(p1->id(), p2->id()); - } else if (p2->is_output() && p1->is_input()) { - _connector.disconnect(p2->id(), p1->id()); - } - } + auto* const p1 = dynamic_cast(port1); + auto* const p2 = dynamic_cast(port2); + + if (p1 && p2) { + if (p1->is_output() && p2->is_input()) { + _connector.disconnect(p1->id(), p2->id()); + } else if (p2->is_output() && p1->is_input()) { + _connector.disconnect(p2->id(), p1->id()); + } + } } void Canvas::add_module(const ClientID& id, CanvasModule* module) { - _module_index.emplace(id, module); - - // Join partners, if applicable - CanvasModule* in_module = nullptr; - CanvasModule* out_module = nullptr; - if (module->type() == SignalDirection::input) { - in_module = module; - out_module = find_module(id, SignalDirection::output); - } else if (module->type() == SignalDirection::output) { - in_module = find_module(id, SignalDirection::input); - out_module = module; - } - - if (in_module && out_module) { - out_module->set_partner(in_module); - } + _module_index.emplace(id, module); + + // Join partners, if applicable + CanvasModule* in_module = nullptr; + CanvasModule* out_module = nullptr; + if (module->type() == SignalDirection::input) { + in_module = module; + out_module = find_module(id, SignalDirection::output); + } else if (module->type() == SignalDirection::output) { + in_module = find_module(id, SignalDirection::input); + out_module = module; + } + + if (in_module && out_module) { + out_module->set_partner(in_module); + } } void disconnect_edge(GanvEdge* edge, void* data) { - auto* canvas = static_cast(data); - Ganv::Edge* edgemm = Glib::wrap(edge); - canvas->on_disconnect(edgemm->get_tail(), edgemm->get_head()); + auto* canvas = static_cast(data); + Ganv::Edge* edgemm = Glib::wrap(edge); + canvas->on_disconnect(edgemm->get_tail(), edgemm->get_head()); } bool Canvas::on_event(GdkEvent* ev) { - if (ev->type == GDK_KEY_PRESS && ev->key.keyval == GDK_KEY_Delete) { - for_each_selected_edge(disconnect_edge, this); - clear_selection(); - return true; - } + if (ev->type == GDK_KEY_PRESS && ev->key.keyval == GDK_KEY_Delete) { + for_each_selected_edge(disconnect_edge, this); + clear_selection(); + return true; + } - return false; + return false; } bool Canvas::make_connection(Ganv::Node* tail, Ganv::Node* head) { - new Ganv::Edge(*this, tail, head); - return true; + new Ganv::Edge(*this, tail, head); + return true; } void Canvas::remove_module(CanvasModule* module) { - // Remove module from cache - for (auto i = _module_index.find(module->id()); - i != _module_index.end() && i->first == module->id(); - ++i) { - if (i->second == module) { - _module_index.erase(i); - return; - } - } + // Remove module from cache + for (auto i = _module_index.find(module->id()); + i != _module_index.end() && i->first == module->id(); + ++i) { + if (i->second == module) { + _module_index.erase(i); + return; + } + } } void Canvas::clear() { - _port_index.clear(); - _module_index.clear(); - Ganv::Canvas::clear(); + _port_index.clear(); + _module_index.clear(); + Ganv::Canvas::clear(); } } // namespace patchage diff --git a/src/Canvas.hpp b/src/Canvas.hpp index dbc902a..59b886b 100644 --- a/src/Canvas.hpp +++ b/src/Canvas.hpp @@ -47,41 +47,42 @@ class Connector; class Canvas : public Ganv::Canvas { public: - Canvas(Connector& connector, int width, int height); + Canvas(Connector& connector, int width, int height); - CanvasPort* - create_port(Patchage& patchage, const PortID& id, const PortInfo& info); + CanvasPort* create_port(Patchage& patchage, + const PortID& id, + const PortInfo& info); - CanvasModule* find_module(const ClientID& id, SignalDirection type); - CanvasPort* find_port(const PortID& id); + CanvasModule* find_module(const ClientID& id, SignalDirection type); + CanvasPort* find_port(const PortID& id); - void remove_module(const ClientID& id); - void remove_module(CanvasModule* module); + void remove_module(const ClientID& id); + void remove_module(CanvasModule* module); - void remove_ports(bool (*pred)(const CanvasPort*)); + void remove_ports(bool (*pred)(const CanvasPort*)); - void add_module(const ClientID& id, CanvasModule* module); + void add_module(const ClientID& id, CanvasModule* module); - bool make_connection(Ganv::Node* tail, Ganv::Node* head); + bool make_connection(Ganv::Node* tail, Ganv::Node* head); - void remove_port(const PortID& id); + void remove_port(const PortID& id); - void clear() override; + void clear() override; private: - using PortIndex = std::map; - using ModuleIndex = std::multimap; + using PortIndex = std::map; + using ModuleIndex = std::multimap; - friend void disconnect_edge(GanvEdge*, void*); + friend void disconnect_edge(GanvEdge*, void*); - bool on_event(GdkEvent* ev); + bool on_event(GdkEvent* ev); - void on_connect(Ganv::Node* port1, Ganv::Node* port2); - void on_disconnect(Ganv::Node* port1, Ganv::Node* port2); + void on_connect(Ganv::Node* port1, Ganv::Node* port2); + void on_disconnect(Ganv::Node* port1, Ganv::Node* port2); - Connector& _connector; - PortIndex _port_index; - ModuleIndex _module_index; + Connector& _connector; + PortIndex _port_index; + ModuleIndex _module_index; }; } // namespace patchage diff --git a/src/CanvasModule.cpp b/src/CanvasModule.cpp index 0f32f14..4b74f9e 100644 --- a/src/CanvasModule.cpp +++ b/src/CanvasModule.cpp @@ -49,143 +49,143 @@ CanvasModule::CanvasModule(Patchage* app, ClientID id, double x, double y) - : Module(*app->canvas(), name, x, y) - , _app(app) - , _menu(nullptr) - , _name(name) - , _type(type) - , _id(std::move(id)) + : Module(*app->canvas(), name, x, y) + , _app(app) + , _menu(nullptr) + , _name(name) + , _type(type) + , _id(std::move(id)) { - signal_event().connect(sigc::mem_fun(this, &CanvasModule::on_event)); + signal_event().connect(sigc::mem_fun(this, &CanvasModule::on_event)); - signal_moved().connect(sigc::mem_fun(this, &CanvasModule::store_location)); + signal_moved().connect(sigc::mem_fun(this, &CanvasModule::store_location)); - // Set as source by default, turned off if input ports added - set_is_source(true); + // Set as source by default, turned off if input ports added + set_is_source(true); } CanvasModule::~CanvasModule() { - _app->canvas()->remove_module(this); - delete _menu; - _menu = nullptr; + _app->canvas()->remove_module(this); + delete _menu; + _menu = nullptr; } void CanvasModule::update_menu() { - if (!_menu) { - return; - } - - if (_type == SignalDirection::duplex) { - bool has_in = false; - bool has_out = false; - for (const auto* p : *this) { - if (p->is_input()) { - has_in = true; - } else { - has_out = true; - } - - if (has_in && has_out) { - _menu->items()[0].show(); // Show "Split" menu item - return; - } - } - _menu->items()[0].hide(); // Hide "Split" menu item - } + if (!_menu) { + return; + } + + if (_type == SignalDirection::duplex) { + bool has_in = false; + bool has_out = false; + for (const auto* p : *this) { + if (p->is_input()) { + has_in = true; + } else { + has_out = true; + } + + if (has_in && has_out) { + _menu->items()[0].show(); // Show "Split" menu item + return; + } + } + _menu->items()[0].hide(); // Hide "Split" menu item + } } bool CanvasModule::show_menu(GdkEventButton* ev) { - _menu = new Gtk::Menu(); - Gtk::Menu::MenuList& items = _menu->items(); - - if (_type == SignalDirection::duplex) { - items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Split", sigc::mem_fun(this, &CanvasModule::split))); - update_menu(); - } else { - items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Join", sigc::mem_fun(this, &CanvasModule::join))); - } - - items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Disconnect All", sigc::mem_fun(this, &CanvasModule::disconnect_all))); - - _menu->popup(ev->button, ev->time); - return true; + _menu = new Gtk::Menu(); + Gtk::Menu::MenuList& items = _menu->items(); + + if (_type == SignalDirection::duplex) { + items.push_back(Gtk::Menu_Helpers::MenuElem( + "_Split", sigc::mem_fun(this, &CanvasModule::split))); + update_menu(); + } else { + items.push_back(Gtk::Menu_Helpers::MenuElem( + "_Join", sigc::mem_fun(this, &CanvasModule::join))); + } + + items.push_back(Gtk::Menu_Helpers::MenuElem( + "_Disconnect All", sigc::mem_fun(this, &CanvasModule::disconnect_all))); + + _menu->popup(ev->button, ev->time); + return true; } bool CanvasModule::on_event(GdkEvent* ev) { - if (ev->type == GDK_BUTTON_PRESS && ev->button.button == 3) { - return show_menu(&ev->button); - } - return false; + if (ev->type == GDK_BUTTON_PRESS && ev->button.button == 3) { + return show_menu(&ev->button); + } + return false; } void CanvasModule::load_location() { - Coord loc; - - if (_app->conf().get_module_location(_name, _type, loc)) { - move_to(loc.x, loc.y); - } else { - const double x = 20 + rand() % 640; - const double y = 20 + rand() % 480; - - // Move, then store generated location so it is stable - move_to(x, y); - store_location(x, y); - } + Coord loc; + + if (_app->conf().get_module_location(_name, _type, loc)) { + move_to(loc.x, loc.y); + } else { + const double x = 20 + rand() % 640; + const double y = 20 + rand() % 480; + + // Move, then store generated location so it is stable + move_to(x, y); + store_location(x, y); + } } void CanvasModule::store_location(double x, double y) { - _app->conf().set_module_location(_name, _type, {x, y}); + _app->conf().set_module_location(_name, _type, {x, y}); } void CanvasModule::split() { - assert(_type == SignalDirection::duplex); - _app->conf().set_module_split(_name, true); - _app->refresh(); + assert(_type == SignalDirection::duplex); + _app->conf().set_module_split(_name, true); + _app->refresh(); } void CanvasModule::join() { - assert(_type != SignalDirection::duplex); - _app->conf().set_module_split(_name, false); - _app->refresh(); + assert(_type != SignalDirection::duplex); + _app->conf().set_module_split(_name, false); + _app->refresh(); } void CanvasModule::disconnect_all() { - for (Ganv::Port* p : *this) { - p->disconnect(); - } + for (Ganv::Port* p : *this) { + p->disconnect(); + } } CanvasPort* CanvasModule::get_port(const PortID& id) { - for (Ganv::Port* p : *this) { - auto* pport = dynamic_cast(p); - if (pport && pport->id() == id) { - return pport; - } - } - - return nullptr; + for (Ganv::Port* p : *this) { + auto* pport = dynamic_cast(p); + if (pport && pport->id() == id) { + return pport; + } + } + + return nullptr; } } // namespace patchage diff --git a/src/CanvasModule.hpp b/src/CanvasModule.hpp index 3361fbb..b8c9523 100644 --- a/src/CanvasModule.hpp +++ b/src/CanvasModule.hpp @@ -43,45 +43,45 @@ class Patchage; class CanvasModule : public Ganv::Module { public: - CanvasModule(Patchage* app, - const std::string& name, - SignalDirection type, - ClientID id, - double x = 0.0, - double y = 0.0); + CanvasModule(Patchage* app, + const std::string& name, + SignalDirection type, + ClientID id, + double x = 0.0, + double y = 0.0); - CanvasModule(const CanvasModule&) = delete; - CanvasModule& operator=(const CanvasModule&) = delete; + CanvasModule(const CanvasModule&) = delete; + CanvasModule& operator=(const CanvasModule&) = delete; - CanvasModule(CanvasModule&&) = delete; - CanvasModule& operator=(CanvasModule&&) = delete; + CanvasModule(CanvasModule&&) = delete; + CanvasModule& operator=(CanvasModule&&) = delete; - ~CanvasModule() override; + ~CanvasModule() override; - bool show_menu(GdkEventButton* ev); - void update_menu(); + bool show_menu(GdkEventButton* ev); + void update_menu(); - void split(); - void join(); - void disconnect_all(); + void split(); + void join(); + void disconnect_all(); - CanvasPort* get_port(const PortID& id); + CanvasPort* get_port(const PortID& id); - void load_location(); - void store_location(double x, double y); + void load_location(); + void store_location(double x, double y); - SignalDirection type() const { return _type; } - ClientID id() const { return _id; } - const std::string& name() const { return _name; } + SignalDirection type() const { return _type; } + ClientID id() const { return _id; } + const std::string& name() const { return _name; } protected: - bool on_event(GdkEvent* ev) override; + bool on_event(GdkEvent* ev) override; - Patchage* _app; - Gtk::Menu* _menu; - std::string _name; - SignalDirection _type; - ClientID _id; + Patchage* _app; + Gtk::Menu* _menu; + std::string _name; + SignalDirection _type; + ClientID _id; }; } // namespace patchage diff --git a/src/CanvasPort.hpp b/src/CanvasPort.hpp index e8e809f..3376e15 100644 --- a/src/CanvasPort.hpp +++ b/src/CanvasPort.hpp @@ -48,71 +48,71 @@ namespace patchage { class CanvasPort : public Ganv::Port { public: - CanvasPort(Ganv::Module& module, - PortType type, - PortID id, - const std::string& name, - const std::string& human_name, - bool is_input, - uint32_t color, - bool show_human_name, - boost::optional order = boost::optional()) - : Port(module, - (show_human_name && !human_name.empty()) ? human_name : name, - is_input, - color) - , _type(type) - , _id(std::move(id)) - , _name(name) - , _human_name(human_name) - , _order(order) - { - signal_event().connect(sigc::mem_fun(this, &CanvasPort::on_event)); - } - - CanvasPort(const CanvasPort&) = delete; - CanvasPort& operator=(const CanvasPort&) = delete; - - CanvasPort(CanvasPort&&) = delete; - CanvasPort& operator=(CanvasPort&&) = delete; - - ~CanvasPort() override = default; - - void show_human_name(bool human) - { - if (human && !_human_name.empty()) { - set_label(_human_name.c_str()); - } else { - set_label(_name.c_str()); - } - } - - bool on_event(GdkEvent* ev) override - { - if (ev->type != GDK_BUTTON_PRESS || ev->button.button != 3) { - return false; - } - - Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); - menu->items().push_back(Gtk::Menu_Helpers::MenuElem( - "Disconnect", sigc::mem_fun(this, &Port::disconnect))); - - menu->popup(ev->button.button, ev->button.time); - return true; - } - - PortType type() const { return _type; } - PortID id() const { return _id; } - const std::string& name() const { return _name; } - const std::string& human_name() const { return _human_name; } - const boost::optional& order() const { return _order; } + CanvasPort(Ganv::Module& module, + PortType type, + PortID id, + const std::string& name, + const std::string& human_name, + bool is_input, + uint32_t color, + bool show_human_name, + boost::optional order = boost::optional()) + : Port(module, + (show_human_name && !human_name.empty()) ? human_name : name, + is_input, + color) + , _type(type) + , _id(std::move(id)) + , _name(name) + , _human_name(human_name) + , _order(order) + { + signal_event().connect(sigc::mem_fun(this, &CanvasPort::on_event)); + } + + CanvasPort(const CanvasPort&) = delete; + CanvasPort& operator=(const CanvasPort&) = delete; + + CanvasPort(CanvasPort&&) = delete; + CanvasPort& operator=(CanvasPort&&) = delete; + + ~CanvasPort() override = default; + + void show_human_name(bool human) + { + if (human && !_human_name.empty()) { + set_label(_human_name.c_str()); + } else { + set_label(_name.c_str()); + } + } + + bool on_event(GdkEvent* ev) override + { + if (ev->type != GDK_BUTTON_PRESS || ev->button.button != 3) { + return false; + } + + Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); + menu->items().push_back(Gtk::Menu_Helpers::MenuElem( + "Disconnect", sigc::mem_fun(this, &Port::disconnect))); + + menu->popup(ev->button.button, ev->button.time); + return true; + } + + PortType type() const { return _type; } + PortID id() const { return _id; } + const std::string& name() const { return _name; } + const std::string& human_name() const { return _human_name; } + const boost::optional& order() const { return _order; } private: - PortType _type; - PortID _id; - std::string _name; - std::string _human_name; - boost::optional _order; + PortType _type; + PortID _id; + std::string _name; + std::string _human_name; + boost::optional _order; }; } // namespace patchage diff --git a/src/ClientID.hpp b/src/ClientID.hpp index c0a2db8..911d2ec 100644 --- a/src/ClientID.hpp +++ b/src/ClientID.hpp @@ -28,99 +28,98 @@ namespace patchage { /// An ID for some client (program) that has ports -struct ClientID -{ - using Type = ClientType; +struct ClientID { + using Type = ClientType; - ClientID(const ClientID& copy) = default; - ClientID& operator=(const ClientID& copy) = default; + ClientID(const ClientID& copy) = default; + ClientID& operator=(const ClientID& copy) = default; - ClientID(ClientID&& id) = default; - ClientID& operator=(ClientID&& id) = default; + ClientID(ClientID&& id) = default; + ClientID& operator=(ClientID&& id) = default; - ~ClientID() = default; + ~ClientID() = default; - /// Return an ID for a JACK client by name - static ClientID jack(std::string name) - { - return ClientID{Type::jack, std::move(name)}; - } + /// Return an ID for a JACK client by name + static ClientID jack(std::string name) + { + return ClientID{Type::jack, std::move(name)}; + } - /// Return an ID for an ALSA Sequencer client by ID - static ClientID alsa(const uint8_t id) { return ClientID{Type::alsa, id}; } + /// Return an ID for an ALSA Sequencer client by ID + static ClientID alsa(const uint8_t id) { return ClientID{Type::alsa, id}; } - Type type() const { return _type; } - const std::string& jack_name() const { return _jack_name; } - uint8_t alsa_id() const { return _alsa_id; } + Type type() const { return _type; } + const std::string& jack_name() const { return _jack_name; } + uint8_t alsa_id() const { return _alsa_id; } private: - ClientID(const Type type, std::string jack_name) - : _type{type} - , _jack_name{std::move(jack_name)} - { - assert(_type == Type::jack); - } - - ClientID(const Type type, const uint8_t alsa_id) - : _type{type} - , _alsa_id{alsa_id} - { - assert(_type == Type::alsa); - } - - Type _type; ///< Determines which field is active - std::string _jack_name{}; ///< Client name for Type::jack - uint8_t _alsa_id{}; ///< Client ID for Type::alsa + ClientID(const Type type, std::string jack_name) + : _type{type} + , _jack_name{std::move(jack_name)} + { + assert(_type == Type::jack); + } + + ClientID(const Type type, const uint8_t alsa_id) + : _type{type} + , _alsa_id{alsa_id} + { + assert(_type == Type::alsa); + } + + Type _type; ///< Determines which field is active + std::string _jack_name{}; ///< Client name for Type::jack + uint8_t _alsa_id{}; ///< Client ID for Type::alsa }; static inline std::ostream& operator<<(std::ostream& os, const ClientID& id) { - switch (id.type()) { - case ClientID::Type::jack: - return os << "jack:" << id.jack_name(); - case ClientID::Type::alsa: - return os << "alsa:" << int(id.alsa_id()); - } - - assert(false); - return os; + switch (id.type()) { + case ClientID::Type::jack: + return os << "jack:" << id.jack_name(); + case ClientID::Type::alsa: + return os << "alsa:" << int(id.alsa_id()); + } + + assert(false); + return os; } static inline bool operator==(const ClientID& lhs, const ClientID& rhs) { - if (lhs.type() != rhs.type()) { - return false; - } - - switch (lhs.type()) { - case ClientID::Type::jack: - return lhs.jack_name() == rhs.jack_name(); - case ClientID::Type::alsa: - return lhs.alsa_id() == rhs.alsa_id(); - } - - assert(false); - return false; + if (lhs.type() != rhs.type()) { + return false; + } + + switch (lhs.type()) { + case ClientID::Type::jack: + return lhs.jack_name() == rhs.jack_name(); + case ClientID::Type::alsa: + return lhs.alsa_id() == rhs.alsa_id(); + } + + assert(false); + return false; } static inline bool operator<(const ClientID& lhs, const ClientID& rhs) { - if (lhs.type() != rhs.type()) { - return lhs.type() < rhs.type(); - } - - switch (lhs.type()) { - case ClientID::Type::jack: - return lhs.jack_name() < rhs.jack_name(); - case ClientID::Type::alsa: - return lhs.alsa_id() < rhs.alsa_id(); - } - - assert(false); - return false; + if (lhs.type() != rhs.type()) { + return lhs.type() < rhs.type(); + } + + switch (lhs.type()) { + case ClientID::Type::jack: + return lhs.jack_name() < rhs.jack_name(); + case ClientID::Type::alsa: + return lhs.alsa_id() < rhs.alsa_id(); + } + + assert(false); + return false; } } // namespace patchage diff --git a/src/ClientInfo.hpp b/src/ClientInfo.hpp index 19c3c85..8acddfe 100644 --- a/src/ClientInfo.hpp +++ b/src/ClientInfo.hpp @@ -22,9 +22,8 @@ namespace patchage { /// Extra information about a client (program) not expressed in its ID -struct ClientInfo -{ - std::string label; ///< Human-friendly label +struct ClientInfo { + std::string label; ///< Human-friendly label }; } // namespace patchage diff --git a/src/ClientType.hpp b/src/ClientType.hpp index 5f96875..4785501 100644 --- a/src/ClientType.hpp +++ b/src/ClientType.hpp @@ -20,10 +20,9 @@ namespace patchage { /// A type of client (program) with supported ports -enum class ClientType -{ - jack, - alsa, +enum class ClientType { + jack, + alsa, }; } // namespace patchage diff --git a/src/Configuration.cpp b/src/Configuration.cpp index c2172f9..d615fba 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -39,45 +39,43 @@ static const char* const port_type_names[N_PORT_TYPES] = {"JACK_AUDIO", Configuration::Configuration() { #ifdef PATCHAGE_USE_LIGHT_THEME - _port_colors[static_cast(PortType::jack_audio)] = - _default_port_colors[static_cast(PortType::jack_audio)] = - 0xA4BC8CFF; + _port_colors[static_cast(PortType::jack_audio)] = + _default_port_colors[static_cast(PortType::jack_audio)] = + 0xA4BC8CFF; - _port_colors[static_cast(PortType::jack_midi)] = - _default_port_colors[static_cast(PortType::jack_midi)] = - 0xC89595FF; + _port_colors[static_cast(PortType::jack_midi)] = + _default_port_colors[static_cast(PortType::jack_midi)] = + 0xC89595FF; - _port_colors[static_cast(PortType::alsa_midi)] = - _default_port_colors[static_cast(PortType::alsa_midi)] = - 0x8F7198FF; + _port_colors[static_cast(PortType::alsa_midi)] = + _default_port_colors[static_cast(PortType::alsa_midi)] = + 0x8F7198FF; - _port_colors[static_cast(PortType::jack_osc)] = - _default_port_colors[static_cast(PortType::jack_osc)] = - 0x7E8EAAFF; + _port_colors[static_cast(PortType::jack_osc)] = + _default_port_colors[static_cast(PortType::jack_osc)] = + 0x7E8EAAFF; - _port_colors[static_cast(PortType::jack_cv)] = - _default_port_colors[static_cast(PortType::jack_cv)] = - 0x83AFABFF; + _port_colors[static_cast(PortType::jack_cv)] = + _default_port_colors[static_cast(PortType::jack_cv)] = 0x83AFABFF; #else - _port_colors[static_cast(PortType::jack_audio)] = - _default_port_colors[static_cast(PortType::jack_audio)] = - 0x3E5E00FF; + _port_colors[static_cast(PortType::jack_audio)] = + _default_port_colors[static_cast(PortType::jack_audio)] = + 0x3E5E00FF; - _port_colors[static_cast(PortType::jack_midi)] = - _default_port_colors[static_cast(PortType::jack_midi)] = - 0x650300FF; + _port_colors[static_cast(PortType::jack_midi)] = + _default_port_colors[static_cast(PortType::jack_midi)] = + 0x650300FF; - _port_colors[static_cast(PortType::alsa_midi)] = - _default_port_colors[static_cast(PortType::alsa_midi)] = - 0x2D0043FF; + _port_colors[static_cast(PortType::alsa_midi)] = + _default_port_colors[static_cast(PortType::alsa_midi)] = + 0x2D0043FF; - _port_colors[static_cast(PortType::jack_osc)] = - _default_port_colors[static_cast(PortType::jack_osc)] = - 0x4100FEFF; + _port_colors[static_cast(PortType::jack_osc)] = + _default_port_colors[static_cast(PortType::jack_osc)] = + 0x4100FEFF; - _port_colors[static_cast(PortType::jack_cv)] = - _default_port_colors[static_cast(PortType::jack_cv)] = - 0x005E4EFF; + _port_colors[static_cast(PortType::jack_cv)] = + _default_port_colors[static_cast(PortType::jack_cv)] = 0x005E4EFF; #endif } @@ -86,23 +84,23 @@ Configuration::get_module_location(const std::string& name, SignalDirection type, Coord& loc) const { - auto i = _module_settings.find(name); - if (i == _module_settings.end()) { - return false; - } - - const ModuleSettings& settings = (*i).second; - if (type == SignalDirection::input && settings.input_location) { - loc = *settings.input_location; - } else if (type == SignalDirection::output && settings.output_location) { - loc = *settings.output_location; - } else if (type == SignalDirection::duplex && settings.inout_location) { - loc = *settings.inout_location; - } else { - return false; - } - - return true; + auto i = _module_settings.find(name); + if (i == _module_settings.end()) { + return false; + } + + const ModuleSettings& settings = (*i).second; + if (type == SignalDirection::input && settings.input_location) { + loc = *settings.input_location; + } else if (type == SignalDirection::output && settings.output_location) { + loc = *settings.output_location; + } else if (type == SignalDirection::duplex && settings.inout_location) { + loc = *settings.inout_location; + } else { + return false; + } + + return true; } void @@ -110,26 +108,26 @@ Configuration::set_module_location(const std::string& name, SignalDirection type, Coord loc) { - auto i = _module_settings.find(name); - if (i == _module_settings.end()) { - i = _module_settings - .insert(std::make_pair( - name, ModuleSettings(type != SignalDirection::duplex))) - .first; - } - - ModuleSettings& settings = (*i).second; - switch (type) { - case SignalDirection::input: - settings.input_location = loc; - break; - case SignalDirection::output: - settings.output_location = loc; - break; - case SignalDirection::duplex: - settings.inout_location = loc; - break; - } + auto i = _module_settings.find(name); + if (i == _module_settings.end()) { + i = _module_settings + .insert(std::make_pair( + name, ModuleSettings(type != SignalDirection::duplex))) + .first; + } + + ModuleSettings& settings = (*i).second; + switch (type) { + case SignalDirection::input: + settings.input_location = loc; + break; + case SignalDirection::output: + settings.output_location = loc; + break; + case SignalDirection::duplex: + settings.inout_location = loc; + break; + } } /** Returns whether or not this module should be split. @@ -140,156 +138,156 @@ Configuration::set_module_location(const std::string& name, bool Configuration::get_module_split(const std::string& name, bool default_val) const { - auto i = _module_settings.find(name); - if (i == _module_settings.end()) { - return default_val; - } + auto i = _module_settings.find(name); + if (i == _module_settings.end()) { + return default_val; + } - return (*i).second.split; + return (*i).second.split; } void Configuration::set_module_split(const std::string& name, bool split) { - _module_settings[name].split = split; + _module_settings[name].split = split; } /** Return a vector of filenames in descending order by preference. */ static std::vector get_filenames() { - std::vector filenames; - std::string prefix; + std::vector filenames; + std::string prefix; - const char* xdg_config_home = getenv("XDG_CONFIG_HOME"); - const char* home = getenv("HOME"); + const char* xdg_config_home = getenv("XDG_CONFIG_HOME"); + const char* home = getenv("HOME"); - // XDG spec - if (xdg_config_home) { - filenames.push_back(std::string(xdg_config_home) + "/patchagerc"); - } else if (home) { - filenames.push_back(std::string(home) + "/.config/patchagerc"); - } + // XDG spec + if (xdg_config_home) { + filenames.push_back(std::string(xdg_config_home) + "/patchagerc"); + } else if (home) { + filenames.push_back(std::string(home) + "/.config/patchagerc"); + } - // Old location - if (home) { - filenames.push_back(std::string(home) + "/.patchagerc"); - } + // Old location + if (home) { + filenames.push_back(std::string(home) + "/.patchagerc"); + } - // Current directory (bundle or last-ditch effort) - filenames.emplace_back("patchagerc"); + // Current directory (bundle or last-ditch effort) + filenames.emplace_back("patchagerc"); - return filenames; + return filenames; } void Configuration::load() { - // Try to find a readable configuration file - const std::vector filenames = get_filenames(); - std::ifstream file; - for (const auto& filename : filenames) { - file.open(filename.c_str(), std::ios::in); - if (file.good()) { - std::cout << "Loading configuration from " << filename << std::endl; - break; - } - } - - if (!file.good()) { - std::cout << "No configuration file present" << std::endl; - return; - } - - _module_settings.clear(); - while (file.good()) { - std::string key; - if (file.peek() == '\"') { - /* Old versions omitted the module_position key and listed - positions starting with module name in quotes. */ - key = "module_position"; - } else { - file >> key; - } - - if (key == "window_location") { - file >> _window_location.x >> _window_location.y; - } else if (key == "window_size") { - file >> _window_size.x >> _window_size.y; - } else if (key == "zoom_level") { - file >> _zoom; - } else if (key == "font_size") { - file >> _font_size; - } else if (key == "show_toolbar") { - file >> _show_toolbar; - } else if (key == "sprung_layout") { - file >> _sprung_layout; - } else if (key == "show_messages") { - file >> _show_messages; - } else if (key == "sort_ports") { - file >> _sort_ports; - } else if (key == "messages_height") { - file >> _messages_height; - } else if (key == "port_color") { - std::string type_name; - uint32_t rgba = 0u; - file >> type_name; - file.ignore(1, '#'); - file >> std::hex >> std::uppercase; - file >> rgba; - file >> std::dec >> std::nouppercase; - - bool found = false; - for (int i = 0; i < N_PORT_TYPES; ++i) { - if (type_name == port_type_names[i]) { - _port_colors[i] = rgba; - found = true; - break; - } - } - if (!found) { - std::cerr << "error: color for unknown port type `" << type_name - << "'" << std::endl; - } - } else if (key == "module_position" || key[0] == '\"') { - Coord loc; - std::string name; - file.ignore(1, '\"'); - std::getline(file, name, '\"'); - - SignalDirection type = SignalDirection::input; - std::string type_str; - file >> type_str; - if (type_str == "input") { - type = SignalDirection::input; - } else if (type_str == "output") { - type = SignalDirection::output; - } else if (type_str == "inputoutput") { - type = SignalDirection::duplex; - } else { - std::cerr << "error: bad position type `" << type_str - << "' for module `" << name << "'" << std::endl; - file.ignore(std::numeric_limits::max(), '\n'); - continue; - } - - file >> loc.x; - file >> loc.y; - - set_module_location(name, type, loc); - } else { - std::cerr << "warning: unknown configuration key `" << key << "'" - << std::endl; - file.ignore(std::numeric_limits::max(), '\n'); - } - - // Skip trailing whitespace, including newline - while (file.good() && isspace(file.peek())) { - file.ignore(1); - } - } - - file.close(); + // Try to find a readable configuration file + const std::vector filenames = get_filenames(); + std::ifstream file; + for (const auto& filename : filenames) { + file.open(filename.c_str(), std::ios::in); + if (file.good()) { + std::cout << "Loading configuration from " << filename << std::endl; + break; + } + } + + if (!file.good()) { + std::cout << "No configuration file present" << std::endl; + return; + } + + _module_settings.clear(); + while (file.good()) { + std::string key; + if (file.peek() == '\"') { + /* Old versions omitted the module_position key and listed + positions starting with module name in quotes. */ + key = "module_position"; + } else { + file >> key; + } + + if (key == "window_location") { + file >> _window_location.x >> _window_location.y; + } else if (key == "window_size") { + file >> _window_size.x >> _window_size.y; + } else if (key == "zoom_level") { + file >> _zoom; + } else if (key == "font_size") { + file >> _font_size; + } else if (key == "show_toolbar") { + file >> _show_toolbar; + } else if (key == "sprung_layout") { + file >> _sprung_layout; + } else if (key == "show_messages") { + file >> _show_messages; + } else if (key == "sort_ports") { + file >> _sort_ports; + } else if (key == "messages_height") { + file >> _messages_height; + } else if (key == "port_color") { + std::string type_name; + uint32_t rgba = 0u; + file >> type_name; + file.ignore(1, '#'); + file >> std::hex >> std::uppercase; + file >> rgba; + file >> std::dec >> std::nouppercase; + + bool found = false; + for (int i = 0; i < N_PORT_TYPES; ++i) { + if (type_name == port_type_names[i]) { + _port_colors[i] = rgba; + found = true; + break; + } + } + if (!found) { + std::cerr << "error: color for unknown port type `" << type_name << "'" + << std::endl; + } + } else if (key == "module_position" || key[0] == '\"') { + Coord loc; + std::string name; + file.ignore(1, '\"'); + std::getline(file, name, '\"'); + + SignalDirection type = SignalDirection::input; + std::string type_str; + file >> type_str; + if (type_str == "input") { + type = SignalDirection::input; + } else if (type_str == "output") { + type = SignalDirection::output; + } else if (type_str == "inputoutput") { + type = SignalDirection::duplex; + } else { + std::cerr << "error: bad position type `" << type_str + << "' for module `" << name << "'" << std::endl; + file.ignore(std::numeric_limits::max(), '\n'); + continue; + } + + file >> loc.x; + file >> loc.y; + + set_module_location(name, type, loc); + } else { + std::cerr << "warning: unknown configuration key `" << key << "'" + << std::endl; + file.ignore(std::numeric_limits::max(), '\n'); + } + + // Skip trailing whitespace, including newline + while (file.good() && isspace(file.peek())) { + file.ignore(1); + } + } + + file.close(); } static inline void @@ -298,71 +296,69 @@ write_module_position(std::ofstream& os, const char* type, const Coord& loc) { - os << "module_position \"" << name << "\"" - << " " << type << " " << loc.x << " " << loc.y << std::endl; + os << "module_position \"" << name << "\"" + << " " << type << " " << loc.x << " " << loc.y << std::endl; } void Configuration::save() { - // Try to find a writable configuration file - const std::vector filenames = get_filenames(); - std::ofstream file; - for (const std::string& filename : filenames) { - file.open(filename.c_str(), std::ios::out); - if (file.good()) { - std::cout << "Writing configuration to " << filename << std::endl; - break; - } - } - - if (!file.good()) { - std::cout << "Unable to open configuration file to write" << std::endl; - return; - } - - file << "window_location " << _window_location.x << " " - << _window_location.y << std::endl; - file << "window_size " << _window_size.x << " " << _window_size.y - << std::endl; - file << "zoom_level " << _zoom << std::endl; - file << "font_size " << _font_size << std::endl; - file << "show_toolbar " << _show_toolbar << std::endl; - file << "sprung_layout " << _sprung_layout << std::endl; - file << "show_messages " << _show_messages << std::endl; - file << "sort_ports " << _sort_ports << std::endl; - file << "messages_height " << _messages_height << std::endl; - - file << std::hex << std::uppercase; - for (int i = 0; i < N_PORT_TYPES; ++i) { - if (_port_colors[i] != _default_port_colors[i]) { - file << "port_color " << port_type_names[i] << " " - << _port_colors[i] << std::endl; - } - } - file << std::dec << std::nouppercase; - - for (const auto& s : _module_settings) { - const std::string& name = s.first; - const ModuleSettings& settings = s.second; - - if (settings.split) { - if (settings.input_location) { - write_module_position( - file, name, "input", *settings.input_location); - } - - if (settings.output_location) { - write_module_position( - file, name, "output", *settings.output_location); - } - } else if (settings.inout_location) { - write_module_position( - file, name, "inputoutput", *settings.inout_location); - } - } - - file.close(); + // Try to find a writable configuration file + const std::vector filenames = get_filenames(); + std::ofstream file; + for (const std::string& filename : filenames) { + file.open(filename.c_str(), std::ios::out); + if (file.good()) { + std::cout << "Writing configuration to " << filename << std::endl; + break; + } + } + + if (!file.good()) { + std::cout << "Unable to open configuration file to write" << std::endl; + return; + } + + file << "window_location " << _window_location.x << " " << _window_location.y + << std::endl; + file << "window_size " << _window_size.x << " " << _window_size.y + << std::endl; + file << "zoom_level " << _zoom << std::endl; + file << "font_size " << _font_size << std::endl; + file << "show_toolbar " << _show_toolbar << std::endl; + file << "sprung_layout " << _sprung_layout << std::endl; + file << "show_messages " << _show_messages << std::endl; + file << "sort_ports " << _sort_ports << std::endl; + file << "messages_height " << _messages_height << std::endl; + + file << std::hex << std::uppercase; + for (int i = 0; i < N_PORT_TYPES; ++i) { + if (_port_colors[i] != _default_port_colors[i]) { + file << "port_color " << port_type_names[i] << " " << _port_colors[i] + << std::endl; + } + } + file << std::dec << std::nouppercase; + + for (const auto& s : _module_settings) { + const std::string& name = s.first; + const ModuleSettings& settings = s.second; + + if (settings.split) { + if (settings.input_location) { + write_module_position(file, name, "input", *settings.input_location); + } + + if (settings.output_location) { + write_module_position(file, name, "output", *settings.output_location); + } + } else if (settings.inout_location) { + write_module_position( + file, name, "inputoutput", *settings.inout_location); + } + } + + file.close(); } } // namespace patchage diff --git a/src/Configuration.hpp b/src/Configuration.hpp index 7e406ef..45842a4 100644 --- a/src/Configuration.hpp +++ b/src/Configuration.hpp @@ -30,107 +30,102 @@ namespace patchage { -struct Coord -{ - Coord() = default; +struct Coord { + Coord() = default; - Coord(double x_, double y_) - : x(x_) - , y(y_) - {} + Coord(double x_, double y_) + : x(x_) + , y(y_) + {} - double x{0.0}; - double y{0.0}; + double x{0.0}; + double y{0.0}; }; class Configuration { public: - Configuration(); + Configuration(); - void load(); - void save(); + void load(); + void save(); - bool get_module_location(const std::string& name, - SignalDirection type, - Coord& loc) const; + bool get_module_location(const std::string& name, + SignalDirection type, + Coord& loc) const; - void set_module_location(const std::string& name, - SignalDirection type, - Coord loc); + void set_module_location(const std::string& name, + SignalDirection type, + Coord loc); - void set_module_split(const std::string& name, bool split); - bool get_module_split(const std::string& name, bool default_val) const; + void set_module_split(const std::string& name, bool split); + bool get_module_split(const std::string& name, bool default_val) const; - float get_zoom() const { return _zoom; } - void set_zoom(float zoom) { _zoom = zoom; } - float get_font_size() const { return _font_size; } - void set_font_size(float font_size) { _font_size = font_size; } + float get_zoom() const { return _zoom; } + void set_zoom(float zoom) { _zoom = zoom; } + float get_font_size() const { return _font_size; } + void set_font_size(float font_size) { _font_size = font_size; } - float get_show_toolbar() const { return _show_toolbar; } - void set_show_toolbar(float show_toolbar) { _show_toolbar = show_toolbar; } + float get_show_toolbar() const { return _show_toolbar; } + void set_show_toolbar(float show_toolbar) { _show_toolbar = show_toolbar; } - float get_sprung_layout() const { return _sprung_layout; } - void set_sprung_layout(float sprung_layout) - { - _sprung_layout = sprung_layout; - } + float get_sprung_layout() const { return _sprung_layout; } + void set_sprung_layout(float sprung_layout) + { + _sprung_layout = sprung_layout; + } - bool get_show_messages() const { return _show_messages; } - void set_show_messages(bool show_messages) - { - _show_messages = show_messages; - } + bool get_show_messages() const { return _show_messages; } + void set_show_messages(bool show_messages) { _show_messages = show_messages; } - bool get_sort_ports() const { return _sort_ports; } - void set_sort_ports(bool sort_ports) { _sort_ports = sort_ports; } + bool get_sort_ports() const { return _sort_ports; } + void set_sort_ports(bool sort_ports) { _sort_ports = sort_ports; } - int get_messages_height() const { return _messages_height; } - void set_messages_height(int height) { _messages_height = height; } + int get_messages_height() const { return _messages_height; } + void set_messages_height(int height) { _messages_height = height; } - uint32_t get_port_color(PortType type) const - { - return _port_colors[static_cast(type)]; - } + uint32_t get_port_color(PortType type) const + { + return _port_colors[static_cast(type)]; + } - void set_port_color(PortType type, uint32_t rgba) - { - _port_colors[static_cast(type)] = rgba; - } + void set_port_color(PortType type, uint32_t rgba) + { + _port_colors[static_cast(type)] = rgba; + } - Coord get_window_location() { return _window_location; } - void set_window_location(Coord loc) { _window_location = loc; } - Coord get_window_size() { return _window_size; } - void set_window_size(Coord size) { _window_size = size; } + Coord get_window_location() { return _window_location; } + void set_window_location(Coord loc) { _window_location = loc; } + Coord get_window_size() { return _window_size; } + void set_window_size(Coord size) { _window_size = size; } private: - struct ModuleSettings - { - explicit ModuleSettings(bool s = false) - : split(s) - {} - - boost::optional input_location; - boost::optional output_location; - boost::optional inout_location; - bool split; - }; - - std::map _module_settings; - - uint32_t _default_port_colors[N_PORT_TYPES] = {}; - uint32_t _port_colors[N_PORT_TYPES] = {}; - - Coord _window_location{0.0, 0.0}; - Coord _window_size{960.0, 540.0}; - - float _zoom = 1.0f; - float _font_size = 12.0f; - int _messages_height = 0; - bool _show_toolbar = true; - bool _sprung_layout = false; - bool _show_messages = false; - bool _sort_ports = true; + struct ModuleSettings { + explicit ModuleSettings(bool s = false) + : split(s) + {} + + boost::optional input_location; + boost::optional output_location; + boost::optional inout_location; + bool split; + }; + + std::map _module_settings; + + uint32_t _default_port_colors[N_PORT_TYPES] = {}; + uint32_t _port_colors[N_PORT_TYPES] = {}; + + Coord _window_location{0.0, 0.0}; + Coord _window_size{960.0, 540.0}; + + float _zoom = 1.0f; + float _font_size = 12.0f; + int _messages_height = 0; + bool _show_toolbar = true; + bool _sprung_layout = false; + bool _show_messages = false; + bool _sort_ports = true; }; } // namespace patchage diff --git a/src/Connector.cpp b/src/Connector.cpp index 8226f91..fe008ce 100644 --- a/src/Connector.cpp +++ b/src/Connector.cpp @@ -26,47 +26,47 @@ namespace patchage { Connector::Connector(ILog& log) - : _log(log) + : _log(log) {} void Connector::add_driver(PortID::Type type, Driver* driver) { - _drivers.emplace(type, driver); + _drivers.emplace(type, driver); } void Connector::connect(const PortID& tail, const PortID& head) { - if (tail.type() != head.type()) { - _log.warning("Unable to connect incompatible port types"); - return; - } + if (tail.type() != head.type()) { + _log.warning("Unable to connect incompatible port types"); + return; + } - auto d = _drivers.find(tail.type()); - if (d == _drivers.end()) { - _log.error("No driver for port type"); - return; - } + auto d = _drivers.find(tail.type()); + if (d == _drivers.end()) { + _log.error("No driver for port type"); + return; + } - d->second->connect(tail, head); + d->second->connect(tail, head); } void Connector::disconnect(const PortID& tail, const PortID& head) { - if (tail.type() != head.type()) { - _log.error("Unable to disconnect incompatible port types"); - return; - } + if (tail.type() != head.type()) { + _log.error("Unable to disconnect incompatible port types"); + return; + } - auto d = _drivers.find(tail.type()); - if (d == _drivers.end()) { - _log.error("No driver for port type"); - return; - } + auto d = _drivers.find(tail.type()); + if (d == _drivers.end()) { + _log.error("No driver for port type"); + return; + } - d->second->disconnect(tail, head); + d->second->disconnect(tail, head); } } // namespace patchage diff --git a/src/Connector.hpp b/src/Connector.hpp index e10e540..f3e3816 100644 --- a/src/Connector.hpp +++ b/src/Connector.hpp @@ -30,16 +30,16 @@ class ILog; class Connector { public: - explicit Connector(ILog& log); + explicit Connector(ILog& log); - void add_driver(PortID::Type type, Driver* driver); + void add_driver(PortID::Type type, Driver* driver); - void connect(const PortID& tail, const PortID& head); - void disconnect(const PortID& tail, const PortID& head); + void connect(const PortID& tail, const PortID& head); + void disconnect(const PortID& tail, const PortID& head); private: - ILog& _log; - std::unordered_map _drivers; + ILog& _log; + std::unordered_map _drivers; }; } // namespace patchage diff --git a/src/Driver.hpp b/src/Driver.hpp index 1c62697..da11765 100644 --- a/src/Driver.hpp +++ b/src/Driver.hpp @@ -30,40 +30,40 @@ struct PortID; class Driver { public: - using EventSink = std::function; + using EventSink = std::function; - explicit Driver(EventSink emit_event) - : _emit_event{std::move(emit_event)} - {} + explicit Driver(EventSink emit_event) + : _emit_event{std::move(emit_event)} + {} - Driver(const Driver&) = delete; - Driver& operator=(const Driver&) = delete; + Driver(const Driver&) = delete; + Driver& operator=(const Driver&) = delete; - Driver(Driver&&) = delete; - Driver& operator=(Driver&&) = delete; + Driver(Driver&&) = delete; + Driver& operator=(Driver&&) = delete; - virtual ~Driver() = default; + virtual ~Driver() = default; - /// Connect to the underlying system API - virtual void attach(bool launch_daemon) = 0; + /// Connect to the underlying system API + virtual void attach(bool launch_daemon) = 0; - /// Disconnect from the underlying system API - virtual void detach() = 0; + /// Disconnect from the underlying system API + virtual void detach() = 0; - /// Return true iff the driver is active and connected to the system - virtual bool is_attached() const = 0; + /// Return true iff the driver is active and connected to the system + virtual bool is_attached() const = 0; - /// Send events to `sink` that describe the complete current system state - virtual void refresh(const EventSink& sink) = 0; + /// Send events to `sink` that describe the complete current system state + virtual void refresh(const EventSink& sink) = 0; - /// Make a connection between ports - virtual bool connect(const PortID& tail_id, const PortID& head_id) = 0; + /// Make a connection between ports + virtual bool connect(const PortID& tail_id, const PortID& head_id) = 0; - /// Remove a connection between ports - virtual bool disconnect(const PortID& tail_id, const PortID& head_id) = 0; + /// Remove a connection between ports + virtual bool disconnect(const PortID& tail_id, const PortID& head_id) = 0; protected: - EventSink _emit_event; ///< Sink for emitting "live" events + EventSink _emit_event; ///< Sink for emitting "live" events }; } // namespace patchage diff --git a/src/Event.hpp b/src/Event.hpp index e664399..3cb5bba 100644 --- a/src/Event.hpp +++ b/src/Event.hpp @@ -27,48 +27,40 @@ namespace patchage { -struct DriverAttachmentEvent -{ - ClientType type; +struct DriverAttachmentEvent { + ClientType type; }; -struct DriverDetachmentEvent -{ - ClientType type; +struct DriverDetachmentEvent { + ClientType type; }; -struct ClientCreationEvent -{ - ClientID id; - ClientInfo info; +struct ClientCreationEvent { + ClientID id; + ClientInfo info; }; -struct ClientDestructionEvent -{ - ClientID id; +struct ClientDestructionEvent { + ClientID id; }; -struct PortCreationEvent -{ - PortID id; - PortInfo info; +struct PortCreationEvent { + PortID id; + PortInfo info; }; -struct PortDestructionEvent -{ - PortID id; +struct PortDestructionEvent { + PortID id; }; -struct ConnectionEvent -{ - PortID tail; - PortID head; +struct ConnectionEvent { + PortID tail; + PortID head; }; -struct DisconnectionEvent -{ - PortID tail; - PortID head; +struct DisconnectionEvent { + PortID tail; + PortID head; }; /// An event from drivers that is processed by the GUI diff --git a/src/ILog.hpp b/src/ILog.hpp index 33b2644..d71059a 100644 --- a/src/ILog.hpp +++ b/src/ILog.hpp @@ -25,19 +25,19 @@ namespace patchage { class ILog { public: - ILog() = default; + ILog() = default; - ILog(const ILog&) = default; - ILog& operator=(const ILog&) = default; + ILog(const ILog&) = default; + ILog& operator=(const ILog&) = default; - ILog(ILog&&) = default; - ILog& operator=(ILog&&) = default; + ILog(ILog&&) = default; + ILog& operator=(ILog&&) = default; - virtual ~ILog() = default; + virtual ~ILog() = default; - virtual void info(const std::string& msg) = 0; - virtual void warning(const std::string& msg) = 0; - virtual void error(const std::string& msg) = 0; + virtual void info(const std::string& msg) = 0; + virtual void warning(const std::string& msg) = 0; + virtual void error(const std::string& msg) = 0; }; } // namespace patchage diff --git a/src/JackDbusDriver.cpp b/src/JackDbusDriver.cpp index 1e276ef..23c12f2 100644 --- a/src/JackDbusDriver.cpp +++ b/src/JackDbusDriver.cpp @@ -41,18 +41,18 @@ PATCHAGE_RESTORE_WARNINGS #include #include -#define JACKDBUS_SERVICE "org.jackaudio.service" -#define JACKDBUS_OBJECT "/org/jackaudio/Controller" -#define JACKDBUS_IFACE_CONTROL "org.jackaudio.JackControl" +#define JACKDBUS_SERVICE "org.jackaudio.service" +#define JACKDBUS_OBJECT "/org/jackaudio/Controller" +#define JACKDBUS_IFACE_CONTROL "org.jackaudio.JackControl" #define JACKDBUS_IFACE_PATCHBAY "org.jackaudio.JackPatchbay" #define JACKDBUS_CALL_DEFAULT_TIMEOUT 1000 // in milliseconds -#define JACKDBUS_PORT_FLAG_INPUT 0x00000001 +#define JACKDBUS_PORT_FLAG_INPUT 0x00000001 #define JACKDBUS_PORT_FLAG_TERMINAL 0x00000010 #define JACKDBUS_PORT_TYPE_AUDIO 0 -#define JACKDBUS_PORT_TYPE_MIDI 1 +#define JACKDBUS_PORT_TYPE_MIDI 1 namespace patchage { namespace { @@ -61,143 +61,143 @@ namespace { class JackDriver : public AudioDriver { public: - explicit JackDriver(ILog& log, EventSink emit_event); + explicit JackDriver(ILog& log, EventSink emit_event); - JackDriver(const JackDriver&) = delete; - JackDriver& operator=(const JackDriver&) = delete; + JackDriver(const JackDriver&) = delete; + JackDriver& operator=(const JackDriver&) = delete; - JackDriver(JackDriver&&) = delete; - JackDriver& operator=(JackDriver&&) = delete; + JackDriver(JackDriver&&) = delete; + JackDriver& operator=(JackDriver&&) = delete; - ~JackDriver() override; + ~JackDriver() override; - // Driver interface - void attach(bool launch_daemon) override; - void detach() override; - bool is_attached() const override; - void refresh(const EventSink& sink) override; - bool connect(const PortID& tail_id, const PortID& head_id) override; - bool disconnect(const PortID& tail_id, const PortID& head_id) override; + // Driver interface + void attach(bool launch_daemon) override; + void detach() override; + bool is_attached() const override; + void refresh(const EventSink& sink) override; + bool connect(const PortID& tail_id, const PortID& head_id) override; + bool disconnect(const PortID& tail_id, const PortID& head_id) override; - // AudioDriver interface - uint32_t xruns() override; - void reset_xruns() override; - uint32_t buffer_size() override; - bool set_buffer_size(uint32_t frames) override; - uint32_t sample_rate() override; + // AudioDriver interface + uint32_t xruns() override; + void reset_xruns() override; + uint32_t buffer_size() override; + bool set_buffer_size(uint32_t frames) override; + uint32_t sample_rate() override; private: - PortType patchage_port_type(dbus_uint32_t dbus_port_type) const; + PortType patchage_port_type(dbus_uint32_t dbus_port_type) const; - PortInfo port_info(const std::string& port_name, - dbus_uint32_t port_type, - dbus_uint32_t port_flags) const; + PortInfo port_info(const std::string& port_name, + dbus_uint32_t port_type, + dbus_uint32_t port_flags) const; - void error_msg(const std::string& msg) const; - void info_msg(const std::string& msg) const; + void error_msg(const std::string& msg) const; + void info_msg(const std::string& msg) const; - bool call(bool response_expected, - const char* iface, - const char* method, - DBusMessage** reply_ptr_ptr, - int in_type, - ...); + bool call(bool response_expected, + const char* iface, + const char* method, + DBusMessage** reply_ptr_ptr, + int in_type, + ...); - void update_attached(); + void update_attached(); - bool is_started(); + bool is_started(); - void start_server(); + void start_server(); - void stop_server(); + void stop_server(); - static DBusHandlerResult dbus_message_hook(DBusConnection* connection, - DBusMessage* message, - void* jack_driver); + static DBusHandlerResult dbus_message_hook(DBusConnection* connection, + DBusMessage* message, + void* jack_driver); - void on_jack_appeared(); + void on_jack_appeared(); - void on_jack_disappeared(); + void on_jack_disappeared(); - ILog& _log; - DBusError _dbus_error; - DBusConnection* _dbus_connection; + ILog& _log; + DBusError _dbus_error; + DBusConnection* _dbus_connection; - mutable bool _server_responding; - bool _server_started; + mutable bool _server_responding; + bool _server_started; - dbus_uint64_t _graph_version; + dbus_uint64_t _graph_version; }; JackDriver::JackDriver(ILog& log, EventSink emit_event) - : AudioDriver{std::move(emit_event)} - , _log(log) - , _dbus_error() - , _dbus_connection(nullptr) - , _server_responding(false) - , _server_started(false) - , _graph_version(0) + : AudioDriver{std::move(emit_event)} + , _log(log) + , _dbus_error() + , _dbus_connection(nullptr) + , _server_responding(false) + , _server_started(false) + , _graph_version(0) { - dbus_error_init(&_dbus_error); + dbus_error_init(&_dbus_error); } JackDriver::~JackDriver() { - if (_dbus_connection) { - dbus_connection_flush(_dbus_connection); - } + if (_dbus_connection) { + dbus_connection_flush(_dbus_connection); + } - if (dbus_error_is_set(&_dbus_error)) { - dbus_error_free(&_dbus_error); - } + if (dbus_error_is_set(&_dbus_error)) { + dbus_error_free(&_dbus_error); + } } void JackDriver::update_attached() { - bool was_attached = _server_started; - _server_started = is_started(); - - if (!_server_responding) { - if (was_attached) { - _emit_event(DriverDetachmentEvent{ClientType::jack}); - } - return; - } - - if (_server_started && !was_attached) { - _emit_event(DriverAttachmentEvent{ClientType::jack}); - return; - } - - if (!_server_started && was_attached) { - _emit_event(DriverDetachmentEvent{ClientType::jack}); - return; - } + bool was_attached = _server_started; + _server_started = is_started(); + + if (!_server_responding) { + if (was_attached) { + _emit_event(DriverDetachmentEvent{ClientType::jack}); + } + return; + } + + if (_server_started && !was_attached) { + _emit_event(DriverAttachmentEvent{ClientType::jack}); + return; + } + + if (!_server_started && was_attached) { + _emit_event(DriverDetachmentEvent{ClientType::jack}); + return; + } } void JackDriver::on_jack_appeared() { - info_msg("Server appeared"); - update_attached(); + info_msg("Server appeared"); + update_attached(); } void JackDriver::on_jack_disappeared() { - info_msg("Server disappeared"); + info_msg("Server disappeared"); - // we are not calling update_attached() here, because it will activate - // jackdbus + // we are not calling update_attached() here, because it will activate + // jackdbus - _server_responding = false; + _server_responding = false; - if (_server_started) { - _emit_event(DriverDetachmentEvent{ClientType::jack}); - } + if (_server_started) { + _emit_event(DriverDetachmentEvent{ClientType::jack}); + } - _server_started = false; + _server_started = false; } DBusHandlerResult @@ -205,217 +205,209 @@ JackDriver::dbus_message_hook(DBusConnection* /*connection*/, DBusMessage* message, void* jack_driver) { - const char* client2_name = nullptr; - const char* client_name = nullptr; - const char* new_owner = nullptr; - const char* object_name = nullptr; - const char* old_owner = nullptr; - const char* port2_name = nullptr; - const char* port_name = nullptr; - dbus_uint32_t port_flags = 0u; - dbus_uint32_t port_type = 0u; - dbus_uint64_t client2_id = 0u; - dbus_uint64_t client_id = 0u; - dbus_uint64_t connection_id = 0u; - dbus_uint64_t new_graph_version = 0u; - dbus_uint64_t port2_id = 0u; - dbus_uint64_t port_id = 0u; - - assert(jack_driver); - auto* me = static_cast(jack_driver); - assert(me->_dbus_connection); - - if (dbus_message_is_signal( - message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { - if (!dbus_message_get_args(message, - &me->_dbus_error, - DBUS_TYPE_STRING, - &object_name, - DBUS_TYPE_STRING, - &old_owner, - DBUS_TYPE_STRING, - &new_owner, - DBUS_TYPE_INVALID)) { - me->error_msg( - fmt::format("dbus_message_get_args() failed to extract " - "NameOwnerChanged signal arguments ({})", - me->_dbus_error.message)); - - dbus_error_free(&me->_dbus_error); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (old_owner[0] == '\0') { - me->on_jack_appeared(); - } else if (new_owner[0] == '\0') { - me->on_jack_disappeared(); - } - } - - if (dbus_message_is_signal( - message, JACKDBUS_IFACE_PATCHBAY, "PortAppeared")) { - if (!dbus_message_get_args(message, - &me->_dbus_error, - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_UINT32, - &port_flags, - DBUS_TYPE_UINT32, - &port_type, - DBUS_TYPE_INVALID)) { - me->error_msg( - fmt::format("dbus_message_get_args() failed to extract " - "PortAppeared signal arguments ({})", - me->_dbus_error.message)); - dbus_error_free(&me->_dbus_error); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (!me->_server_started) { - me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); - } - - me->_emit_event( - PortCreationEvent{PortID::jack(client_name, port_name), - me->port_info(port_name, port_type, port_flags)}); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (dbus_message_is_signal( - message, JACKDBUS_IFACE_PATCHBAY, "PortDisappeared")) { - if (!dbus_message_get_args(message, - &me->_dbus_error, - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_INVALID)) { - me->error_msg( - fmt::format("dbus_message_get_args() failed to extract " - "PortDisappeared signal arguments ({})", - me->_dbus_error.message)); - dbus_error_free(&me->_dbus_error); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (!me->_server_started) { - me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); - } - - me->_emit_event( - PortDestructionEvent{PortID::jack(client_name, port_name)}); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (dbus_message_is_signal( - message, JACKDBUS_IFACE_PATCHBAY, "PortsConnected")) { - if (!dbus_message_get_args(message, - &me->_dbus_error, - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID)) { - me->error_msg( - fmt::format("dbus_message_get_args() failed to extract " - "PortsConnected signal arguments ({})", - me->_dbus_error.message)); - dbus_error_free(&me->_dbus_error); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (!me->_server_started) { - me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); - } - - me->_emit_event( - ConnectionEvent{PortID::jack(client_name, port_name), - PortID::jack(client2_name, port2_name)}); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (dbus_message_is_signal( - message, JACKDBUS_IFACE_PATCHBAY, "PortsDisconnected")) { - if (!dbus_message_get_args(message, - &me->_dbus_error, - DBUS_TYPE_UINT64, - &new_graph_version, - DBUS_TYPE_UINT64, - &client_id, - DBUS_TYPE_STRING, - &client_name, - DBUS_TYPE_UINT64, - &port_id, - DBUS_TYPE_STRING, - &port_name, - DBUS_TYPE_UINT64, - &client2_id, - DBUS_TYPE_STRING, - &client2_name, - DBUS_TYPE_UINT64, - &port2_id, - DBUS_TYPE_STRING, - &port2_name, - DBUS_TYPE_UINT64, - &connection_id, - DBUS_TYPE_INVALID)) { - me->error_msg( - fmt::format("dbus_message_get_args() failed to extract " - "PortsDisconnected signal arguments ({})", - me->_dbus_error.message)); - dbus_error_free(&me->_dbus_error); - return DBUS_HANDLER_RESULT_HANDLED; - } - - if (!me->_server_started) { - me->_server_started = true; - me->_emit_event(DriverAttachmentEvent{ClientType::jack}); - } - - me->_emit_event( - DisconnectionEvent{PortID::jack(client_name, port_name), - PortID::jack(client2_name, port2_name)}); - - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + const char* client2_name = nullptr; + const char* client_name = nullptr; + const char* new_owner = nullptr; + const char* object_name = nullptr; + const char* old_owner = nullptr; + const char* port2_name = nullptr; + const char* port_name = nullptr; + dbus_uint32_t port_flags = 0u; + dbus_uint32_t port_type = 0u; + dbus_uint64_t client2_id = 0u; + dbus_uint64_t client_id = 0u; + dbus_uint64_t connection_id = 0u; + dbus_uint64_t new_graph_version = 0u; + dbus_uint64_t port2_id = 0u; + dbus_uint64_t port_id = 0u; + + assert(jack_driver); + auto* me = static_cast(jack_driver); + assert(me->_dbus_connection); + + if (dbus_message_is_signal( + message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { + if (!dbus_message_get_args(message, + &me->_dbus_error, + DBUS_TYPE_STRING, + &object_name, + DBUS_TYPE_STRING, + &old_owner, + DBUS_TYPE_STRING, + &new_owner, + DBUS_TYPE_INVALID)) { + me->error_msg(fmt::format("dbus_message_get_args() failed to extract " + "NameOwnerChanged signal arguments ({})", + me->_dbus_error.message)); + + dbus_error_free(&me->_dbus_error); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (old_owner[0] == '\0') { + me->on_jack_appeared(); + } else if (new_owner[0] == '\0') { + me->on_jack_disappeared(); + } + } + + if (dbus_message_is_signal( + message, JACKDBUS_IFACE_PATCHBAY, "PortAppeared")) { + if (!dbus_message_get_args(message, + &me->_dbus_error, + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_UINT64, + &port_id, + DBUS_TYPE_STRING, + &port_name, + DBUS_TYPE_UINT32, + &port_flags, + DBUS_TYPE_UINT32, + &port_type, + DBUS_TYPE_INVALID)) { + me->error_msg(fmt::format("dbus_message_get_args() failed to extract " + "PortAppeared signal arguments ({})", + me->_dbus_error.message)); + dbus_error_free(&me->_dbus_error); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (!me->_server_started) { + me->_server_started = true; + me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + } + + me->_emit_event( + PortCreationEvent{PortID::jack(client_name, port_name), + me->port_info(port_name, port_type, port_flags)}); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (dbus_message_is_signal( + message, JACKDBUS_IFACE_PATCHBAY, "PortDisappeared")) { + if (!dbus_message_get_args(message, + &me->_dbus_error, + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_UINT64, + &port_id, + DBUS_TYPE_STRING, + &port_name, + DBUS_TYPE_INVALID)) { + me->error_msg(fmt::format("dbus_message_get_args() failed to extract " + "PortDisappeared signal arguments ({})", + me->_dbus_error.message)); + dbus_error_free(&me->_dbus_error); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (!me->_server_started) { + me->_server_started = true; + me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + } + + me->_emit_event(PortDestructionEvent{PortID::jack(client_name, port_name)}); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (dbus_message_is_signal( + message, JACKDBUS_IFACE_PATCHBAY, "PortsConnected")) { + if (!dbus_message_get_args(message, + &me->_dbus_error, + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_UINT64, + &port_id, + DBUS_TYPE_STRING, + &port_name, + DBUS_TYPE_UINT64, + &client2_id, + DBUS_TYPE_STRING, + &client2_name, + DBUS_TYPE_UINT64, + &port2_id, + DBUS_TYPE_STRING, + &port2_name, + DBUS_TYPE_UINT64, + &connection_id, + DBUS_TYPE_INVALID)) { + me->error_msg(fmt::format("dbus_message_get_args() failed to extract " + "PortsConnected signal arguments ({})", + me->_dbus_error.message)); + dbus_error_free(&me->_dbus_error); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (!me->_server_started) { + me->_server_started = true; + me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + } + + me->_emit_event(ConnectionEvent{PortID::jack(client_name, port_name), + PortID::jack(client2_name, port2_name)}); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (dbus_message_is_signal( + message, JACKDBUS_IFACE_PATCHBAY, "PortsDisconnected")) { + if (!dbus_message_get_args(message, + &me->_dbus_error, + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_UINT64, + &port_id, + DBUS_TYPE_STRING, + &port_name, + DBUS_TYPE_UINT64, + &client2_id, + DBUS_TYPE_STRING, + &client2_name, + DBUS_TYPE_UINT64, + &port2_id, + DBUS_TYPE_STRING, + &port2_name, + DBUS_TYPE_UINT64, + &connection_id, + DBUS_TYPE_INVALID)) { + me->error_msg(fmt::format("dbus_message_get_args() failed to extract " + "PortsDisconnected signal arguments ({})", + me->_dbus_error.message)); + dbus_error_free(&me->_dbus_error); + return DBUS_HANDLER_RESULT_HANDLED; + } + + if (!me->_server_started) { + me->_server_started = true; + me->_emit_event(DriverAttachmentEvent{ClientType::jack}); + } + + me->_emit_event(DisconnectionEvent{PortID::jack(client_name, port_name), + PortID::jack(client2_name, port2_name)}); + + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } bool @@ -426,525 +418,513 @@ JackDriver::call(bool response_expected, int in_type, ...) { - DBusMessage* request_ptr = nullptr; - DBusMessage* reply_ptr = nullptr; - va_list ap; - - request_ptr = dbus_message_new_method_call( - JACKDBUS_SERVICE, JACKDBUS_OBJECT, iface, method); - if (!request_ptr) { - throw std::runtime_error("dbus_message_new_method_call() returned 0"); - } - - va_start(ap, in_type); - - dbus_message_append_args_valist(request_ptr, in_type, ap); - - va_end(ap); - - // send message and get a handle for a reply - reply_ptr = - dbus_connection_send_with_reply_and_block(_dbus_connection, - request_ptr, - JACKDBUS_CALL_DEFAULT_TIMEOUT, - &_dbus_error); - - dbus_message_unref(request_ptr); - - if (!reply_ptr) { - if (response_expected) { - error_msg( - fmt::format("No reply from server when calling method {} ({})", - method, - _dbus_error.message)); - } - _server_responding = false; - dbus_error_free(&_dbus_error); - } else { - _server_responding = true; - *reply_ptr_ptr = reply_ptr; - } - - return reply_ptr; + DBusMessage* request_ptr = nullptr; + DBusMessage* reply_ptr = nullptr; + va_list ap; + + request_ptr = dbus_message_new_method_call( + JACKDBUS_SERVICE, JACKDBUS_OBJECT, iface, method); + if (!request_ptr) { + throw std::runtime_error("dbus_message_new_method_call() returned 0"); + } + + va_start(ap, in_type); + + dbus_message_append_args_valist(request_ptr, in_type, ap); + + va_end(ap); + + // send message and get a handle for a reply + reply_ptr = dbus_connection_send_with_reply_and_block( + _dbus_connection, request_ptr, JACKDBUS_CALL_DEFAULT_TIMEOUT, &_dbus_error); + + dbus_message_unref(request_ptr); + + if (!reply_ptr) { + if (response_expected) { + error_msg(fmt::format("No reply from server when calling method {} ({})", + method, + _dbus_error.message)); + } + _server_responding = false; + dbus_error_free(&_dbus_error); + } else { + _server_responding = true; + *reply_ptr_ptr = reply_ptr; + } + + return reply_ptr; } bool JackDriver::is_started() { - DBusMessage* reply_ptr = nullptr; - dbus_bool_t started = false; - - if (!call(false, - JACKDBUS_IFACE_CONTROL, - "IsStarted", - &reply_ptr, - DBUS_TYPE_INVALID)) { - return false; - } - - if (!dbus_message_get_args(reply_ptr, - &_dbus_error, - DBUS_TYPE_BOOLEAN, - &started, - DBUS_TYPE_INVALID)) { - dbus_message_unref(reply_ptr); - dbus_error_free(&_dbus_error); - error_msg("Decoding reply of IsStarted failed"); - return false; - } - - dbus_message_unref(reply_ptr); - - return started; + DBusMessage* reply_ptr = nullptr; + dbus_bool_t started = false; + + if (!call(false, + JACKDBUS_IFACE_CONTROL, + "IsStarted", + &reply_ptr, + DBUS_TYPE_INVALID)) { + return false; + } + + if (!dbus_message_get_args(reply_ptr, + &_dbus_error, + DBUS_TYPE_BOOLEAN, + &started, + DBUS_TYPE_INVALID)) { + dbus_message_unref(reply_ptr); + dbus_error_free(&_dbus_error); + error_msg("Decoding reply of IsStarted failed"); + return false; + } + + dbus_message_unref(reply_ptr); + + return started; } void JackDriver::start_server() { - DBusMessage* reply_ptr = nullptr; + DBusMessage* reply_ptr = nullptr; - if (!call(false, - JACKDBUS_IFACE_CONTROL, - "StartServer", - &reply_ptr, - DBUS_TYPE_INVALID)) { - return; - } + if (!call(false, + JACKDBUS_IFACE_CONTROL, + "StartServer", + &reply_ptr, + DBUS_TYPE_INVALID)) { + return; + } - dbus_message_unref(reply_ptr); + dbus_message_unref(reply_ptr); - update_attached(); + update_attached(); } void JackDriver::stop_server() { - DBusMessage* reply_ptr = nullptr; - - if (!call(false, - JACKDBUS_IFACE_CONTROL, - "StopServer", - &reply_ptr, - DBUS_TYPE_INVALID)) { - error_msg("Error stopping JACK server"); - } - - dbus_message_unref(reply_ptr); - _emit_event(DriverDetachmentEvent{ClientType::jack}); + DBusMessage* reply_ptr = nullptr; + + if (!call(false, + JACKDBUS_IFACE_CONTROL, + "StopServer", + &reply_ptr, + DBUS_TYPE_INVALID)) { + error_msg("Error stopping JACK server"); + } + + dbus_message_unref(reply_ptr); + _emit_event(DriverDetachmentEvent{ClientType::jack}); } void JackDriver::attach(bool launch_daemon) { - // Connect to the bus - _dbus_connection = dbus_bus_get(DBUS_BUS_SESSION, &_dbus_error); - if (dbus_error_is_set(&_dbus_error)) { - error_msg( - fmt::format("dbus_bus_get() failed ({})", _dbus_error.message)); - dbus_error_free(&_dbus_error); - return; - } - - dbus_connection_setup_with_g_main(_dbus_connection, nullptr); - - dbus_bus_add_match(_dbus_connection, - "type='signal',interface='" DBUS_INTERFACE_DBUS - "',member=NameOwnerChanged,arg0='org.jackaudio.service'", - nullptr); - dbus_bus_add_match(_dbus_connection, - "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY - "',member=PortAppeared", - nullptr); - dbus_bus_add_match(_dbus_connection, - "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY - "',member=PortDisappeared", - nullptr); - dbus_bus_add_match(_dbus_connection, - "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY - "',member=PortsConnected", - nullptr); - dbus_bus_add_match(_dbus_connection, - "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY - "',member=PortsDisconnected", - nullptr); - - dbus_connection_add_filter( - _dbus_connection, dbus_message_hook, this, nullptr); - - update_attached(); - - if (!_server_responding) { - return; - } - - if (launch_daemon) { - start_server(); - } - - _log.info("[JACK] Attached to bus"); + // Connect to the bus + _dbus_connection = dbus_bus_get(DBUS_BUS_SESSION, &_dbus_error); + if (dbus_error_is_set(&_dbus_error)) { + error_msg(fmt::format("dbus_bus_get() failed ({})", _dbus_error.message)); + dbus_error_free(&_dbus_error); + return; + } + + dbus_connection_setup_with_g_main(_dbus_connection, nullptr); + + dbus_bus_add_match(_dbus_connection, + "type='signal',interface='" DBUS_INTERFACE_DBUS + "',member=NameOwnerChanged,arg0='org.jackaudio.service'", + nullptr); + dbus_bus_add_match(_dbus_connection, + "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY + "',member=PortAppeared", + nullptr); + dbus_bus_add_match(_dbus_connection, + "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY + "',member=PortDisappeared", + nullptr); + dbus_bus_add_match(_dbus_connection, + "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY + "',member=PortsConnected", + nullptr); + dbus_bus_add_match(_dbus_connection, + "type='signal',interface='" JACKDBUS_IFACE_PATCHBAY + "',member=PortsDisconnected", + nullptr); + + dbus_connection_add_filter( + _dbus_connection, dbus_message_hook, this, nullptr); + + update_attached(); + + if (!_server_responding) { + return; + } + + if (launch_daemon) { + start_server(); + } + + _log.info("[JACK] Attached to bus"); } void JackDriver::detach() { - stop_server(); + stop_server(); } bool JackDriver::is_attached() const { - return _dbus_connection && _server_responding; + return _dbus_connection && _server_responding; } void JackDriver::refresh(const EventSink& sink) { - DBusMessage* reply_ptr = nullptr; - DBusMessageIter iter = {}; - dbus_uint64_t version = 0u; - const char* reply_signature = nullptr; - DBusMessageIter clients_array_iter = {}; - DBusMessageIter client_struct_iter = {}; - DBusMessageIter ports_array_iter = {}; - DBusMessageIter port_struct_iter = {}; - DBusMessageIter connections_array_iter = {}; - DBusMessageIter connection_struct_iter = {}; - dbus_uint64_t client_id = 0u; - const char* client_name = nullptr; - dbus_uint64_t port_id = 0u; - const char* port_name = nullptr; - dbus_uint32_t port_flags = 0u; - dbus_uint32_t port_type = 0u; - dbus_uint64_t client2_id = 0u; - const char* client2_name = nullptr; - dbus_uint64_t port2_id = 0u; - const char* port2_name = nullptr; - dbus_uint64_t connection_id = 0u; - - if (!call(true, - JACKDBUS_IFACE_PATCHBAY, - "GetGraph", - &reply_ptr, - DBUS_TYPE_UINT64, - &version, - DBUS_TYPE_INVALID)) { - error_msg("GetGraph() failed"); - return; - } - - reply_signature = dbus_message_get_signature(reply_ptr); - - if (strcmp(reply_signature, "ta(tsa(tsuu))a(tstststst)") != 0) { - error_msg(std::string{"GetGraph() reply signature mismatch. "} + - reply_signature); - dbus_message_unref(reply_ptr); - return; - } - - dbus_message_iter_init(reply_ptr, &iter); - - dbus_message_iter_get_basic(&iter, &version); - dbus_message_iter_next(&iter); - - _graph_version = version; - - // Emit all clients and ports - for (dbus_message_iter_recurse(&iter, &clients_array_iter); - dbus_message_iter_get_arg_type(&clients_array_iter) != - DBUS_TYPE_INVALID; - dbus_message_iter_next(&clients_array_iter)) { - dbus_message_iter_recurse(&clients_array_iter, &client_struct_iter); - - dbus_message_iter_get_basic(&client_struct_iter, &client_id); - dbus_message_iter_next(&client_struct_iter); - - dbus_message_iter_get_basic(&client_struct_iter, &client_name); - dbus_message_iter_next(&client_struct_iter); - - // TODO: Pretty name? - sink({ClientCreationEvent{ClientID::jack(client_name), {client_name}}}); - - for (dbus_message_iter_recurse(&client_struct_iter, &ports_array_iter); - dbus_message_iter_get_arg_type(&ports_array_iter) != - DBUS_TYPE_INVALID; - dbus_message_iter_next(&ports_array_iter)) { - dbus_message_iter_recurse(&ports_array_iter, &port_struct_iter); - - dbus_message_iter_get_basic(&port_struct_iter, &port_id); - dbus_message_iter_next(&port_struct_iter); - - dbus_message_iter_get_basic(&port_struct_iter, &port_name); - dbus_message_iter_next(&port_struct_iter); - - dbus_message_iter_get_basic(&port_struct_iter, &port_flags); - dbus_message_iter_next(&port_struct_iter); - - dbus_message_iter_get_basic(&port_struct_iter, &port_type); - dbus_message_iter_next(&port_struct_iter); - - sink({PortCreationEvent{ - PortID::jack(client_name, port_name), - port_info(port_name, port_type, port_flags)}}); - } - - dbus_message_iter_next(&client_struct_iter); - } - - dbus_message_iter_next(&iter); - - // Emit all connections - for (dbus_message_iter_recurse(&iter, &connections_array_iter); - dbus_message_iter_get_arg_type(&connections_array_iter) != - DBUS_TYPE_INVALID; - dbus_message_iter_next(&connections_array_iter)) { - dbus_message_iter_recurse(&connections_array_iter, - &connection_struct_iter); - - dbus_message_iter_get_basic(&connection_struct_iter, &client_id); - dbus_message_iter_next(&connection_struct_iter); - - dbus_message_iter_get_basic(&connection_struct_iter, &client_name); - dbus_message_iter_next(&connection_struct_iter); - - dbus_message_iter_get_basic(&connection_struct_iter, &port_id); - dbus_message_iter_next(&connection_struct_iter); - - dbus_message_iter_get_basic(&connection_struct_iter, &port_name); - dbus_message_iter_next(&connection_struct_iter); + DBusMessage* reply_ptr = nullptr; + DBusMessageIter iter = {}; + dbus_uint64_t version = 0u; + const char* reply_signature = nullptr; + DBusMessageIter clients_array_iter = {}; + DBusMessageIter client_struct_iter = {}; + DBusMessageIter ports_array_iter = {}; + DBusMessageIter port_struct_iter = {}; + DBusMessageIter connections_array_iter = {}; + DBusMessageIter connection_struct_iter = {}; + dbus_uint64_t client_id = 0u; + const char* client_name = nullptr; + dbus_uint64_t port_id = 0u; + const char* port_name = nullptr; + dbus_uint32_t port_flags = 0u; + dbus_uint32_t port_type = 0u; + dbus_uint64_t client2_id = 0u; + const char* client2_name = nullptr; + dbus_uint64_t port2_id = 0u; + const char* port2_name = nullptr; + dbus_uint64_t connection_id = 0u; + + if (!call(true, + JACKDBUS_IFACE_PATCHBAY, + "GetGraph", + &reply_ptr, + DBUS_TYPE_UINT64, + &version, + DBUS_TYPE_INVALID)) { + error_msg("GetGraph() failed"); + return; + } + + reply_signature = dbus_message_get_signature(reply_ptr); + + if (strcmp(reply_signature, "ta(tsa(tsuu))a(tstststst)") != 0) { + error_msg(std::string{"GetGraph() reply signature mismatch. "} + + reply_signature); + dbus_message_unref(reply_ptr); + return; + } + + dbus_message_iter_init(reply_ptr, &iter); + + dbus_message_iter_get_basic(&iter, &version); + dbus_message_iter_next(&iter); + + _graph_version = version; + + // Emit all clients and ports + for (dbus_message_iter_recurse(&iter, &clients_array_iter); + dbus_message_iter_get_arg_type(&clients_array_iter) != DBUS_TYPE_INVALID; + dbus_message_iter_next(&clients_array_iter)) { + dbus_message_iter_recurse(&clients_array_iter, &client_struct_iter); + + dbus_message_iter_get_basic(&client_struct_iter, &client_id); + dbus_message_iter_next(&client_struct_iter); + + dbus_message_iter_get_basic(&client_struct_iter, &client_name); + dbus_message_iter_next(&client_struct_iter); + + // TODO: Pretty name? + sink({ClientCreationEvent{ClientID::jack(client_name), {client_name}}}); + + for (dbus_message_iter_recurse(&client_struct_iter, &ports_array_iter); + dbus_message_iter_get_arg_type(&ports_array_iter) != DBUS_TYPE_INVALID; + dbus_message_iter_next(&ports_array_iter)) { + dbus_message_iter_recurse(&ports_array_iter, &port_struct_iter); + + dbus_message_iter_get_basic(&port_struct_iter, &port_id); + dbus_message_iter_next(&port_struct_iter); + + dbus_message_iter_get_basic(&port_struct_iter, &port_name); + dbus_message_iter_next(&port_struct_iter); + + dbus_message_iter_get_basic(&port_struct_iter, &port_flags); + dbus_message_iter_next(&port_struct_iter); + + dbus_message_iter_get_basic(&port_struct_iter, &port_type); + dbus_message_iter_next(&port_struct_iter); + + sink({PortCreationEvent{PortID::jack(client_name, port_name), + port_info(port_name, port_type, port_flags)}}); + } + + dbus_message_iter_next(&client_struct_iter); + } + + dbus_message_iter_next(&iter); + + // Emit all connections + for (dbus_message_iter_recurse(&iter, &connections_array_iter); + dbus_message_iter_get_arg_type(&connections_array_iter) != + DBUS_TYPE_INVALID; + dbus_message_iter_next(&connections_array_iter)) { + dbus_message_iter_recurse(&connections_array_iter, &connection_struct_iter); + + dbus_message_iter_get_basic(&connection_struct_iter, &client_id); + dbus_message_iter_next(&connection_struct_iter); + + dbus_message_iter_get_basic(&connection_struct_iter, &client_name); + dbus_message_iter_next(&connection_struct_iter); + + dbus_message_iter_get_basic(&connection_struct_iter, &port_id); + dbus_message_iter_next(&connection_struct_iter); + + dbus_message_iter_get_basic(&connection_struct_iter, &port_name); + dbus_message_iter_next(&connection_struct_iter); - dbus_message_iter_get_basic(&connection_struct_iter, &client2_id); - dbus_message_iter_next(&connection_struct_iter); + dbus_message_iter_get_basic(&connection_struct_iter, &client2_id); + dbus_message_iter_next(&connection_struct_iter); - dbus_message_iter_get_basic(&connection_struct_iter, &client2_name); - dbus_message_iter_next(&connection_struct_iter); + dbus_message_iter_get_basic(&connection_struct_iter, &client2_name); + dbus_message_iter_next(&connection_struct_iter); - dbus_message_iter_get_basic(&connection_struct_iter, &port2_id); - dbus_message_iter_next(&connection_struct_iter); + dbus_message_iter_get_basic(&connection_struct_iter, &port2_id); + dbus_message_iter_next(&connection_struct_iter); - dbus_message_iter_get_basic(&connection_struct_iter, &port2_name); - dbus_message_iter_next(&connection_struct_iter); + dbus_message_iter_get_basic(&connection_struct_iter, &port2_name); + dbus_message_iter_next(&connection_struct_iter); - dbus_message_iter_get_basic(&connection_struct_iter, &connection_id); - dbus_message_iter_next(&connection_struct_iter); + dbus_message_iter_get_basic(&connection_struct_iter, &connection_id); + dbus_message_iter_next(&connection_struct_iter); - sink({ConnectionEvent{PortID::jack(client_name, port_name), - PortID::jack(client2_name, port2_name)}}); - } + sink({ConnectionEvent{PortID::jack(client_name, port_name), + PortID::jack(client2_name, port2_name)}}); + } } bool JackDriver::connect(const PortID& tail_id, const PortID& head_id) { - const auto tail_names = PortNames(tail_id); - const auto head_names = PortNames(head_id); - const char* const tail_client_name = tail_names.client().c_str(); - const char* const tail_port_name = tail_names.port().c_str(); - const char* const head_client_name = head_names.client().c_str(); - const char* const head_port_name = head_names.port().c_str(); - - DBusMessage* reply_ptr = nullptr; - - if (!call(true, - JACKDBUS_IFACE_PATCHBAY, - "ConnectPortsByName", - &reply_ptr, - DBUS_TYPE_STRING, - &tail_client_name, - DBUS_TYPE_STRING, - &tail_port_name, - DBUS_TYPE_STRING, - &head_client_name, - DBUS_TYPE_STRING, - &head_port_name, - DBUS_TYPE_INVALID)) { - error_msg("ConnectPortsByName() failed"); - return false; - } - - return true; + const auto tail_names = PortNames(tail_id); + const auto head_names = PortNames(head_id); + const char* const tail_client_name = tail_names.client().c_str(); + const char* const tail_port_name = tail_names.port().c_str(); + const char* const head_client_name = head_names.client().c_str(); + const char* const head_port_name = head_names.port().c_str(); + + DBusMessage* reply_ptr = nullptr; + + if (!call(true, + JACKDBUS_IFACE_PATCHBAY, + "ConnectPortsByName", + &reply_ptr, + DBUS_TYPE_STRING, + &tail_client_name, + DBUS_TYPE_STRING, + &tail_port_name, + DBUS_TYPE_STRING, + &head_client_name, + DBUS_TYPE_STRING, + &head_port_name, + DBUS_TYPE_INVALID)) { + error_msg("ConnectPortsByName() failed"); + return false; + } + + return true; } bool JackDriver::disconnect(const PortID& tail_id, const PortID& head_id) { - const auto tail_names = PortNames(tail_id); - const auto head_names = PortNames(head_id); - const char* const tail_client_name = tail_names.client().c_str(); - const char* const tail_port_name = tail_names.port().c_str(); - const char* const head_client_name = head_names.client().c_str(); - const char* const head_port_name = head_names.port().c_str(); - - DBusMessage* reply_ptr = nullptr; - - if (!call(true, - JACKDBUS_IFACE_PATCHBAY, - "DisconnectPortsByName", - &reply_ptr, - DBUS_TYPE_STRING, - &tail_client_name, - DBUS_TYPE_STRING, - &tail_port_name, - DBUS_TYPE_STRING, - &head_client_name, - DBUS_TYPE_STRING, - &head_port_name, - DBUS_TYPE_INVALID)) { - error_msg("DisconnectPortsByName() failed"); - return false; - } - - return true; + const auto tail_names = PortNames(tail_id); + const auto head_names = PortNames(head_id); + const char* const tail_client_name = tail_names.client().c_str(); + const char* const tail_port_name = tail_names.port().c_str(); + const char* const head_client_name = head_names.client().c_str(); + const char* const head_port_name = head_names.port().c_str(); + + DBusMessage* reply_ptr = nullptr; + + if (!call(true, + JACKDBUS_IFACE_PATCHBAY, + "DisconnectPortsByName", + &reply_ptr, + DBUS_TYPE_STRING, + &tail_client_name, + DBUS_TYPE_STRING, + &tail_port_name, + DBUS_TYPE_STRING, + &head_client_name, + DBUS_TYPE_STRING, + &head_port_name, + DBUS_TYPE_INVALID)) { + error_msg("DisconnectPortsByName() failed"); + return false; + } + + return true; } uint32_t JackDriver::xruns() { - DBusMessage* reply_ptr = nullptr; - dbus_uint32_t xruns = 0u; - - if (_server_responding && !_server_started) { - return 0; - } - - if (!call(true, - JACKDBUS_IFACE_CONTROL, - "GetXruns", - &reply_ptr, - DBUS_TYPE_INVALID)) { - return 0; - } - - if (!dbus_message_get_args(reply_ptr, - &_dbus_error, - DBUS_TYPE_UINT32, - &xruns, - DBUS_TYPE_INVALID)) { - dbus_message_unref(reply_ptr); - dbus_error_free(&_dbus_error); - error_msg("Decoding reply of GetXruns failed"); - return 0; - } - - dbus_message_unref(reply_ptr); - - return xruns; + DBusMessage* reply_ptr = nullptr; + dbus_uint32_t xruns = 0u; + + if (_server_responding && !_server_started) { + return 0; + } + + if (!call(true, + JACKDBUS_IFACE_CONTROL, + "GetXruns", + &reply_ptr, + DBUS_TYPE_INVALID)) { + return 0; + } + + if (!dbus_message_get_args( + reply_ptr, &_dbus_error, DBUS_TYPE_UINT32, &xruns, DBUS_TYPE_INVALID)) { + dbus_message_unref(reply_ptr); + dbus_error_free(&_dbus_error); + error_msg("Decoding reply of GetXruns failed"); + return 0; + } + + dbus_message_unref(reply_ptr); + + return xruns; } void JackDriver::reset_xruns() { - DBusMessage* reply_ptr = nullptr; + DBusMessage* reply_ptr = nullptr; - if (!call(true, - JACKDBUS_IFACE_CONTROL, - "ResetXruns", - &reply_ptr, - DBUS_TYPE_INVALID)) { - return; - } + if (!call(true, + JACKDBUS_IFACE_CONTROL, + "ResetXruns", + &reply_ptr, + DBUS_TYPE_INVALID)) { + return; + } - dbus_message_unref(reply_ptr); + dbus_message_unref(reply_ptr); } uint32_t JackDriver::buffer_size() { - DBusMessage* reply_ptr = nullptr; - dbus_uint32_t buffer_size = 0u; - - if (_server_responding && !_server_started) { - return 4096; - } - - if (!call(true, - JACKDBUS_IFACE_CONTROL, - "GetBufferSize", - &reply_ptr, - DBUS_TYPE_INVALID)) { - return 4096; - } - - if (!dbus_message_get_args(reply_ptr, - &_dbus_error, - DBUS_TYPE_UINT32, - &buffer_size, - DBUS_TYPE_INVALID)) { - dbus_message_unref(reply_ptr); - dbus_error_free(&_dbus_error); - error_msg("Decoding reply of GetBufferSize failed"); - return 4096; - } - - dbus_message_unref(reply_ptr); - - return buffer_size; + DBusMessage* reply_ptr = nullptr; + dbus_uint32_t buffer_size = 0u; + + if (_server_responding && !_server_started) { + return 4096; + } + + if (!call(true, + JACKDBUS_IFACE_CONTROL, + "GetBufferSize", + &reply_ptr, + DBUS_TYPE_INVALID)) { + return 4096; + } + + if (!dbus_message_get_args(reply_ptr, + &_dbus_error, + DBUS_TYPE_UINT32, + &buffer_size, + DBUS_TYPE_INVALID)) { + dbus_message_unref(reply_ptr); + dbus_error_free(&_dbus_error); + error_msg("Decoding reply of GetBufferSize failed"); + return 4096; + } + + dbus_message_unref(reply_ptr); + + return buffer_size; } bool JackDriver::set_buffer_size(const uint32_t frames) { - DBusMessage* reply_ptr = nullptr; - dbus_uint32_t buffer_size = frames; - - if (!call(true, - JACKDBUS_IFACE_CONTROL, - "SetBufferSize", - &reply_ptr, - DBUS_TYPE_UINT32, - &buffer_size, - DBUS_TYPE_INVALID)) { - return false; - } - - dbus_message_unref(reply_ptr); - - return true; + DBusMessage* reply_ptr = nullptr; + dbus_uint32_t buffer_size = frames; + + if (!call(true, + JACKDBUS_IFACE_CONTROL, + "SetBufferSize", + &reply_ptr, + DBUS_TYPE_UINT32, + &buffer_size, + DBUS_TYPE_INVALID)) { + return false; + } + + dbus_message_unref(reply_ptr); + + return true; } uint32_t JackDriver::sample_rate() { - DBusMessage* reply_ptr = nullptr; - dbus_uint32_t sample_rate = 0u; - - if (!call(true, - JACKDBUS_IFACE_CONTROL, - "GetSampleRate", - &reply_ptr, - DBUS_TYPE_INVALID)) { - return false; - } - - if (!dbus_message_get_args(reply_ptr, - &_dbus_error, - DBUS_TYPE_UINT32, - &sample_rate, - DBUS_TYPE_INVALID)) { - dbus_message_unref(reply_ptr); - dbus_error_free(&_dbus_error); - error_msg("Decoding reply of GetSampleRate failed"); - return false; - } - - dbus_message_unref(reply_ptr); - - return sample_rate; + DBusMessage* reply_ptr = nullptr; + dbus_uint32_t sample_rate = 0u; + + if (!call(true, + JACKDBUS_IFACE_CONTROL, + "GetSampleRate", + &reply_ptr, + DBUS_TYPE_INVALID)) { + return false; + } + + if (!dbus_message_get_args(reply_ptr, + &_dbus_error, + DBUS_TYPE_UINT32, + &sample_rate, + DBUS_TYPE_INVALID)) { + dbus_message_unref(reply_ptr); + dbus_error_free(&_dbus_error); + error_msg("Decoding reply of GetSampleRate failed"); + return false; + } + + dbus_message_unref(reply_ptr); + + return sample_rate; } PortType JackDriver::patchage_port_type(const dbus_uint32_t dbus_port_type) const { - switch (dbus_port_type) { - case JACKDBUS_PORT_TYPE_AUDIO: - return PortType::jack_audio; - case JACKDBUS_PORT_TYPE_MIDI: - return PortType::jack_midi; - default: - break; - } - - error_msg(fmt::format("Unknown JACK D-Bus port type {}", dbus_port_type)); - return PortType::jack_audio; + switch (dbus_port_type) { + case JACKDBUS_PORT_TYPE_AUDIO: + return PortType::jack_audio; + case JACKDBUS_PORT_TYPE_MIDI: + return PortType::jack_midi; + default: + break; + } + + error_msg(fmt::format("Unknown JACK D-Bus port type {}", dbus_port_type)); + return PortType::jack_audio; } PortInfo @@ -952,28 +932,28 @@ JackDriver::port_info(const std::string& port_name, const dbus_uint32_t port_type, const dbus_uint32_t port_flags) const { - const SignalDirection direction = - ((port_flags & JACKDBUS_PORT_FLAG_INPUT) ? SignalDirection::input - : SignalDirection::output); - - // TODO: Metadata? - return {port_name, - patchage_port_type(port_type), - direction, - {}, - bool(port_flags & JACKDBUS_PORT_FLAG_TERMINAL)}; + const SignalDirection direction = + ((port_flags & JACKDBUS_PORT_FLAG_INPUT) ? SignalDirection::input + : SignalDirection::output); + + // TODO: Metadata? + return {port_name, + patchage_port_type(port_type), + direction, + {}, + bool(port_flags & JACKDBUS_PORT_FLAG_TERMINAL)}; } void JackDriver::error_msg(const std::string& msg) const { - _log.error(std::string{"[JACK] "} + msg); + _log.error(std::string{"[JACK] "} + msg); } void JackDriver::info_msg(const std::string& msg) const { - _log.info(std::string{"[JACK] "} + msg); + _log.info(std::string{"[JACK] "} + msg); } } // namespace @@ -981,8 +961,8 @@ JackDriver::info_msg(const std::string& msg) const std::unique_ptr make_jack_driver(ILog& log, Driver::EventSink emit_event) { - return std::unique_ptr{ - new JackDriver{log, std::move(emit_event)}}; + return std::unique_ptr{ + new JackDriver{log, std::move(emit_event)}}; } } // namespace patchage diff --git a/src/JackLibDriver.cpp b/src/JackLibDriver.cpp index 21c8f9b..feb8e8c 100644 --- a/src/JackLibDriver.cpp +++ b/src/JackLibDriver.cpp @@ -32,7 +32,7 @@ #include "warnings.hpp" #ifdef HAVE_JACK_METADATA -# include +# include #endif PATCHAGE_DISABLE_FMT_WARNINGS @@ -60,350 +60,350 @@ namespace { class JackLibDriver : public AudioDriver { public: - explicit JackLibDriver(ILog& log, EventSink emit_event); + explicit JackLibDriver(ILog& log, EventSink emit_event); - JackLibDriver(const JackLibDriver&) = delete; - JackLibDriver& operator=(const JackLibDriver&) = delete; + JackLibDriver(const JackLibDriver&) = delete; + JackLibDriver& operator=(const JackLibDriver&) = delete; - JackLibDriver(JackLibDriver&&) = delete; - JackLibDriver& operator=(JackLibDriver&&) = delete; + JackLibDriver(JackLibDriver&&) = delete; + JackLibDriver& operator=(JackLibDriver&&) = delete; - ~JackLibDriver() override; + ~JackLibDriver() override; - // Driver interface - void attach(bool launch_daemon) override; - void detach() override; - bool is_attached() const override; - void refresh(const EventSink& sink) override; - bool connect(const PortID& tail_id, const PortID& head_id) override; - bool disconnect(const PortID& tail_id, const PortID& head_id) override; + // Driver interface + void attach(bool launch_daemon) override; + void detach() override; + bool is_attached() const override; + void refresh(const EventSink& sink) override; + bool connect(const PortID& tail_id, const PortID& head_id) override; + bool disconnect(const PortID& tail_id, const PortID& head_id) override; - // AudioDriver interface - uint32_t xruns() override; - void reset_xruns() override; - uint32_t buffer_size() override; - bool set_buffer_size(uint32_t frames) override; - uint32_t sample_rate() override; + // AudioDriver interface + uint32_t xruns() override; + void reset_xruns() override; + uint32_t buffer_size() override; + bool set_buffer_size(uint32_t frames) override; + uint32_t sample_rate() override; private: - ClientInfo get_client_info(const char* name); - PortInfo get_port_info(const jack_port_t* port); + ClientInfo get_client_info(const char* name); + PortInfo get_port_info(const jack_port_t* port); - static void on_client(const char* name, int registered, void* driver); + static void on_client(const char* name, int registered, void* driver); - static void on_port(jack_port_id_t port_id, int registered, void* driver); + static void on_port(jack_port_id_t port_id, int registered, void* driver); - static void on_connection(jack_port_id_t src, - jack_port_id_t dst, - int connect, - void* driver); + static void on_connection(jack_port_id_t src, + jack_port_id_t dst, + int connect, + void* driver); - static int on_xrun(void* driver); + static int on_xrun(void* driver); - static void on_shutdown(void* driver); + static void on_shutdown(void* driver); - ILog& _log; - std::mutex _shutdown_mutex; + ILog& _log; + std::mutex _shutdown_mutex; - jack_client_t* _client = nullptr; - jack_nframes_t _buffer_size = 0u; - uint32_t _xruns = 0u; - bool _is_activated = false; + jack_client_t* _client = nullptr; + jack_nframes_t _buffer_size = 0u; + uint32_t _xruns = 0u; + bool _is_activated = false; }; JackLibDriver::JackLibDriver(ILog& log, EventSink emit_event) - : AudioDriver{std::move(emit_event)} - , _log{log} + : AudioDriver{std::move(emit_event)} + , _log{log} {} JackLibDriver::~JackLibDriver() { - detach(); + detach(); } void JackLibDriver::attach(const bool launch_daemon) { - if (_client) { - return; // Already connected - } - - const jack_options_t options = - (!launch_daemon) ? JackNoStartServer : JackNullOption; - - if (!(_client = jack_client_open("Patchage", options, nullptr))) { - _log.error("[JACK] Unable to create client"); - _is_activated = false; - return; - } - - jack_on_shutdown(_client, on_shutdown, this); - jack_set_client_registration_callback(_client, on_client, this); - jack_set_port_registration_callback(_client, on_port, this); - jack_set_port_connect_callback(_client, on_connection, this); - jack_set_xrun_callback(_client, on_xrun, this); - - if (jack_activate(_client)) { - _log.error("[JACK] Client activation failed"); - _is_activated = false; - _buffer_size = 0; - return; - } - - _is_activated = true; - _buffer_size = jack_get_buffer_size(_client); - - _emit_event(DriverAttachmentEvent{ClientType::jack}); + if (_client) { + return; // Already connected + } + + const jack_options_t options = + (!launch_daemon) ? JackNoStartServer : JackNullOption; + + if (!(_client = jack_client_open("Patchage", options, nullptr))) { + _log.error("[JACK] Unable to create client"); + _is_activated = false; + return; + } + + jack_on_shutdown(_client, on_shutdown, this); + jack_set_client_registration_callback(_client, on_client, this); + jack_set_port_registration_callback(_client, on_port, this); + jack_set_port_connect_callback(_client, on_connection, this); + jack_set_xrun_callback(_client, on_xrun, this); + + if (jack_activate(_client)) { + _log.error("[JACK] Client activation failed"); + _is_activated = false; + _buffer_size = 0; + return; + } + + _is_activated = true; + _buffer_size = jack_get_buffer_size(_client); + + _emit_event(DriverAttachmentEvent{ClientType::jack}); } void JackLibDriver::detach() { - std::lock_guard lock{_shutdown_mutex}; + std::lock_guard lock{_shutdown_mutex}; - if (_client) { - jack_deactivate(_client); - jack_client_close(_client); - _client = nullptr; - } + if (_client) { + jack_deactivate(_client); + jack_client_close(_client); + _client = nullptr; + } - _is_activated = false; - _emit_event(DriverDetachmentEvent{ClientType::jack}); + _is_activated = false; + _emit_event(DriverDetachmentEvent{ClientType::jack}); } bool JackLibDriver::is_attached() const { - return _client != nullptr; + return _client != nullptr; } std::string get_property(const jack_uuid_t subject, const char* const key) { - std::string result; + std::string result; #ifdef HAVE_JACK_METADATA - char* value = nullptr; - char* datatype = nullptr; - if (!jack_get_property(subject, key, &value, &datatype)) { - result = value; - } - jack_free(datatype); - jack_free(value); + char* value = nullptr; + char* datatype = nullptr; + if (!jack_get_property(subject, key, &value, &datatype)) { + result = value; + } + jack_free(datatype); + jack_free(value); #else - (void)subject; - (void)key; + (void)subject; + (void)key; #endif - return result; + return result; } ClientInfo JackLibDriver::get_client_info(const char* const name) { - return {name}; // TODO: Pretty name? + return {name}; // TODO: Pretty name? } PortInfo JackLibDriver::get_port_info(const jack_port_t* const port) { - const auto uuid = jack_port_uuid(port); - const auto flags = jack_port_flags(port); - const std::string name = jack_port_name(port); - auto label = PortNames{name}.port(); + const auto uuid = jack_port_uuid(port); + const auto flags = jack_port_flags(port); + const std::string name = jack_port_name(port); + auto label = PortNames{name}.port(); - // Get pretty name to use as a label, if present + // Get pretty name to use as a label, if present #ifdef HAVE_JACK_METADATA - const auto pretty_name = get_property(uuid, JACK_METADATA_PRETTY_NAME); - if (!pretty_name.empty()) { - label = pretty_name; - } + const auto pretty_name = get_property(uuid, JACK_METADATA_PRETTY_NAME); + if (!pretty_name.empty()) { + label = pretty_name; + } #endif - // Determine detailed type, using metadata for fancy types if possible - const char* const type_str = jack_port_type(port); - PortType type = PortType::jack_audio; - if (!strcmp(type_str, JACK_DEFAULT_AUDIO_TYPE)) { - if (get_property(uuid, JACKEY_SIGNAL_TYPE) == "CV") { - type = PortType::jack_cv; - } - } else if (!strcmp(type_str, JACK_DEFAULT_MIDI_TYPE)) { - type = PortType::jack_midi; - if (get_property(uuid, JACKEY_EVENT_TYPES) == "OSC") { - type = PortType::jack_osc; - } - } else { - _log.warning(fmt::format( - R"([JACK] Port "{}" has unknown type "{}")", name, type_str)); - } - - // Get direction from port flags - const SignalDirection direction = - ((flags & JackPortIsInput) ? SignalDirection::input - : SignalDirection::output); - - // Get port order from metadata if possible - boost::optional order; - const std::string order_str = get_property(uuid, JACKEY_ORDER); - if (!order_str.empty()) { - order = std::stoi(order_str); - } - - return {label, type, direction, order, bool(flags & JackPortIsTerminal)}; + // Determine detailed type, using metadata for fancy types if possible + const char* const type_str = jack_port_type(port); + PortType type = PortType::jack_audio; + if (!strcmp(type_str, JACK_DEFAULT_AUDIO_TYPE)) { + if (get_property(uuid, JACKEY_SIGNAL_TYPE) == "CV") { + type = PortType::jack_cv; + } + } else if (!strcmp(type_str, JACK_DEFAULT_MIDI_TYPE)) { + type = PortType::jack_midi; + if (get_property(uuid, JACKEY_EVENT_TYPES) == "OSC") { + type = PortType::jack_osc; + } + } else { + _log.warning( + fmt::format(R"([JACK] Port "{}" has unknown type "{}")", name, type_str)); + } + + // Get direction from port flags + const SignalDirection direction = + ((flags & JackPortIsInput) ? SignalDirection::input + : SignalDirection::output); + + // Get port order from metadata if possible + boost::optional order; + const std::string order_str = get_property(uuid, JACKEY_ORDER); + if (!order_str.empty()) { + order = std::stoi(order_str); + } + + return {label, type, direction, order, bool(flags & JackPortIsTerminal)}; } void JackLibDriver::refresh(const EventSink& sink) { - std::lock_guard lock{_shutdown_mutex}; - - if (!_client) { - return; - } - - // Get all existing ports - const char** const ports = jack_get_ports(_client, nullptr, nullptr, 0); - if (!ports) { - return; - } - - // Get all client names (to only send a creation event once for each) - std::unordered_set client_names; - for (auto i = 0u; ports[i]; ++i) { - client_names.insert(PortID::jack(ports[i]).client().jack_name()); - } - - // Emit all clients - for (const auto& client_name : client_names) { - sink({ClientCreationEvent{ClientID::jack(client_name), - get_client_info(client_name.c_str())}}); - } - - // Emit all ports - for (auto i = 0u; ports[i]; ++i) { - const jack_port_t* const port = jack_port_by_name(_client, ports[i]); - - sink({PortCreationEvent{PortID::jack(ports[i]), get_port_info(port)}}); - } - - // Get all connections (again to only create them once) - std::set> connections; - for (auto i = 0u; ports[i]; ++i) { - const jack_port_t* const port = jack_port_by_name(_client, ports[i]); - const char** const peers = jack_port_get_all_connections(_client, port); - - if (peers) { - if (jack_port_flags(port) & JackPortIsInput) { - for (auto j = 0u; peers[j]; ++j) { - connections.emplace(peers[j], ports[i]); - } - } else { - for (auto j = 0u; peers[j]; ++j) { - connections.emplace(ports[i], peers[j]); - } - } - - jack_free(peers); - } - } - - // Emit all connections - for (const auto& connection : connections) { - sink({ConnectionEvent{PortID::jack(connection.first), - PortID::jack(connection.second)}}); - } - - jack_free(ports); + std::lock_guard lock{_shutdown_mutex}; + + if (!_client) { + return; + } + + // Get all existing ports + const char** const ports = jack_get_ports(_client, nullptr, nullptr, 0); + if (!ports) { + return; + } + + // Get all client names (to only send a creation event once for each) + std::unordered_set client_names; + for (auto i = 0u; ports[i]; ++i) { + client_names.insert(PortID::jack(ports[i]).client().jack_name()); + } + + // Emit all clients + for (const auto& client_name : client_names) { + sink({ClientCreationEvent{ClientID::jack(client_name), + get_client_info(client_name.c_str())}}); + } + + // Emit all ports + for (auto i = 0u; ports[i]; ++i) { + const jack_port_t* const port = jack_port_by_name(_client, ports[i]); + + sink({PortCreationEvent{PortID::jack(ports[i]), get_port_info(port)}}); + } + + // Get all connections (again to only create them once) + std::set> connections; + for (auto i = 0u; ports[i]; ++i) { + const jack_port_t* const port = jack_port_by_name(_client, ports[i]); + const char** const peers = jack_port_get_all_connections(_client, port); + + if (peers) { + if (jack_port_flags(port) & JackPortIsInput) { + for (auto j = 0u; peers[j]; ++j) { + connections.emplace(peers[j], ports[i]); + } + } else { + for (auto j = 0u; peers[j]; ++j) { + connections.emplace(ports[i], peers[j]); + } + } + + jack_free(peers); + } + } + + // Emit all connections + for (const auto& connection : connections) { + sink({ConnectionEvent{PortID::jack(connection.first), + PortID::jack(connection.second)}}); + } + + jack_free(ports); } bool JackLibDriver::connect(const PortID& tail_id, const PortID& head_id) { - if (!_client) { - return false; - } + if (!_client) { + return false; + } - const auto& tail_name = tail_id.jack_name(); - const auto& head_name = head_id.jack_name(); + const auto& tail_name = tail_id.jack_name(); + const auto& head_name = head_id.jack_name(); - const int result = - jack_connect(_client, tail_name.c_str(), head_name.c_str()); + const int result = + jack_connect(_client, tail_name.c_str(), head_name.c_str()); - if (result) { - _log.error(fmt::format( - "[JACK] Failed to connect {} => {}", tail_name, head_name)); + if (result) { + _log.error( + fmt::format("[JACK] Failed to connect {} => {}", tail_name, head_name)); - return false; - } + return false; + } - return true; + return true; } bool JackLibDriver::disconnect(const PortID& tail_id, const PortID& head_id) { - if (!_client) { - return false; - } + if (!_client) { + return false; + } - const auto& tail_name = tail_id.jack_name(); - const auto& head_name = head_id.jack_name(); + const auto& tail_name = tail_id.jack_name(); + const auto& head_name = head_id.jack_name(); - const int result = - jack_disconnect(_client, tail_name.c_str(), head_name.c_str()); + const int result = + jack_disconnect(_client, tail_name.c_str(), head_name.c_str()); - if (result) { - _log.error(fmt::format( - "[JACK] Failed to disconnect {} => {}", tail_name, head_name)); - return false; - } + if (result) { + _log.error(fmt::format( + "[JACK] Failed to disconnect {} => {}", tail_name, head_name)); + return false; + } - return true; + return true; } uint32_t JackLibDriver::xruns() { - return _xruns; + return _xruns; } void JackLibDriver::reset_xruns() { - _xruns = 0; + _xruns = 0; } uint32_t JackLibDriver::buffer_size() { - return _is_activated ? _buffer_size : jack_get_buffer_size(_client); + return _is_activated ? _buffer_size : jack_get_buffer_size(_client); } bool JackLibDriver::set_buffer_size(const uint32_t frames) { - if (!_client) { - _buffer_size = frames; - return true; - } - - if (buffer_size() == frames) { - return true; - } - - if (jack_set_buffer_size(_client, frames)) { - _log.error("[JACK] Unable to set buffer size"); - return false; - } - - _buffer_size = frames; - return true; + if (!_client) { + _buffer_size = frames; + return true; + } + + if (buffer_size() == frames) { + return true; + } + + if (jack_set_buffer_size(_client, frames)) { + _log.error("[JACK] Unable to set buffer size"); + return false; + } + + _buffer_size = frames; + return true; } uint32_t JackLibDriver::sample_rate() { - return jack_get_sample_rate(_client); + return jack_get_sample_rate(_client); } void @@ -411,13 +411,13 @@ JackLibDriver::on_client(const char* const name, const int registered, void* const driver) { - auto* const me = static_cast(driver); + auto* const me = static_cast(driver); - if (registered) { - me->_emit_event(ClientCreationEvent{ClientID::jack(name), {name}}); - } else { - me->_emit_event(ClientDestructionEvent{ClientID::jack(name)}); - } + if (registered) { + me->_emit_event(ClientCreationEvent{ClientID::jack(name), {name}}); + } else { + me->_emit_event(ClientDestructionEvent{ClientID::jack(name)}); + } } void @@ -425,17 +425,17 @@ JackLibDriver::on_port(const jack_port_id_t port_id, const int registered, void* const driver) { - auto* const me = static_cast(driver); + auto* const me = static_cast(driver); - jack_port_t* const port = jack_port_by_id(me->_client, port_id); - const char* const name = jack_port_name(port); - const auto id = PortID::jack(name); + jack_port_t* const port = jack_port_by_id(me->_client, port_id); + const char* const name = jack_port_name(port); + const auto id = PortID::jack(name); - if (registered) { - me->_emit_event(PortCreationEvent{id, me->get_port_info(port)}); - } else { - me->_emit_event(PortDestructionEvent{id}); - } + if (registered) { + me->_emit_event(PortCreationEvent{id, me->get_port_info(port)}); + } else { + me->_emit_event(PortDestructionEvent{id}); + } } void @@ -444,52 +444,52 @@ JackLibDriver::on_connection(const jack_port_id_t src, const int connect, void* const driver) { - auto* const me = static_cast(driver); - - jack_port_t* const src_port = jack_port_by_id(me->_client, src); - jack_port_t* const dst_port = jack_port_by_id(me->_client, dst); - const char* const src_name = jack_port_name(src_port); - const char* const dst_name = jack_port_name(dst_port); - - if (connect) { - me->_emit_event( - ConnectionEvent{PortID::jack(src_name), PortID::jack(dst_name)}); - } else { - me->_emit_event( - DisconnectionEvent{PortID::jack(src_name), PortID::jack(dst_name)}); - } + auto* const me = static_cast(driver); + + jack_port_t* const src_port = jack_port_by_id(me->_client, src); + jack_port_t* const dst_port = jack_port_by_id(me->_client, dst); + const char* const src_name = jack_port_name(src_port); + const char* const dst_name = jack_port_name(dst_port); + + if (connect) { + me->_emit_event( + ConnectionEvent{PortID::jack(src_name), PortID::jack(dst_name)}); + } else { + me->_emit_event( + DisconnectionEvent{PortID::jack(src_name), PortID::jack(dst_name)}); + } } int JackLibDriver::on_xrun(void* const driver) { - auto* const me = static_cast(driver); + auto* const me = static_cast(driver); - ++me->_xruns; + ++me->_xruns; - return 0; + return 0; } void JackLibDriver::on_shutdown(void* const driver) { - auto* const me = static_cast(driver); + auto* const me = static_cast(driver); - /* Note that the JACK documentation lies about this situation. It says the - client must not call jack_client_close() here... except that is exactly - what libjack does if a shutdown callback isn't registered. Despite - that, doing so here hangs forever. Handling it "properly" like a signal - handler and calling jack_client_close() in another thread also hangs. + /* Note that the JACK documentation lies about this situation. It says the + client must not call jack_client_close() here... except that is exactly + what libjack does if a shutdown callback isn't registered. Despite + that, doing so here hangs forever. Handling it "properly" like a signal + handler and calling jack_client_close() in another thread also hangs. - So, since JACK is a hot mess and it's impossible to gracefully handle - this situation, just leak the client. */ + So, since JACK is a hot mess and it's impossible to gracefully handle + this situation, just leak the client. */ - std::lock_guard lock{me->_shutdown_mutex}; + std::lock_guard lock{me->_shutdown_mutex}; - me->_client = nullptr; - me->_is_activated = false; + me->_client = nullptr; + me->_is_activated = false; - me->_emit_event(DriverDetachmentEvent{ClientType::jack}); + me->_emit_event(DriverDetachmentEvent{ClientType::jack}); } } // namespace @@ -497,8 +497,8 @@ JackLibDriver::on_shutdown(void* const driver) std::unique_ptr make_jack_driver(ILog& log, Driver::EventSink emit_event) { - return std::unique_ptr{ - new JackLibDriver{log, std::move(emit_event)}}; + return std::unique_ptr{ + new JackLibDriver{log, std::move(emit_event)}}; } } // namespace patchage diff --git a/src/Legend.cpp b/src/Legend.cpp index ff9fe4b..e8e4743 100644 --- a/src/Legend.cpp +++ b/src/Legend.cpp @@ -35,48 +35,47 @@ namespace patchage { Legend::Legend(const Configuration& configuration) { - add_button(PortType::jack_audio, - "Audio", - configuration.get_port_color(PortType::jack_audio)); + add_button(PortType::jack_audio, + "Audio", + configuration.get_port_color(PortType::jack_audio)); #ifdef HAVE_JACK_METADATA - add_button(PortType::jack_cv, - "CV", - configuration.get_port_color(PortType::jack_cv)); - add_button(PortType::jack_osc, - "OSC", - configuration.get_port_color(PortType::jack_osc)); + add_button( + PortType::jack_cv, "CV", configuration.get_port_color(PortType::jack_cv)); + add_button(PortType::jack_osc, + "OSC", + configuration.get_port_color(PortType::jack_osc)); #endif - add_button(PortType::jack_midi, - "MIDI", - configuration.get_port_color(PortType::jack_midi)); + add_button(PortType::jack_midi, + "MIDI", + configuration.get_port_color(PortType::jack_midi)); - add_button(PortType::alsa_midi, - "ALSA MIDI", - configuration.get_port_color(PortType::alsa_midi)); + add_button(PortType::alsa_midi, + "ALSA MIDI", + configuration.get_port_color(PortType::alsa_midi)); - show_all_children(); + show_all_children(); } void Legend::add_button(const PortType id, const std::string& label, uint32_t rgba) { - Gdk::Color col; - col.set_rgb(((rgba >> 24) & 0xFF) * 0x100, - ((rgba >> 16) & 0xFF) * 0x100, - ((rgba >> 8) & 0xFF) * 0x100); + Gdk::Color col; + col.set_rgb(((rgba >> 24) & 0xFF) * 0x100, + ((rgba >> 16) & 0xFF) * 0x100, + ((rgba >> 8) & 0xFF) * 0x100); - auto* box = new Gtk::HBox(); - auto* but = new Gtk::ColorButton(col); - but->set_use_alpha(false); - but->signal_color_set().connect( - sigc::bind(sigc::mem_fun(this, &Legend::on_color_set), id, label, but)); + auto* box = new Gtk::HBox(); + auto* but = new Gtk::ColorButton(col); + but->set_use_alpha(false); + but->signal_color_set().connect( + sigc::bind(sigc::mem_fun(this, &Legend::on_color_set), id, label, but)); - box->pack_end(*Gtk::manage(but)); - box->pack_end(*Gtk::manage(new Gtk::Label(label)), false, false, 2); + box->pack_end(*Gtk::manage(but)); + box->pack_end(*Gtk::manage(new Gtk::Label(label)), false, false, 2); - this->pack_start(*Gtk::manage(box), false, false, 6); + this->pack_start(*Gtk::manage(box), false, false, 6); } void @@ -84,12 +83,12 @@ Legend::on_color_set(const PortType id, const std::string& label, const Gtk::ColorButton* but) { - const Gdk::Color col = but->get_color(); - const uint32_t rgba = - (((col.get_red() / 0x100) << 24) | ((col.get_green() / 0x100) << 16) | - ((col.get_blue() / 0x100) << 8) | 0xFF); + const Gdk::Color col = but->get_color(); + const uint32_t rgba = + (((col.get_red() / 0x100) << 24) | ((col.get_green() / 0x100) << 16) | + ((col.get_blue() / 0x100) << 8) | 0xFF); - signal_color_changed.emit(id, label, rgba); + signal_color_changed.emit(id, label, rgba); } } // namespace patchage diff --git a/src/Legend.hpp b/src/Legend.hpp index ab64d2f..81fbd86 100644 --- a/src/Legend.hpp +++ b/src/Legend.hpp @@ -36,16 +36,16 @@ class Configuration; class Legend : public Gtk::HBox { public: - explicit Legend(const Configuration& configuration); + explicit Legend(const Configuration& configuration); - sigc::signal signal_color_changed; + sigc::signal signal_color_changed; private: - void add_button(PortType id, const std::string& label, uint32_t rgba); + void add_button(PortType id, const std::string& label, uint32_t rgba); - void on_color_set(PortType id, - const std::string& label, - const Gtk::ColorButton* but); + void on_color_set(PortType id, + const std::string& label, + const Gtk::ColorButton* but); }; } // namespace patchage diff --git a/src/Metadata.cpp b/src/Metadata.cpp index d1af31c..b1c2ffd 100644 --- a/src/Metadata.cpp +++ b/src/Metadata.cpp @@ -30,57 +30,57 @@ namespace patchage { boost::optional Metadata::client(const ClientID& id) { - const auto i = _client_data.find(id); - if (i == _client_data.end()) { - return {}; - } + const auto i = _client_data.find(id); + if (i == _client_data.end()) { + return {}; + } - return i->second; + return i->second; } boost::optional Metadata::port(const PortID& id) { - const auto i = _port_data.find(id); - if (i == _port_data.end()) { - return {}; - } + const auto i = _port_data.find(id); + if (i == _port_data.end()) { + return {}; + } - return i->second; + return i->second; } void Metadata::set_client(const ClientID& id, const ClientInfo& info) { - const auto i = _client_data.find(id); - if (i == _client_data.end()) { - _client_data.emplace(id, info); - } else { - i->second = info; - } + const auto i = _client_data.find(id); + if (i == _client_data.end()) { + _client_data.emplace(id, info); + } else { + i->second = info; + } } void Metadata::set_port(const PortID& id, const PortInfo& info) { - const auto i = _port_data.find(id); - if (i == _port_data.end()) { - _port_data.emplace(id, info); - } else { - i->second = info; - } + const auto i = _port_data.find(id); + if (i == _port_data.end()) { + _port_data.emplace(id, info); + } else { + i->second = info; + } } void Metadata::erase_client(const ClientID& id) { - _client_data.erase(id); + _client_data.erase(id); } void Metadata::erase_port(const PortID& id) { - _port_data.erase(id); + _port_data.erase(id); } } // namespace patchage diff --git a/src/Metadata.hpp b/src/Metadata.hpp index 717971d..7da86d8 100644 --- a/src/Metadata.hpp +++ b/src/Metadata.hpp @@ -32,23 +32,23 @@ namespace patchage { class Metadata { public: - Metadata() = default; + Metadata() = default; - boost::optional client(const ClientID& id); - boost::optional port(const PortID& id); + boost::optional client(const ClientID& id); + boost::optional port(const PortID& id); - void set_client(const ClientID& id, const ClientInfo& info); - void set_port(const PortID& id, const PortInfo& info); + void set_client(const ClientID& id, const ClientInfo& info); + void set_port(const PortID& id, const PortInfo& info); - void erase_client(const ClientID& id); - void erase_port(const PortID& id); + void erase_client(const ClientID& id); + void erase_port(const PortID& id); private: - using ClientData = std::map; - using PortData = std::map; + using ClientData = std::map; + using PortData = std::map; - ClientData _client_data; - PortData _port_data; + ClientData _client_data; + PortData _port_data; }; } // namespace patchage diff --git a/src/Options.hpp b/src/Options.hpp index 86853e5..dd143fe 100644 --- a/src/Options.hpp +++ b/src/Options.hpp @@ -19,10 +19,9 @@ namespace patchage { -struct Options -{ - bool alsa_driver_autoattach = true; - bool jack_driver_autoattach = true; +struct Options { + bool alsa_driver_autoattach = true; + bool jack_driver_autoattach = true; }; } // namespace patchage diff --git a/src/Patchage.cpp b/src/Patchage.cpp index 7207567..7b33e4a 100644 --- a/src/Patchage.cpp +++ b/src/Patchage.cpp @@ -101,23 +101,23 @@ PATCHAGE_RESTORE_WARNINGS #ifdef PATCHAGE_GTK_OSX -# include -# include +# include +# include namespace { gboolean can_activate_cb(GtkWidget* widget, guint, gpointer) { - return gtk_widget_is_sensitive(widget); + return gtk_widget_is_sensitive(widget); } void terminate_cb(GtkosxApplication*, gpointer data) { - auto* patchage = static_cast(data); - patchage->save(); - Gtk::Main::quit(); + auto* patchage = static_cast(data); + patchage->save(); + Gtk::Main::quit(); } } // namespace @@ -131,43 +131,43 @@ namespace { bool configure_cb(GtkWindow*, GdkEvent*, gpointer data) { - static_cast(data)->store_window_location(); - return FALSE; + static_cast(data)->store_window_location(); + return FALSE; } int port_order(const GanvPort* a, const GanvPort* b, void*) { - const auto* pa = dynamic_cast(Glib::wrap(a)); - const auto* pb = dynamic_cast(Glib::wrap(b)); - if (pa && pb) { - if (pa->order() && pb->order()) { - return *pa->order() - *pb->order(); - } + const auto* pa = dynamic_cast(Glib::wrap(a)); + const auto* pb = dynamic_cast(Glib::wrap(b)); + if (pa && pb) { + if (pa->order() && pb->order()) { + return *pa->order() - *pb->order(); + } - if (pa->order()) { - return -1; - } + if (pa->order()) { + return -1; + } - if (pb->order()) { - return 1; - } + if (pb->order()) { + return 1; + } - return pa->name().compare(pb->name()); - } - return 0; + return pa->name().compare(pb->name()); + } + return 0; } void load_module_location(GanvNode* node, void*) { - if (GANV_IS_MODULE(node)) { - Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); - auto* pmod = dynamic_cast(gmod); - if (pmod) { - pmod->load_location(); - } - } + if (GANV_IS_MODULE(node)) { + Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); + auto* pmod = dynamic_cast(gmod); + if (pmod) { + pmod->load_location(); + } + } } } // namespace @@ -175,755 +175,748 @@ load_module_location(GanvNode* node, void*) #define INIT_WIDGET(x) x(_xml, (#x) + 1) Patchage::Patchage(Options options) - : _xml(UIFile::open("patchage")) - , _gtk_main(nullptr) - , INIT_WIDGET(_about_win) - , INIT_WIDGET(_main_scrolledwin) - , INIT_WIDGET(_main_win) - , INIT_WIDGET(_main_vbox) - , INIT_WIDGET(_menubar) - , INIT_WIDGET(_menu_alsa_connect) - , INIT_WIDGET(_menu_alsa_disconnect) - , INIT_WIDGET(_menu_file_quit) - , INIT_WIDGET(_menu_export_image) - , INIT_WIDGET(_menu_help_about) - , INIT_WIDGET(_menu_jack_connect) - , INIT_WIDGET(_menu_jack_disconnect) - , INIT_WIDGET(_menu_view_arrange) - , INIT_WIDGET(_menu_view_sprung_layout) - , INIT_WIDGET(_menu_view_messages) - , INIT_WIDGET(_menu_view_toolbar) - , INIT_WIDGET(_menu_view_refresh) - , INIT_WIDGET(_menu_view_human_names) - , INIT_WIDGET(_menu_view_sort_ports) - , INIT_WIDGET(_menu_zoom_in) - , INIT_WIDGET(_menu_zoom_out) - , INIT_WIDGET(_menu_zoom_normal) - , INIT_WIDGET(_menu_zoom_full) - , INIT_WIDGET(_menu_increase_font_size) - , INIT_WIDGET(_menu_decrease_font_size) - , INIT_WIDGET(_menu_normal_font_size) - , INIT_WIDGET(_toolbar) - , INIT_WIDGET(_clear_load_but) - , INIT_WIDGET(_dropouts_label) - , INIT_WIDGET(_buf_size_combo) - , INIT_WIDGET(_latency_label) - , INIT_WIDGET(_legend_alignment) - , INIT_WIDGET(_main_paned) - , INIT_WIDGET(_log_scrolledwindow) - , INIT_WIDGET(_status_text) - , _legend(nullptr) - , _log(_status_text) - , _connector(_log) - , _options{options} - , _pane_initialized(false) - , _attach(true) -{ - _canvas = - std::unique_ptr{new Canvas(_connector, 1600 * 2, 1200 * 2)}; - - Glib::set_application_name("Patchage"); - _about_win->property_program_name() = "Patchage"; - _about_win->property_logo_icon_name() = "patchage"; - gtk_window_set_default_icon_name("patchage"); - - // Create list model for buffer size selector - Glib::RefPtr buf_size_store = - Gtk::ListStore::create(_buf_size_columns); - for (size_t i = 32; i <= 4096; i *= 2) { - Gtk::TreeModel::Row row = *(buf_size_store->append()); - row[_buf_size_columns.label] = std::to_string(i); - } - - _buf_size_combo->set_model(buf_size_store); - _buf_size_combo->pack_start(_buf_size_columns.label); - - _main_scrolledwin->add(_canvas->widget()); - - _main_scrolledwin->property_hadjustment().get_value()->set_step_increment( - 10); - _main_scrolledwin->property_vadjustment().get_value()->set_step_increment( - 10); - - _main_scrolledwin->signal_scroll_event().connect( - sigc::mem_fun(this, &Patchage::on_scroll)); - _clear_load_but->signal_clicked().connect( - sigc::mem_fun(this, &Patchage::clear_load)); - _buf_size_combo->signal_changed().connect( - sigc::mem_fun(this, &Patchage::buffer_size_changed)); - _status_text->signal_size_allocate().connect( - sigc::mem_fun(this, &Patchage::on_messages_resized)); - - _menu_file_quit->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_quit)); - _menu_export_image->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_export_image)); - _menu_view_refresh->signal_activate().connect( - sigc::mem_fun(this, &Patchage::refresh)); - _menu_view_human_names->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_human_names)); - _menu_view_sort_ports->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_sort_ports)); - _menu_view_arrange->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_arrange)); - _menu_view_sprung_layout->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_sprung_layout_toggled)); - _menu_view_messages->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_messages)); - _menu_view_toolbar->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_view_toolbar)); - _menu_help_about->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_help_about)); - _menu_zoom_in->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_zoom_in)); - _menu_zoom_out->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_zoom_out)); - _menu_zoom_normal->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_zoom_normal)); - _menu_zoom_full->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_zoom_full)); - _menu_increase_font_size->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_increase_font_size)); - _menu_decrease_font_size->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_decrease_font_size)); - _menu_normal_font_size->signal_activate().connect( - sigc::mem_fun(this, &Patchage::on_normal_font_size)); - - if (_canvas->supports_sprung_layout()) { - _menu_view_sprung_layout->set_active(true); - } else { - _menu_view_sprung_layout->set_active(false); - _menu_view_sprung_layout->set_sensitive(false); - } - - _canvas->widget().show(); - _main_win->present(); - - _conf.set_font_size(_canvas->get_default_font_size()); - _conf.load(); - _canvas->set_zoom(_conf.get_zoom()); - _canvas->set_font_size(_conf.get_font_size()); - if (_conf.get_sort_ports()) { - _canvas->set_port_order(port_order, nullptr); - } - - _main_win->resize(static_cast(_conf.get_window_size().x), - static_cast(_conf.get_window_size().y)); - - _main_win->move(static_cast(_conf.get_window_location().x), - static_cast(_conf.get_window_location().y)); - - _legend = new Legend(_conf); - _legend->signal_color_changed.connect( - sigc::mem_fun(this, &Patchage::on_legend_color_change)); - _legend_alignment->add(*Gtk::manage(_legend)); - _legend->show_all(); - - _about_win->set_transient_for(*_main_win); + : _xml(UIFile::open("patchage")) + , _gtk_main(nullptr) + , INIT_WIDGET(_about_win) + , INIT_WIDGET(_main_scrolledwin) + , INIT_WIDGET(_main_win) + , INIT_WIDGET(_main_vbox) + , INIT_WIDGET(_menubar) + , INIT_WIDGET(_menu_alsa_connect) + , INIT_WIDGET(_menu_alsa_disconnect) + , INIT_WIDGET(_menu_file_quit) + , INIT_WIDGET(_menu_export_image) + , INIT_WIDGET(_menu_help_about) + , INIT_WIDGET(_menu_jack_connect) + , INIT_WIDGET(_menu_jack_disconnect) + , INIT_WIDGET(_menu_view_arrange) + , INIT_WIDGET(_menu_view_sprung_layout) + , INIT_WIDGET(_menu_view_messages) + , INIT_WIDGET(_menu_view_toolbar) + , INIT_WIDGET(_menu_view_refresh) + , INIT_WIDGET(_menu_view_human_names) + , INIT_WIDGET(_menu_view_sort_ports) + , INIT_WIDGET(_menu_zoom_in) + , INIT_WIDGET(_menu_zoom_out) + , INIT_WIDGET(_menu_zoom_normal) + , INIT_WIDGET(_menu_zoom_full) + , INIT_WIDGET(_menu_increase_font_size) + , INIT_WIDGET(_menu_decrease_font_size) + , INIT_WIDGET(_menu_normal_font_size) + , INIT_WIDGET(_toolbar) + , INIT_WIDGET(_clear_load_but) + , INIT_WIDGET(_dropouts_label) + , INIT_WIDGET(_buf_size_combo) + , INIT_WIDGET(_latency_label) + , INIT_WIDGET(_legend_alignment) + , INIT_WIDGET(_main_paned) + , INIT_WIDGET(_log_scrolledwindow) + , INIT_WIDGET(_status_text) + , _legend(nullptr) + , _log(_status_text) + , _connector(_log) + , _options{options} + , _pane_initialized(false) + , _attach(true) +{ + _canvas = std::unique_ptr{new Canvas(_connector, 1600 * 2, 1200 * 2)}; + + Glib::set_application_name("Patchage"); + _about_win->property_program_name() = "Patchage"; + _about_win->property_logo_icon_name() = "patchage"; + gtk_window_set_default_icon_name("patchage"); + + // Create list model for buffer size selector + Glib::RefPtr buf_size_store = + Gtk::ListStore::create(_buf_size_columns); + for (size_t i = 32; i <= 4096; i *= 2) { + Gtk::TreeModel::Row row = *(buf_size_store->append()); + row[_buf_size_columns.label] = std::to_string(i); + } + + _buf_size_combo->set_model(buf_size_store); + _buf_size_combo->pack_start(_buf_size_columns.label); + + _main_scrolledwin->add(_canvas->widget()); + + _main_scrolledwin->property_hadjustment().get_value()->set_step_increment(10); + _main_scrolledwin->property_vadjustment().get_value()->set_step_increment(10); + + _main_scrolledwin->signal_scroll_event().connect( + sigc::mem_fun(this, &Patchage::on_scroll)); + _clear_load_but->signal_clicked().connect( + sigc::mem_fun(this, &Patchage::clear_load)); + _buf_size_combo->signal_changed().connect( + sigc::mem_fun(this, &Patchage::buffer_size_changed)); + _status_text->signal_size_allocate().connect( + sigc::mem_fun(this, &Patchage::on_messages_resized)); + + _menu_file_quit->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_quit)); + _menu_export_image->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_export_image)); + _menu_view_refresh->signal_activate().connect( + sigc::mem_fun(this, &Patchage::refresh)); + _menu_view_human_names->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_view_human_names)); + _menu_view_sort_ports->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_view_sort_ports)); + _menu_view_arrange->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_arrange)); + _menu_view_sprung_layout->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_sprung_layout_toggled)); + _menu_view_messages->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_view_messages)); + _menu_view_toolbar->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_view_toolbar)); + _menu_help_about->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_help_about)); + _menu_zoom_in->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_zoom_in)); + _menu_zoom_out->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_zoom_out)); + _menu_zoom_normal->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_zoom_normal)); + _menu_zoom_full->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_zoom_full)); + _menu_increase_font_size->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_increase_font_size)); + _menu_decrease_font_size->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_decrease_font_size)); + _menu_normal_font_size->signal_activate().connect( + sigc::mem_fun(this, &Patchage::on_normal_font_size)); + + if (_canvas->supports_sprung_layout()) { + _menu_view_sprung_layout->set_active(true); + } else { + _menu_view_sprung_layout->set_active(false); + _menu_view_sprung_layout->set_sensitive(false); + } + + _canvas->widget().show(); + _main_win->present(); + + _conf.set_font_size(_canvas->get_default_font_size()); + _conf.load(); + _canvas->set_zoom(_conf.get_zoom()); + _canvas->set_font_size(_conf.get_font_size()); + if (_conf.get_sort_ports()) { + _canvas->set_port_order(port_order, nullptr); + } + + _main_win->resize(static_cast(_conf.get_window_size().x), + static_cast(_conf.get_window_size().y)); + + _main_win->move(static_cast(_conf.get_window_location().x), + static_cast(_conf.get_window_location().y)); + + _legend = new Legend(_conf); + _legend->signal_color_changed.connect( + sigc::mem_fun(this, &Patchage::on_legend_color_change)); + _legend_alignment->add(*Gtk::manage(_legend)); + _legend->show_all(); + + _about_win->set_transient_for(*_main_win); #ifdef __APPLE__ - try { - _about_win->set_logo(Gdk::Pixbuf::create_from_file( - bundle_location() + "/Resources/Patchage.icns")); - } catch (const Glib::Exception& e) { - _log.error( - fmt::format("Failed to set logo ({})", std::string(e.what()))); - } + try { + _about_win->set_logo(Gdk::Pixbuf::create_from_file( + bundle_location() + "/Resources/Patchage.icns")); + } catch (const Glib::Exception& e) { + _log.error(fmt::format("Failed to set logo ({})", std::string(e.what()))); + } #endif - // Make Jack driver if possible - _jack_driver = make_jack_driver( - _log, [this](const Event& event) { on_driver_event(event); }); + // Make Jack driver if possible + _jack_driver = make_jack_driver( + _log, [this](const Event& event) { on_driver_event(event); }); - if (_jack_driver) { - _connector.add_driver(PortID::Type::jack, _jack_driver.get()); + if (_jack_driver) { + _connector.add_driver(PortID::Type::jack, _jack_driver.get()); - _menu_jack_connect->signal_activate().connect(sigc::bind( - sigc::mem_fun(_jack_driver.get(), &AudioDriver::attach), true)); - _menu_jack_disconnect->signal_activate().connect( - sigc::mem_fun(_jack_driver.get(), &AudioDriver::detach)); - } else { - _menu_jack_connect->set_sensitive(false); - _menu_jack_disconnect->set_sensitive(false); - } + _menu_jack_connect->signal_activate().connect(sigc::bind( + sigc::mem_fun(_jack_driver.get(), &AudioDriver::attach), true)); + _menu_jack_disconnect->signal_activate().connect( + sigc::mem_fun(_jack_driver.get(), &AudioDriver::detach)); + } else { + _menu_jack_connect->set_sensitive(false); + _menu_jack_disconnect->set_sensitive(false); + } - // Make ALSA driver if possible - _alsa_driver = make_alsa_driver( - _log, [this](const Event& event) { on_driver_event(event); }); + // Make ALSA driver if possible + _alsa_driver = make_alsa_driver( + _log, [this](const Event& event) { on_driver_event(event); }); - if (_alsa_driver) { - _connector.add_driver(PortID::Type::alsa, _alsa_driver.get()); + if (_alsa_driver) { + _connector.add_driver(PortID::Type::alsa, _alsa_driver.get()); - _menu_alsa_connect->signal_activate().connect(sigc::bind( - sigc::mem_fun(_alsa_driver.get(), &Driver::attach), false)); - _menu_alsa_disconnect->signal_activate().connect( - sigc::mem_fun(_alsa_driver.get(), &Driver::detach)); + _menu_alsa_connect->signal_activate().connect( + sigc::bind(sigc::mem_fun(_alsa_driver.get(), &Driver::attach), false)); + _menu_alsa_disconnect->signal_activate().connect( + sigc::mem_fun(_alsa_driver.get(), &Driver::detach)); - } else { - _menu_alsa_connect->set_sensitive(false); - _menu_alsa_disconnect->set_sensitive(false); - } + } else { + _menu_alsa_connect->set_sensitive(false); + _menu_alsa_disconnect->set_sensitive(false); + } - _canvas->for_each_node(load_module_location, nullptr); + _canvas->for_each_node(load_module_location, nullptr); - _menu_view_toolbar->set_active(_conf.get_show_toolbar()); - _menu_view_sprung_layout->set_active(_conf.get_sprung_layout()); - _menu_view_sort_ports->set_active(_conf.get_sort_ports()); + _menu_view_toolbar->set_active(_conf.get_show_toolbar()); + _menu_view_sprung_layout->set_active(_conf.get_sprung_layout()); + _menu_view_sort_ports->set_active(_conf.get_sort_ports()); - g_signal_connect( - _main_win->gobj(), "configure-event", G_CALLBACK(configure_cb), this); + g_signal_connect( + _main_win->gobj(), "configure-event", G_CALLBACK(configure_cb), this); - _canvas->widget().grab_focus(); + _canvas->widget().grab_focus(); - // Idle callback, check if we need to refresh - Glib::signal_timeout().connect( - sigc::mem_fun(this, &Patchage::idle_callback), 100); + // Idle callback, check if we need to refresh + Glib::signal_timeout().connect(sigc::mem_fun(this, &Patchage::idle_callback), + 100); #ifdef PATCHAGE_GTK_OSX - // Set up Mac menu bar - GtkosxApplication* osxapp = static_cast( - g_object_new(GTKOSX_TYPE_APPLICATION, nullptr)); - - _menubar->hide(); - _menu_file_quit->hide(); - gtkosx_application_set_menu_bar(osxapp, GTK_MENU_SHELL(_menubar->gobj())); - gtkosx_application_insert_app_menu_item( - osxapp, GTK_WIDGET(_menu_help_about->gobj()), 0); - g_signal_connect(_menubar->gobj(), - "can-activate-accel", - G_CALLBACK(can_activate_cb), - nullptr); - g_signal_connect( - osxapp, "NSApplicationWillTerminate", G_CALLBACK(terminate_cb), this); - gtkosx_application_ready(osxapp); + // Set up Mac menu bar + GtkosxApplication* osxapp = static_cast( + g_object_new(GTKOSX_TYPE_APPLICATION, nullptr)); + + _menubar->hide(); + _menu_file_quit->hide(); + gtkosx_application_set_menu_bar(osxapp, GTK_MENU_SHELL(_menubar->gobj())); + gtkosx_application_insert_app_menu_item( + osxapp, GTK_WIDGET(_menu_help_about->gobj()), 0); + g_signal_connect(_menubar->gobj(), + "can-activate-accel", + G_CALLBACK(can_activate_cb), + nullptr); + g_signal_connect( + osxapp, "NSApplicationWillTerminate", G_CALLBACK(terminate_cb), this); + gtkosx_application_ready(osxapp); #endif } Patchage::~Patchage() { - _jack_driver.reset(); - _alsa_driver.reset(); - _about_win.destroy(); - _xml.reset(); + _jack_driver.reset(); + _alsa_driver.reset(); + _about_win.destroy(); + _xml.reset(); } void Patchage::attach() { - if (_jack_driver && _options.jack_driver_autoattach) { - _jack_driver->attach(true); - } + if (_jack_driver && _options.jack_driver_autoattach) { + _jack_driver->attach(true); + } - if (_alsa_driver && _options.alsa_driver_autoattach) { - _alsa_driver->attach(false); - } + if (_alsa_driver && _options.alsa_driver_autoattach) { + _alsa_driver->attach(false); + } - process_events(); - refresh(); - update_toolbar(); + process_events(); + refresh(); + update_toolbar(); } bool Patchage::idle_callback() { - // Initial run, attach - if (_attach) { - attach(); - _menu_view_messages->set_active(_conf.get_show_messages()); - _attach = false; - } + // Initial run, attach + if (_attach) { + attach(); + _menu_view_messages->set_active(_conf.get_show_messages()); + _attach = false; + } - // Process any events from drivers - process_events(); + // Process any events from drivers + process_events(); - // Update load every 5 idle callbacks - static int count = 0; - if (++count == 5) { - update_load(); - count = 0; - } + // Update load every 5 idle callbacks + static int count = 0; + if (++count == 5) { + update_load(); + count = 0; + } - return true; + return true; } void Patchage::update_toolbar() { - static bool updating = false; - if (updating) { - return; - } + static bool updating = false; + if (updating) { + return; + } - updating = true; + updating = true; - if (_jack_driver && _jack_driver->is_attached()) { - const auto buffer_size = _jack_driver->buffer_size(); - const auto sample_rate = _jack_driver->sample_rate(); - if (sample_rate != 0) { - const auto latency_ms = - lrintf(buffer_size * 1000 / float(sample_rate)); + if (_jack_driver && _jack_driver->is_attached()) { + const auto buffer_size = _jack_driver->buffer_size(); + const auto sample_rate = _jack_driver->sample_rate(); + if (sample_rate != 0) { + const auto latency_ms = lrintf(buffer_size * 1000 / float(sample_rate)); - _latency_label->set_label(fmt::format( - " frames @ {} kHz ({} ms)", sample_rate / 1000, latency_ms)); - _latency_label->set_visible(true); - _buf_size_combo->set_active( - static_cast(log2f(_jack_driver->buffer_size()) - 5)); - updating = false; - return; - } - } + _latency_label->set_label(fmt::format( + " frames @ {} kHz ({} ms)", sample_rate / 1000, latency_ms)); + _latency_label->set_visible(true); + _buf_size_combo->set_active( + static_cast(log2f(_jack_driver->buffer_size()) - 5)); + updating = false; + return; + } + } - _latency_label->set_visible(false); - updating = false; + _latency_label->set_visible(false); + updating = false; } bool Patchage::update_load() { - if (_jack_driver && _jack_driver->is_attached()) { - const auto xruns = _jack_driver->xruns(); - if (xruns > 0u) { - _dropouts_label->set_text(fmt::format(" Dropouts: {}", xruns)); - _dropouts_label->show(); - _clear_load_but->show(); - } else { - _dropouts_label->set_text(" Dropouts: 0"); - _dropouts_label->hide(); - _clear_load_but->hide(); - } - } + if (_jack_driver && _jack_driver->is_attached()) { + const auto xruns = _jack_driver->xruns(); + if (xruns > 0u) { + _dropouts_label->set_text(fmt::format(" Dropouts: {}", xruns)); + _dropouts_label->show(); + _clear_load_but->show(); + } else { + _dropouts_label->set_text(" Dropouts: 0"); + _dropouts_label->hide(); + _clear_load_but->hide(); + } + } - return true; + return true; } void Patchage::refresh() { - auto sink = [this](const Event& event) { - _log.info("Refresh: " + event_to_string(event)); - handle_event(*this, event); - }; + auto sink = [this](const Event& event) { + _log.info("Refresh: " + event_to_string(event)); + handle_event(*this, event); + }; - if (_canvas) { - _canvas->clear(); + if (_canvas) { + _canvas->clear(); - if (_jack_driver) { - _jack_driver->refresh(sink); - } + if (_jack_driver) { + _jack_driver->refresh(sink); + } - if (_alsa_driver) { - _alsa_driver->refresh(sink); - } - } + if (_alsa_driver) { + _alsa_driver->refresh(sink); + } + } } void Patchage::driver_attached(const ClientType type) { - switch (type) { - case ClientType::jack: - _menu_jack_connect->set_sensitive(false); - _menu_jack_disconnect->set_sensitive(true); + switch (type) { + case ClientType::jack: + _menu_jack_connect->set_sensitive(false); + _menu_jack_disconnect->set_sensitive(true); - if (_jack_driver) { - _jack_driver->refresh( - [this](const Event& event) { handle_event(*this, event); }); - } + if (_jack_driver) { + _jack_driver->refresh( + [this](const Event& event) { handle_event(*this, event); }); + } - break; - case ClientType::alsa: - _menu_alsa_connect->set_sensitive(false); - _menu_alsa_disconnect->set_sensitive(true); + break; + case ClientType::alsa: + _menu_alsa_connect->set_sensitive(false); + _menu_alsa_disconnect->set_sensitive(true); - if (_alsa_driver) { - _alsa_driver->refresh( - [this](const Event& event) { handle_event(*this, event); }); - } + if (_alsa_driver) { + _alsa_driver->refresh( + [this](const Event& event) { handle_event(*this, event); }); + } - break; - } + break; + } } void Patchage::driver_detached(const ClientType type) { - switch (type) { - case ClientType::jack: - _menu_jack_connect->set_sensitive(true); - _menu_jack_disconnect->set_sensitive(false); + switch (type) { + case ClientType::jack: + _menu_jack_connect->set_sensitive(true); + _menu_jack_disconnect->set_sensitive(false); - _canvas->remove_ports([](const CanvasPort* port) { - return (port->type() == PortType::jack_audio || - port->type() == PortType::jack_midi || - port->type() == PortType::jack_osc || - port->type() == PortType::jack_cv); - }); + _canvas->remove_ports([](const CanvasPort* port) { + return (port->type() == PortType::jack_audio || + port->type() == PortType::jack_midi || + port->type() == PortType::jack_osc || + port->type() == PortType::jack_cv); + }); - break; + break; - case ClientType::alsa: - _menu_alsa_connect->set_sensitive(true); - _menu_alsa_disconnect->set_sensitive(false); + case ClientType::alsa: + _menu_alsa_connect->set_sensitive(true); + _menu_alsa_disconnect->set_sensitive(false); - _canvas->remove_ports([](const CanvasPort* port) { - return port->type() == PortType::alsa_midi; - }); + _canvas->remove_ports([](const CanvasPort* port) { + return port->type() == PortType::alsa_midi; + }); - break; - } + break; + } } void Patchage::store_window_location() { - int loc_x = 0; - int loc_y = 0; - _main_win->get_position(loc_x, loc_y); + int loc_x = 0; + int loc_y = 0; + _main_win->get_position(loc_x, loc_y); - int size_x = 0; - int size_y = 0; - _main_win->get_size(size_x, size_y); + int size_x = 0; + int size_y = 0; + _main_win->get_size(size_x, size_y); - _conf.set_window_location({double(loc_x), double(loc_y)}); - _conf.set_window_size({double(size_x), double(size_y)}); + _conf.set_window_location({double(loc_x), double(loc_y)}); + _conf.set_window_size({double(size_x), double(size_y)}); } void Patchage::clear_load() { - _dropouts_label->set_text(" Dropouts: 0"); - _dropouts_label->hide(); - _clear_load_but->hide(); - if (_jack_driver) { - _jack_driver->reset_xruns(); - } + _dropouts_label->set_text(" Dropouts: 0"); + _dropouts_label->hide(); + _clear_load_but->hide(); + if (_jack_driver) { + _jack_driver->reset_xruns(); + } } void Patchage::on_driver_event(const Event& event) { - std::lock_guard lock{_events_mutex}; + std::lock_guard lock{_events_mutex}; - _driver_events.emplace(event); + _driver_events.emplace(event); } void Patchage::process_events() { - std::lock_guard lock{_events_mutex}; + std::lock_guard lock{_events_mutex}; - while (!_driver_events.empty()) { - _log.info(event_to_string(_driver_events.front())); - handle_event(*this, _driver_events.front()); - _driver_events.pop(); - } + while (!_driver_events.empty()) { + _log.info(event_to_string(_driver_events.front())); + handle_event(*this, _driver_events.front()); + _driver_events.pop(); + } } void Patchage::on_arrange() { - if (_canvas) { - _canvas->arrange(); - } + if (_canvas) { + _canvas->arrange(); + } } void Patchage::on_sprung_layout_toggled() { - const bool sprung = _menu_view_sprung_layout->get_active(); + const bool sprung = _menu_view_sprung_layout->get_active(); - _canvas->set_sprung_layout(sprung); - _conf.set_sprung_layout(sprung); + _canvas->set_sprung_layout(sprung); + _conf.set_sprung_layout(sprung); } void Patchage::on_help_about() { - _about_win->run(); - _about_win->hide(); + _about_win->run(); + _about_win->hide(); } static void update_labels(GanvNode* node, void* data) { - const bool human_names = *static_cast(data); - if (GANV_IS_MODULE(node)) { - Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); - auto* pmod = dynamic_cast(gmod); - if (pmod) { - for (Ganv::Port* gport : *gmod) { - auto* pport = dynamic_cast(gport); - if (pport) { - pport->show_human_name(human_names); - } - } - } - } + const bool human_names = *static_cast(data); + if (GANV_IS_MODULE(node)) { + Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); + auto* pmod = dynamic_cast(gmod); + if (pmod) { + for (Ganv::Port* gport : *gmod) { + auto* pport = dynamic_cast(gport); + if (pport) { + pport->show_human_name(human_names); + } + } + } + } } void Patchage::on_view_human_names() { - bool human_names = show_human_names(); - _canvas->for_each_node(update_labels, &human_names); + bool human_names = show_human_names(); + _canvas->for_each_node(update_labels, &human_names); } void Patchage::on_view_sort_ports() { - const bool sort_ports = this->sort_ports(); - _canvas->set_port_order(sort_ports ? port_order : nullptr, nullptr); - _conf.set_sort_ports(sort_ports); - refresh(); + const bool sort_ports = this->sort_ports(); + _canvas->set_port_order(sort_ports ? port_order : nullptr, nullptr); + _conf.set_sort_ports(sort_ports); + refresh(); } void Patchage::on_zoom_in() { - const float zoom = _canvas->get_zoom() * 1.25; - _canvas->set_zoom(zoom); - _conf.set_zoom(zoom); + const float zoom = _canvas->get_zoom() * 1.25; + _canvas->set_zoom(zoom); + _conf.set_zoom(zoom); } void Patchage::on_zoom_out() { - const float zoom = _canvas->get_zoom() * 0.75; - _canvas->set_zoom(zoom); - _conf.set_zoom(zoom); + const float zoom = _canvas->get_zoom() * 0.75; + _canvas->set_zoom(zoom); + _conf.set_zoom(zoom); } void Patchage::on_zoom_normal() { - _canvas->set_zoom(1.0); - _conf.set_zoom(1.0); + _canvas->set_zoom(1.0); + _conf.set_zoom(1.0); } void Patchage::on_zoom_full() { - _canvas->zoom_full(); - _conf.set_zoom(_canvas->get_zoom()); + _canvas->zoom_full(); + _conf.set_zoom(_canvas->get_zoom()); } void Patchage::on_increase_font_size() { - const float points = _canvas->get_font_size() + 1.0; - _canvas->set_font_size(points); - _conf.set_font_size(points); + const float points = _canvas->get_font_size() + 1.0; + _canvas->set_font_size(points); + _conf.set_font_size(points); } void Patchage::on_decrease_font_size() { - const float points = _canvas->get_font_size() - 1.0; - _canvas->set_font_size(points); - _conf.set_font_size(points); + const float points = _canvas->get_font_size() - 1.0; + _canvas->set_font_size(points); + _conf.set_font_size(points); } void Patchage::on_normal_font_size() { - _canvas->set_font_size(_canvas->get_default_font_size()); - _conf.set_font_size(_canvas->get_default_font_size()); + _canvas->set_font_size(_canvas->get_default_font_size()); + _conf.set_font_size(_canvas->get_default_font_size()); } static inline guint highlight_color(guint c, guint delta) { - const guint max_char = 255; - const guint r = MIN((c >> 24) + delta, max_char); - const guint g = MIN(((c >> 16) & 0xFF) + delta, max_char); - const guint b = MIN(((c >> 8) & 0xFF) + delta, max_char); - const guint a = c & 0xFF; + const guint max_char = 255; + const guint r = MIN((c >> 24) + delta, max_char); + const guint g = MIN(((c >> 16) & 0xFF) + delta, max_char); + const guint b = MIN(((c >> 8) & 0xFF) + delta, max_char); + const guint a = c & 0xFF; - return ((r << 24u) | (g << 16u) | (b << 8u) | a); + return ((r << 24u) | (g << 16u) | (b << 8u) | a); } static void update_port_colors(GanvNode* node, void* data) { - auto* patchage = static_cast(data); - if (!GANV_IS_MODULE(node)) { - return; - } + auto* patchage = static_cast(data); + if (!GANV_IS_MODULE(node)) { + return; + } - Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); - auto* pmod = dynamic_cast(gmod); - if (!pmod) { - return; - } + Ganv::Module* gmod = Glib::wrap(GANV_MODULE(node)); + auto* pmod = dynamic_cast(gmod); + if (!pmod) { + return; + } - for (Ganv::Port* p : *pmod) { - auto* port = dynamic_cast(p); - if (port) { - const uint32_t rgba = patchage->conf().get_port_color(port->type()); - port->set_fill_color(rgba); - port->set_border_color(highlight_color(rgba, 0x20)); - } - } + for (Ganv::Port* p : *pmod) { + auto* port = dynamic_cast(p); + if (port) { + const uint32_t rgba = patchage->conf().get_port_color(port->type()); + port->set_fill_color(rgba); + port->set_border_color(highlight_color(rgba, 0x20)); + } + } } static void update_edge_color(GanvEdge* edge, void* data) { - auto* patchage = static_cast(data); - Ganv::Edge* edgemm = Glib::wrap(edge); + auto* patchage = static_cast(data); + Ganv::Edge* edgemm = Glib::wrap(edge); - auto* tail = dynamic_cast((edgemm)->get_tail()); - if (tail) { - edgemm->set_color(patchage->conf().get_port_color(tail->type())); - } + auto* tail = dynamic_cast((edgemm)->get_tail()); + if (tail) { + edgemm->set_color(patchage->conf().get_port_color(tail->type())); + } } void Patchage::on_legend_color_change(PortType id, const std::string&, uint32_t rgba) { - _conf.set_port_color(id, rgba); - _canvas->for_each_node(update_port_colors, this); - _canvas->for_each_edge(update_edge_color, this); + _conf.set_port_color(id, rgba); + _canvas->for_each_node(update_port_colors, this); + _canvas->for_each_edge(update_edge_color, this); } void Patchage::on_messages_resized(Gtk::Allocation&) { - const int max_pos = _main_paned->get_allocation().get_height(); - _conf.set_messages_height(max_pos - _main_paned->get_position()); + const int max_pos = _main_paned->get_allocation().get_height(); + _conf.set_messages_height(max_pos - _main_paned->get_position()); } void Patchage::save() { - _conf.set_zoom(_canvas->get_zoom()); // Can be changed by ganv - _conf.save(); + _conf.set_zoom(_canvas->get_zoom()); // Can be changed by ganv + _conf.save(); } void Patchage::quit() { - _main_win->hide(); + _main_win->hide(); } void Patchage::on_quit() { - if (_alsa_driver) { - _alsa_driver->detach(); - } + if (_alsa_driver) { + _alsa_driver->detach(); + } - if (_jack_driver) { - _jack_driver->detach(); - } + if (_jack_driver) { + _jack_driver->detach(); + } - _main_win->hide(); + _main_win->hide(); } void Patchage::on_export_image() { - Gtk::FileChooserDialog dialog("Export Image", - Gtk::FILE_CHOOSER_ACTION_SAVE); - dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); - dialog.set_default_response(Gtk::RESPONSE_OK); - dialog.set_transient_for(*_main_win); - - using Types = std::map; - - Types types; - types["*.dot"] = "Graphviz DOT"; - types["*.pdf"] = "Portable Document Format"; - types["*.ps"] = "PostScript"; - types["*.svg"] = "Scalable Vector Graphics"; - for (const auto& t : types) { - Gtk::FileFilter filt; - filt.add_pattern(t.first); - filt.set_name(t.second); - dialog.add_filter(filt); - } - - auto* bg_but = new Gtk::CheckButton("Draw _Background", true); - auto* extra = new Gtk::Alignment(1.0, 0.5, 0.0, 0.0); - bg_but->set_active(true); - extra->add(*Gtk::manage(bg_but)); - extra->show_all(); - dialog.set_extra_widget(*Gtk::manage(extra)); - - if (dialog.run() == Gtk::RESPONSE_OK) { - const std::string filename = dialog.get_filename(); - if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - Gtk::MessageDialog confirm(std::string("File exists! Overwrite ") + - filename + "?", - true, - Gtk::MESSAGE_WARNING, - Gtk::BUTTONS_YES_NO, - true); - confirm.set_transient_for(dialog); - if (confirm.run() != Gtk::RESPONSE_YES) { - return; - } - } - _canvas->export_image(filename.c_str(), bg_but->get_active()); - } + Gtk::FileChooserDialog dialog("Export Image", Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); + dialog.set_default_response(Gtk::RESPONSE_OK); + dialog.set_transient_for(*_main_win); + + using Types = std::map; + + Types types; + types["*.dot"] = "Graphviz DOT"; + types["*.pdf"] = "Portable Document Format"; + types["*.ps"] = "PostScript"; + types["*.svg"] = "Scalable Vector Graphics"; + for (const auto& t : types) { + Gtk::FileFilter filt; + filt.add_pattern(t.first); + filt.set_name(t.second); + dialog.add_filter(filt); + } + + auto* bg_but = new Gtk::CheckButton("Draw _Background", true); + auto* extra = new Gtk::Alignment(1.0, 0.5, 0.0, 0.0); + bg_but->set_active(true); + extra->add(*Gtk::manage(bg_but)); + extra->show_all(); + dialog.set_extra_widget(*Gtk::manage(extra)); + + if (dialog.run() == Gtk::RESPONSE_OK) { + const std::string filename = dialog.get_filename(); + if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { + Gtk::MessageDialog confirm(std::string("File exists! Overwrite ") + + filename + "?", + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_YES_NO, + true); + confirm.set_transient_for(dialog); + if (confirm.run() != Gtk::RESPONSE_YES) { + return; + } + } + _canvas->export_image(filename.c_str(), bg_but->get_active()); + } } void Patchage::on_view_messages() { - if (_menu_view_messages->get_active()) { - Glib::RefPtr buffer = _status_text->get_buffer(); - if (!_pane_initialized) { - const int min_height = _log.min_height(); - const int max_pos = _main_paned->get_allocation().get_height(); - const int conf_height = _conf.get_messages_height(); - _main_paned->set_position(max_pos - - std::max(conf_height, min_height)); + if (_menu_view_messages->get_active()) { + Glib::RefPtr buffer = _status_text->get_buffer(); + if (!_pane_initialized) { + const int min_height = _log.min_height(); + const int max_pos = _main_paned->get_allocation().get_height(); + const int conf_height = _conf.get_messages_height(); + _main_paned->set_position(max_pos - std::max(conf_height, min_height)); - _pane_initialized = true; - } + _pane_initialized = true; + } - _log_scrolledwindow->show(); - _status_text->scroll_to_mark(_status_text->get_buffer()->get_insert(), - 0); - _conf.set_show_messages(true); - } else { - _log_scrolledwindow->hide(); - _conf.set_show_messages(false); - } + _log_scrolledwindow->show(); + _status_text->scroll_to_mark(_status_text->get_buffer()->get_insert(), 0); + _conf.set_show_messages(true); + } else { + _log_scrolledwindow->hide(); + _conf.set_show_messages(false); + } } void Patchage::on_view_toolbar() { - if (_menu_view_toolbar->get_active()) { - _toolbar->show(); - } else { - _toolbar->hide(); - } - _conf.set_show_toolbar(_menu_view_toolbar->get_active()); + if (_menu_view_toolbar->get_active()) { + _toolbar->show(); + } else { + _toolbar->hide(); + } + + _conf.set_show_toolbar(_menu_view_toolbar->get_active()); } bool Patchage::on_scroll(GdkEventScroll*) { - return false; + return false; } void Patchage::buffer_size_changed() { - if (_jack_driver) { - const int selected = _buf_size_combo->get_active_row_number(); - - if (selected == -1) { - update_toolbar(); - } else { - const uint32_t buffer_size = 1u << (selected + 5); - _jack_driver->set_buffer_size(buffer_size); - update_toolbar(); - } - } + if (_jack_driver) { + const int selected = _buf_size_combo->get_active_row_number(); + + if (selected == -1) { + update_toolbar(); + } else { + const uint32_t buffer_size = 1u << (selected + 5); + _jack_driver->set_buffer_size(buffer_size); + update_toolbar(); + } + } } } // namespace patchage diff --git a/src/Patchage.hpp b/src/Patchage.hpp index 4496f12..e108748 100644 --- a/src/Patchage.hpp +++ b/src/Patchage.hpp @@ -76,148 +76,145 @@ class Legend; class Patchage { public: - explicit Patchage(Options options); + explicit Patchage(Options options); - ~Patchage(); + ~Patchage(); - Patchage(const Patchage&) = delete; - Patchage& operator=(const Patchage&) = delete; + Patchage(const Patchage&) = delete; + Patchage& operator=(const Patchage&) = delete; - Patchage(Patchage&&) = delete; - Patchage& operator=(Patchage&&) = delete; + Patchage(Patchage&&) = delete; + Patchage& operator=(Patchage&&) = delete; - const std::unique_ptr& canvas() const { return _canvas; } + const std::unique_ptr& canvas() const { return _canvas; } - void attach(); - void refresh(); - void save(); - void quit(); + void attach(); + void refresh(); + void save(); + void quit(); - void driver_attached(ClientType type); - void driver_detached(ClientType type); + void driver_attached(ClientType type); + void driver_detached(ClientType type); - void store_window_location(); + void store_window_location(); - bool show_human_names() const - { - return _menu_view_human_names->get_active(); - } + bool show_human_names() const { return _menu_view_human_names->get_active(); } - bool sort_ports() const { return _menu_view_sort_ports->get_active(); } + bool sort_ports() const { return _menu_view_sort_ports->get_active(); } - Gtk::Window* window() { return _main_win.get(); } - ILog& log() { return _log; } - Metadata& metadata() { return _metadata; } - const Configuration& conf() const { return _conf; } - Configuration& conf() { return _conf; } + Gtk::Window* window() { return _main_win.get(); } + ILog& log() { return _log; } + Metadata& metadata() { return _metadata; } + const Configuration& conf() const { return _conf; } + Configuration& conf() { return _conf; } protected: - class BufferSizeColumns : public Gtk::TreeModel::ColumnRecord - { - public: - BufferSizeColumns() { add(label); } - - Gtk::TreeModelColumn label; - }; - - void on_driver_event(const Event& event); - void process_events(); - - void on_arrange(); - void on_sprung_layout_toggled(); - void on_help_about(); - void on_quit(); - void on_export_image(); - void on_view_messages(); - void on_view_toolbar(); - void on_store_positions(); - void on_view_human_names(); - void on_view_sort_ports(); - void on_zoom_in(); - void on_zoom_out(); - void on_zoom_normal(); - void on_zoom_full(); - void on_increase_font_size(); - void on_decrease_font_size(); - void on_normal_font_size(); - - void on_legend_color_change(PortType id, - const std::string& label, - uint32_t rgba); - - void on_messages_resized(Gtk::Allocation& alloc); - - bool on_scroll(GdkEventScroll* ev); - - bool idle_callback(); - void clear_load(); - bool update_load(); - void update_toolbar(); - - void buffer_size_changed(); - - Glib::RefPtr _xml; - - std::mutex _events_mutex; - std::queue _driver_events; - - std::unique_ptr _alsa_driver; - - std::unique_ptr _canvas; - - std::unique_ptr _jack_driver; - Configuration _conf; - - Gtk::Main* _gtk_main; - - BufferSizeColumns _buf_size_columns; - - Widget _about_win; - Widget _main_scrolledwin; - Widget _main_win; - Widget _main_vbox; - Widget _menubar; - Widget _menu_alsa_connect; - Widget _menu_alsa_disconnect; - Widget _menu_file_quit; - Widget _menu_export_image; - Widget _menu_help_about; - Widget _menu_jack_connect; - Widget _menu_jack_disconnect; - Widget _menu_view_arrange; - Widget _menu_view_sprung_layout; - Widget _menu_view_messages; - Widget _menu_view_toolbar; - Widget _menu_view_refresh; - Widget _menu_view_human_names; - Widget _menu_view_sort_ports; - Widget _menu_zoom_in; - Widget _menu_zoom_out; - Widget _menu_zoom_normal; - Widget _menu_zoom_full; - Widget _menu_increase_font_size; - Widget _menu_decrease_font_size; - Widget _menu_normal_font_size; - Widget _toolbar; - Widget _clear_load_but; - Widget _dropouts_label; - Widget _buf_size_combo; - Widget _latency_label; - Widget _legend_alignment; - Widget _main_paned; - Widget _log_scrolledwindow; - Widget _status_text; - Legend* _legend; - TextViewLog _log; - Connector _connector; - Metadata _metadata; - - Glib::RefPtr _error_tag; - Glib::RefPtr _warning_tag; - - Options _options; - bool _pane_initialized; - bool _attach; + class BufferSizeColumns : public Gtk::TreeModel::ColumnRecord + { + public: + BufferSizeColumns() { add(label); } + + Gtk::TreeModelColumn label; + }; + + void on_driver_event(const Event& event); + void process_events(); + + void on_arrange(); + void on_sprung_layout_toggled(); + void on_help_about(); + void on_quit(); + void on_export_image(); + void on_view_messages(); + void on_view_toolbar(); + void on_store_positions(); + void on_view_human_names(); + void on_view_sort_ports(); + void on_zoom_in(); + void on_zoom_out(); + void on_zoom_normal(); + void on_zoom_full(); + void on_increase_font_size(); + void on_decrease_font_size(); + void on_normal_font_size(); + + void on_legend_color_change(PortType id, + const std::string& label, + uint32_t rgba); + + void on_messages_resized(Gtk::Allocation& alloc); + + bool on_scroll(GdkEventScroll* ev); + + bool idle_callback(); + void clear_load(); + bool update_load(); + void update_toolbar(); + + void buffer_size_changed(); + + Glib::RefPtr _xml; + + std::mutex _events_mutex; + std::queue _driver_events; + + std::unique_ptr _alsa_driver; + + std::unique_ptr _canvas; + + std::unique_ptr _jack_driver; + Configuration _conf; + + Gtk::Main* _gtk_main; + + BufferSizeColumns _buf_size_columns; + + Widget _about_win; + Widget _main_scrolledwin; + Widget _main_win; + Widget _main_vbox; + Widget _menubar; + Widget _menu_alsa_connect; + Widget _menu_alsa_disconnect; + Widget _menu_file_quit; + Widget _menu_export_image; + Widget _menu_help_about; + Widget _menu_jack_connect; + Widget _menu_jack_disconnect; + Widget _menu_view_arrange; + Widget _menu_view_sprung_layout; + Widget _menu_view_messages; + Widget _menu_view_toolbar; + Widget _menu_view_refresh; + Widget _menu_view_human_names; + Widget _menu_view_sort_ports; + Widget _menu_zoom_in; + Widget _menu_zoom_out; + Widget _menu_zoom_normal; + Widget _menu_zoom_full; + Widget _menu_increase_font_size; + Widget _menu_decrease_font_size; + Widget _menu_normal_font_size; + Widget _toolbar; + Widget _clear_load_but; + Widget _dropouts_label; + Widget _buf_size_combo; + Widget _latency_label; + Widget _legend_alignment; + Widget _main_paned; + Widget _log_scrolledwindow; + Widget _status_text; + Legend* _legend; + TextViewLog _log; + Connector _connector; + Metadata _metadata; + + Glib::RefPtr _error_tag; + Glib::RefPtr _warning_tag; + + Options _options; + bool _pane_initialized; + bool _attach; }; } // namespace patchage diff --git a/src/PortID.hpp b/src/PortID.hpp index a5b6109..03d655f 100644 --- a/src/PortID.hpp +++ b/src/PortID.hpp @@ -32,143 +32,142 @@ namespace patchage { /// An ID for some port on a client (program) -struct PortID -{ - using Type = ClientType; - - PortID(const PortID& copy) = default; - PortID& operator=(const PortID& copy) = default; - - PortID(PortID&& id) = default; - PortID& operator=(PortID&& id) = default; - - ~PortID() = default; - - /// Return an ID for a JACK port by full name (like "client:port") - static PortID jack(std::string name) - { - return PortID{Type::jack, std::move(name)}; - } - - /// Return an ID for a JACK port by separate client and port name - static PortID - jack(const std::string& client_name, const std::string& port_name) - { - return PortID{Type::jack, client_name + ":" + port_name}; - } - - /// Return an ID for an ALSA Sequencer port by ID - static PortID - alsa(const uint8_t client_id, const uint8_t port, const bool is_input) - { - return PortID{Type::alsa, client_id, port, is_input}; - } - - /// Return the ID of the client that hosts this port - ClientID client() const - { - switch (_type) { - case Type::jack: - return ClientID::jack(_jack_name.substr(0, _jack_name.find(':'))); - case Type::alsa: - return ClientID::alsa(_alsa_client); - } - - PATCHAGE_UNREACHABLE(); - } - - Type type() const { return _type; } - const std::string& jack_name() const { return _jack_name; } - uint8_t alsa_client() const { return _alsa_client; } - uint8_t alsa_port() const { return _alsa_port; } - bool alsa_is_input() const { return _alsa_is_input; } +struct PortID { + using Type = ClientType; + + PortID(const PortID& copy) = default; + PortID& operator=(const PortID& copy) = default; + + PortID(PortID&& id) = default; + PortID& operator=(PortID&& id) = default; + + ~PortID() = default; + + /// Return an ID for a JACK port by full name (like "client:port") + static PortID jack(std::string name) + { + return PortID{Type::jack, std::move(name)}; + } + + /// Return an ID for a JACK port by separate client and port name + static PortID jack(const std::string& client_name, + const std::string& port_name) + { + return PortID{Type::jack, client_name + ":" + port_name}; + } + + /// Return an ID for an ALSA Sequencer port by ID + static PortID alsa(const uint8_t client_id, + const uint8_t port, + const bool is_input) + { + return PortID{Type::alsa, client_id, port, is_input}; + } + + /// Return the ID of the client that hosts this port + ClientID client() const + { + switch (_type) { + case Type::jack: + return ClientID::jack(_jack_name.substr(0, _jack_name.find(':'))); + case Type::alsa: + return ClientID::alsa(_alsa_client); + } + + PATCHAGE_UNREACHABLE(); + } + + Type type() const { return _type; } + const std::string& jack_name() const { return _jack_name; } + uint8_t alsa_client() const { return _alsa_client; } + uint8_t alsa_port() const { return _alsa_port; } + bool alsa_is_input() const { return _alsa_is_input; } private: - PortID(const Type type, std::string jack_name) - : _type{type} - , _jack_name{std::move(jack_name)} - { - assert(_type == Type::jack); - assert(_jack_name.find(':') != std::string::npos); - assert(_jack_name.find(':') > 0); - assert(_jack_name.find(':') < _jack_name.length() - 1); - } - - PortID(const Type type, - const uint8_t alsa_client, - const uint8_t alsa_port, - const bool is_input) - : _type{type} - , _alsa_client{alsa_client} - , _alsa_port{alsa_port} - , _alsa_is_input{is_input} - { - assert(_type == Type::alsa); - } - - Type _type; ///< Determines which field is active - std::string _jack_name; ///< Full port name for Type::jack - uint8_t _alsa_client{}; ///< Client ID for Type::alsa - uint8_t _alsa_port{}; ///< Port ID for Type::alsa - bool _alsa_is_input{}; ///< Input flag for Type::alsa + PortID(const Type type, std::string jack_name) + : _type{type} + , _jack_name{std::move(jack_name)} + { + assert(_type == Type::jack); + assert(_jack_name.find(':') != std::string::npos); + assert(_jack_name.find(':') > 0); + assert(_jack_name.find(':') < _jack_name.length() - 1); + } + + PortID(const Type type, + const uint8_t alsa_client, + const uint8_t alsa_port, + const bool is_input) + : _type{type} + , _alsa_client{alsa_client} + , _alsa_port{alsa_port} + , _alsa_is_input{is_input} + { + assert(_type == Type::alsa); + } + + Type _type; ///< Determines which field is active + std::string _jack_name; ///< Full port name for Type::jack + uint8_t _alsa_client{}; ///< Client ID for Type::alsa + uint8_t _alsa_port{}; ///< Port ID for Type::alsa + bool _alsa_is_input{}; ///< Input flag for Type::alsa }; static inline std::ostream& operator<<(std::ostream& os, const PortID& id) { - switch (id.type()) { - case PortID::Type::jack: - return os << "jack:" << id.jack_name(); - case PortID::Type::alsa: - return os << "alsa:" << int(id.alsa_client()) << ":" - << int(id.alsa_port()) << ":" - << (id.alsa_is_input() ? "in" : "out"); - } - - assert(false); - return os; + switch (id.type()) { + case PortID::Type::jack: + return os << "jack:" << id.jack_name(); + case PortID::Type::alsa: + return os << "alsa:" << int(id.alsa_client()) << ":" << int(id.alsa_port()) + << ":" << (id.alsa_is_input() ? "in" : "out"); + } + + assert(false); + return os; } static inline bool operator==(const PortID& lhs, const PortID& rhs) { - if (lhs.type() != rhs.type()) { - return false; - } - - switch (lhs.type()) { - case PortID::Type::jack: - return lhs.jack_name() == rhs.jack_name(); - case PortID::Type::alsa: - return std::make_tuple( - lhs.alsa_client(), lhs.alsa_port(), lhs.alsa_is_input()) == - std::make_tuple( - rhs.alsa_client(), rhs.alsa_port(), rhs.alsa_is_input()); - } - - assert(false); - return false; + if (lhs.type() != rhs.type()) { + return false; + } + + switch (lhs.type()) { + case PortID::Type::jack: + return lhs.jack_name() == rhs.jack_name(); + case PortID::Type::alsa: + return std::make_tuple( + lhs.alsa_client(), lhs.alsa_port(), lhs.alsa_is_input()) == + std::make_tuple( + rhs.alsa_client(), rhs.alsa_port(), rhs.alsa_is_input()); + } + + assert(false); + return false; } static inline bool operator<(const PortID& lhs, const PortID& rhs) { - if (lhs.type() != rhs.type()) { - return lhs.type() < rhs.type(); - } - - switch (lhs.type()) { - case PortID::Type::jack: - return lhs.jack_name() < rhs.jack_name(); - case PortID::Type::alsa: - return std::make_tuple( - lhs.alsa_client(), lhs.alsa_port(), lhs.alsa_is_input()) < - std::make_tuple( - rhs.alsa_client(), rhs.alsa_port(), rhs.alsa_is_input()); - } - - assert(false); - return false; + if (lhs.type() != rhs.type()) { + return lhs.type() < rhs.type(); + } + + switch (lhs.type()) { + case PortID::Type::jack: + return lhs.jack_name() < rhs.jack_name(); + case PortID::Type::alsa: + return std::make_tuple( + lhs.alsa_client(), lhs.alsa_port(), lhs.alsa_is_input()) < + std::make_tuple( + rhs.alsa_client(), rhs.alsa_port(), rhs.alsa_is_input()); + } + + assert(false); + return false; } } // namespace patchage @@ -176,12 +175,11 @@ operator<(const PortID& lhs, const PortID& rhs) namespace std { template<> -struct hash -{ - size_t operator()(const patchage::PortID::Type& v) const noexcept - { - return hash()(static_cast(v)); - } +struct hash { + size_t operator()(const patchage::PortID::Type& v) const noexcept + { + return hash()(static_cast(v)); + } }; } // namespace std diff --git a/src/PortInfo.hpp b/src/PortInfo.hpp index a2e2b16..3a4103d 100644 --- a/src/PortInfo.hpp +++ b/src/PortInfo.hpp @@ -26,13 +26,12 @@ namespace patchage { /// Extra information about a port not expressed in its ID -struct PortInfo -{ - std::string label; ///< Human-friendly label - PortType type; ///< Detailed port type - SignalDirection direction; ///< Signal direction - boost::optional order; ///< Order key on client - bool is_terminal; ///< True if this is a system port +struct PortInfo { + std::string label; ///< Human-friendly label + PortType type; ///< Detailed port type + SignalDirection direction; ///< Signal direction + boost::optional order; ///< Order key on client + bool is_terminal; ///< True if this is a system port }; } // namespace patchage diff --git a/src/PortNames.hpp b/src/PortNames.hpp index 9d8baf1..1ec7685 100644 --- a/src/PortNames.hpp +++ b/src/PortNames.hpp @@ -28,28 +28,28 @@ namespace patchage { class PortNames { public: - explicit PortNames(const std::string& jack_name) - { - const auto colon = jack_name.find(':'); + explicit PortNames(const std::string& jack_name) + { + const auto colon = jack_name.find(':'); - if (colon != std::string::npos) { - _client_name = jack_name.substr(0, colon); - _port_name = jack_name.substr(colon + 1); - } - } + if (colon != std::string::npos) { + _client_name = jack_name.substr(0, colon); + _port_name = jack_name.substr(colon + 1); + } + } - explicit PortNames(const PortID& id) - : PortNames(id.jack_name()) - { - assert(id.type() == PortID::Type::jack); - } + explicit PortNames(const PortID& id) + : PortNames(id.jack_name()) + { + assert(id.type() == PortID::Type::jack); + } - const std::string& client() const { return _client_name; } - const std::string& port() const { return _port_name; } + const std::string& client() const { return _client_name; } + const std::string& port() const { return _port_name; } private: - std::string _client_name; - std::string _port_name; + std::string _client_name; + std::string _port_name; }; } // namespace patchage diff --git a/src/PortType.hpp b/src/PortType.hpp index ed5d824..9db0c1f 100644 --- a/src/PortType.hpp +++ b/src/PortType.hpp @@ -19,13 +19,12 @@ namespace patchage { -enum class PortType -{ - jack_audio, - jack_midi, - alsa_midi, - jack_osc, - jack_cv, +enum class PortType { + jack_audio, + jack_midi, + alsa_midi, + jack_osc, + jack_cv, }; } // namespace patchage diff --git a/src/SignalDirection.hpp b/src/SignalDirection.hpp index 52c767d..94f5126 100644 --- a/src/SignalDirection.hpp +++ b/src/SignalDirection.hpp @@ -19,11 +19,10 @@ namespace patchage { -enum class SignalDirection -{ - input, - output, - duplex, +enum class SignalDirection { + input, + output, + duplex, }; } // namespace patchage diff --git a/src/TextViewLog.cpp b/src/TextViewLog.cpp index 74f7bd0..33b7d22 100644 --- a/src/TextViewLog.cpp +++ b/src/TextViewLog.cpp @@ -32,64 +32,63 @@ namespace patchage { TextViewLog::TextViewLog(Widget& text_view) - : _error_tag{Gtk::TextTag::create()} - , _warning_tag{Gtk::TextTag::create()} - , _text_view{text_view} + : _error_tag{Gtk::TextTag::create()} + , _warning_tag{Gtk::TextTag::create()} + , _text_view{text_view} { - for (int s = Gtk::STATE_NORMAL; s <= Gtk::STATE_INSENSITIVE; ++s) { - _text_view->modify_base(static_cast(s), - Gdk::Color("#000000")); - _text_view->modify_text(static_cast(s), - Gdk::Color("#FFFFFF")); - } - - _error_tag->property_foreground() = "#CC0000"; - _text_view->get_buffer()->get_tag_table()->add(_error_tag); - - _warning_tag->property_foreground() = "#C4A000"; - _text_view->get_buffer()->get_tag_table()->add(_warning_tag); - - _text_view->set_pixels_inside_wrap(2); - _text_view->set_left_margin(4); - _text_view->set_right_margin(4); - _text_view->set_pixels_below_lines(2); + for (int s = Gtk::STATE_NORMAL; s <= Gtk::STATE_INSENSITIVE; ++s) { + _text_view->modify_base(static_cast(s), + Gdk::Color("#000000")); + _text_view->modify_text(static_cast(s), + Gdk::Color("#FFFFFF")); + } + + _error_tag->property_foreground() = "#CC0000"; + _text_view->get_buffer()->get_tag_table()->add(_error_tag); + + _warning_tag->property_foreground() = "#C4A000"; + _text_view->get_buffer()->get_tag_table()->add(_warning_tag); + + _text_view->set_pixels_inside_wrap(2); + _text_view->set_left_margin(4); + _text_view->set_right_margin(4); + _text_view->set_pixels_below_lines(2); } void TextViewLog::info(const std::string& msg) { - Glib::RefPtr buffer = _text_view->get_buffer(); - buffer->insert(buffer->end(), std::string("\n") + msg); - _text_view->scroll_to_mark(buffer->get_insert(), 0); + Glib::RefPtr buffer = _text_view->get_buffer(); + buffer->insert(buffer->end(), std::string("\n") + msg); + _text_view->scroll_to_mark(buffer->get_insert(), 0); } void TextViewLog::warning(const std::string& msg) { - Glib::RefPtr buffer = _text_view->get_buffer(); - buffer->insert_with_tag( - buffer->end(), std::string("\n") + msg, _warning_tag); - _text_view->scroll_to_mark(buffer->get_insert(), 0); + Glib::RefPtr buffer = _text_view->get_buffer(); + buffer->insert_with_tag(buffer->end(), std::string("\n") + msg, _warning_tag); + _text_view->scroll_to_mark(buffer->get_insert(), 0); } void TextViewLog::error(const std::string& msg) { - Glib::RefPtr buffer = _text_view->get_buffer(); - buffer->insert_with_tag(buffer->end(), std::string("\n") + msg, _error_tag); - _text_view->scroll_to_mark(buffer->get_insert(), 0); + Glib::RefPtr buffer = _text_view->get_buffer(); + buffer->insert_with_tag(buffer->end(), std::string("\n") + msg, _error_tag); + _text_view->scroll_to_mark(buffer->get_insert(), 0); } int TextViewLog::min_height() const { - Glib::RefPtr buffer = _text_view->get_buffer(); + Glib::RefPtr buffer = _text_view->get_buffer(); - int y = 0; - int line_height = 0; - _text_view->get_line_yrange(buffer->begin(), y, line_height); + int y = 0; + int line_height = 0; + _text_view->get_line_yrange(buffer->begin(), y, line_height); - return line_height + 2 * _text_view->get_pixels_inside_wrap(); + return line_height + 2 * _text_view->get_pixels_inside_wrap(); } } // namespace patchage diff --git a/src/TextViewLog.hpp b/src/TextViewLog.hpp index 52c1b2c..9840303 100644 --- a/src/TextViewLog.hpp +++ b/src/TextViewLog.hpp @@ -39,29 +39,29 @@ class Widget; class TextViewLog : public ILog { public: - explicit TextViewLog(Widget& text_view); + explicit TextViewLog(Widget& text_view); - TextViewLog(const TextViewLog&) = delete; - TextViewLog& operator=(const TextViewLog&) = delete; + TextViewLog(const TextViewLog&) = delete; + TextViewLog& operator=(const TextViewLog&) = delete; - TextViewLog(TextViewLog&&) = delete; - TextViewLog& operator=(TextViewLog&&) = delete; + TextViewLog(TextViewLog&&) = delete; + TextViewLog& operator=(TextViewLog&&) = delete; - ~TextViewLog() override = default; + ~TextViewLog() override = default; - void info(const std::string& msg) override; - void error(const std::string& msg) override; - void warning(const std::string& msg) override; + void info(const std::string& msg) override; + void error(const std::string& msg) override; + void warning(const std::string& msg) override; - int min_height() const; + int min_height() const; - const Widget& text_view() const { return _text_view; } - Widget& text_view() { return _text_view; } + const Widget& text_view() const { return _text_view; } + Widget& text_view() { return _text_view; } private: - Glib::RefPtr _error_tag; - Glib::RefPtr _warning_tag; - Widget& _text_view; + Glib::RefPtr _error_tag; + Glib::RefPtr _warning_tag; + Widget& _text_view; }; } // namespace patchage diff --git a/src/UIFile.hpp b/src/UIFile.hpp index 08c2b42..ee0c4b7 100644 --- a/src/UIFile.hpp +++ b/src/UIFile.hpp @@ -20,7 +20,7 @@ #include "patchage_config.h" #ifdef PATCHAGE_BINLOC -# include "binary_location.h" +# include "binary_location.h" #endif #include @@ -37,38 +37,38 @@ namespace patchage { class UIFile { public: - inline static bool is_readable(const std::string& filename) - { - std::ifstream fs(filename.c_str()); - const bool fail = fs.fail(); - fs.close(); - return !fail; - } + inline static bool is_readable(const std::string& filename) + { + std::ifstream fs(filename.c_str()); + const bool fail = fs.fail(); + fs.close(); + return !fail; + } - static Glib::RefPtr open(const std::string& base_name) - { - std::string ui_filename; + static Glib::RefPtr open(const std::string& base_name) + { + std::string ui_filename; #ifdef PATCHAGE_BINLOC - const std::string bundle = bundle_location(); - if (!bundle.empty()) { - ui_filename = bundle + "/" + base_name + ".ui"; - if (is_readable(ui_filename)) { - std::cout << "Loading UI file " << ui_filename << std::endl; - return Gtk::Builder::create_from_file(ui_filename); - } - } + const std::string bundle = bundle_location(); + if (!bundle.empty()) { + ui_filename = bundle + "/" + base_name + ".ui"; + if (is_readable(ui_filename)) { + std::cout << "Loading UI file " << ui_filename << std::endl; + return Gtk::Builder::create_from_file(ui_filename); + } + } #endif - ui_filename = std::string(PATCHAGE_DATA_DIR) + "/" + base_name + ".ui"; - if (is_readable(ui_filename)) { - std::cout << "Loading UI file " << ui_filename << std::endl; - return Gtk::Builder::create_from_file(ui_filename); - } + ui_filename = std::string(PATCHAGE_DATA_DIR) + "/" + base_name + ".ui"; + if (is_readable(ui_filename)) { + std::cout << "Loading UI file " << ui_filename << std::endl; + return Gtk::Builder::create_from_file(ui_filename); + } - std::stringstream ss; - ss << "Unable to find " << base_name << std::endl; - throw std::runtime_error(ss.str()); - return Glib::RefPtr(); - } + std::stringstream ss; + ss << "Unable to find " << base_name << std::endl; + throw std::runtime_error(ss.str()); + return Glib::RefPtr(); + } }; } // namespace patchage diff --git a/src/Widget.hpp b/src/Widget.hpp index 19f9816..3d13b91 100644 --- a/src/Widget.hpp +++ b/src/Widget.hpp @@ -28,30 +28,30 @@ template class Widget { public: - Widget(const Glib::RefPtr& xml, const std::string& name) - { - xml->get_widget(name, _me); - } + Widget(const Glib::RefPtr& xml, const std::string& name) + { + xml->get_widget(name, _me); + } - Widget(const Widget&) = delete; - Widget& operator=(const Widget&) = delete; + Widget(const Widget&) = delete; + Widget& operator=(const Widget&) = delete; - Widget(Widget&&) = delete; - Widget& operator=(Widget&&) = delete; + Widget(Widget&&) = delete; + Widget& operator=(Widget&&) = delete; - ~Widget() = default; + ~Widget() = default; - void destroy() { delete _me; } + void destroy() { delete _me; } - W* get() { return _me; } - const W* get() const { return _me; } - W* operator->() { return _me; } - const W* operator->() const { return _me; } - W& operator*() { return *_me; } - const W& operator*() const { return *_me; } + W* get() { return _me; } + const W* get() const { return _me; } + W* operator->() { return _me; } + const W* operator->() const { return _me; } + W& operator*() { return *_me; } + const W& operator*() const { return *_me; } private: - W* _me; + W* _me; }; } // namespace patchage diff --git a/src/event_to_string.cpp b/src/event_to_string.cpp index 606c512..d898845 100644 --- a/src/event_to_string.cpp +++ b/src/event_to_string.cpp @@ -41,106 +41,103 @@ namespace patchage { namespace { -struct EventPrinter -{ - using result_type = std::string; ///< For boost::apply_visitor - - std::string operator()(const ClientType type) - { - switch (type) { - case ClientType::jack: - return "JACK"; - case ClientType::alsa: - return "ALSA"; - } - - PATCHAGE_UNREACHABLE(); - } - - std::string operator()(const DriverAttachmentEvent& event) - { - return fmt::format("Attached to {}", (*this)(event.type)); - } - - std::string operator()(const DriverDetachmentEvent& event) - { - return fmt::format("Detached from {}", (*this)(event.type)); - } - - std::string operator()(const ClientCreationEvent& event) - { - return fmt::format( - R"(Add client "{}" ("{}"))", event.id, event.info.label); - } - - std::string operator()(const ClientDestructionEvent& event) - { - return fmt::format(R"(Add{} {} {} port "{}" ("{}"))", event.id); - } - - std::string operator()(const PortType port_type) - { - switch (port_type) { - case PortType::jack_audio: - return "JACK audio"; - case PortType::jack_midi: - return "JACK MIDI"; - case PortType::alsa_midi: - return "ALSA MIDI"; - case PortType::jack_osc: - return "JACK OSC"; - case PortType::jack_cv: - return "JACK CV"; - } - - PATCHAGE_UNREACHABLE(); - } - - std::string operator()(const SignalDirection direction) - { - switch (direction) { - case SignalDirection::input: - return "input"; - case SignalDirection::output: - return "output"; - case SignalDirection::duplex: - return "duplex"; - } - - PATCHAGE_UNREACHABLE(); - } - - std::string operator()(const PortCreationEvent& event) - { - auto result = fmt::format(R"(Add{} {} {} port "{}" ("{}"))", - event.info.is_terminal ? " terminal" : "", - (*this)(event.info.type), - (*this)(event.info.direction), - event.id, - event.info.label); - - if (event.info.order) { - result += fmt::format(" order: {}", *event.info.order); - } - - return result; - } - - std::string operator()(const PortDestructionEvent& event) - { - return fmt::format(R"("Remove port "{}")", event.id); - } - - std::string operator()(const ConnectionEvent& event) - { - return fmt::format(R"(Connect "{}" to "{}")", event.tail, event.head); - } - - std::string operator()(const DisconnectionEvent& event) - { - return fmt::format( - R"(Disconnect "{}" from "{}")", event.tail, event.head); - } +struct EventPrinter { + using result_type = std::string; ///< For boost::apply_visitor + + std::string operator()(const ClientType type) + { + switch (type) { + case ClientType::jack: + return "JACK"; + case ClientType::alsa: + return "ALSA"; + } + + PATCHAGE_UNREACHABLE(); + } + + std::string operator()(const DriverAttachmentEvent& event) + { + return fmt::format("Attached to {}", (*this)(event.type)); + } + + std::string operator()(const DriverDetachmentEvent& event) + { + return fmt::format("Detached from {}", (*this)(event.type)); + } + + std::string operator()(const ClientCreationEvent& event) + { + return fmt::format(R"(Add client "{}" ("{}"))", event.id, event.info.label); + } + + std::string operator()(const ClientDestructionEvent& event) + { + return fmt::format(R"(Add{} {} {} port "{}" ("{}"))", event.id); + } + + std::string operator()(const PortType port_type) + { + switch (port_type) { + case PortType::jack_audio: + return "JACK audio"; + case PortType::jack_midi: + return "JACK MIDI"; + case PortType::alsa_midi: + return "ALSA MIDI"; + case PortType::jack_osc: + return "JACK OSC"; + case PortType::jack_cv: + return "JACK CV"; + } + + PATCHAGE_UNREACHABLE(); + } + + std::string operator()(const SignalDirection direction) + { + switch (direction) { + case SignalDirection::input: + return "input"; + case SignalDirection::output: + return "output"; + case SignalDirection::duplex: + return "duplex"; + } + + PATCHAGE_UNREACHABLE(); + } + + std::string operator()(const PortCreationEvent& event) + { + auto result = fmt::format(R"(Add{} {} {} port "{}" ("{}"))", + event.info.is_terminal ? " terminal" : "", + (*this)(event.info.type), + (*this)(event.info.direction), + event.id, + event.info.label); + + if (event.info.order) { + result += fmt::format(" order: {}", *event.info.order); + } + + return result; + } + + std::string operator()(const PortDestructionEvent& event) + { + return fmt::format(R"("Remove port "{}")", event.id); + } + + std::string operator()(const ConnectionEvent& event) + { + return fmt::format(R"(Connect "{}" to "{}")", event.tail, event.head); + } + + std::string operator()(const DisconnectionEvent& event) + { + return fmt::format(R"(Disconnect "{}" from "{}")", event.tail, event.head); + } }; } // namespace @@ -148,14 +145,14 @@ struct EventPrinter std::string event_to_string(const Event& event) { - EventPrinter printer; - return boost::apply_visitor(printer, event); + EventPrinter printer; + return boost::apply_visitor(printer, event); } std::ostream& operator<<(std::ostream& os, const Event& event) { - return os << event_to_string(event); + return os << event_to_string(event); } } // namespace patchage diff --git a/src/handle_event.cpp b/src/handle_event.cpp index 4e77232..bbe86fc 100644 --- a/src/handle_event.cpp +++ b/src/handle_event.cpp @@ -42,87 +42,87 @@ namespace { class EventHandler { public: - using result_type = void; ///< For boost::apply_visitor - - explicit EventHandler(Patchage& patchage) - : _patchage{patchage} - {} - - void operator()(const DriverAttachmentEvent& event) - { - _patchage.driver_attached(event.type); - } - - void operator()(const DriverDetachmentEvent& event) - { - _patchage.driver_detached(event.type); - } - - void operator()(const ClientCreationEvent& event) - { - // Don't create empty modules, they will be created when ports are added - _patchage.metadata().set_client(event.id, event.info); - } - - void operator()(const ClientDestructionEvent& event) - { - _patchage.canvas()->remove_module(event.id); - _patchage.metadata().erase_client(event.id); - } - - void operator()(const PortCreationEvent& event) - { - _patchage.metadata().set_port(event.id, event.info); - - auto* const port = - _patchage.canvas()->create_port(_patchage, event.id, event.info); - - if (!port) { - _patchage.log().error( - fmt::format("Unable to create view for port \"{}\"", event.id)); - } - } - - void operator()(const PortDestructionEvent& event) - { - _patchage.canvas()->remove_port(event.id); - _patchage.metadata().erase_port(event.id); - } - - void operator()(const ConnectionEvent& event) - { - CanvasPort* port_1 = _patchage.canvas()->find_port(event.tail); - CanvasPort* port_2 = _patchage.canvas()->find_port(event.head); - - if (!port_1) { - _patchage.log().error(fmt::format( - "Unable to find port \"{}\" to connect", event.tail)); - } else if (!port_2) { - _patchage.log().error(fmt::format( - "Unable to find port \"{}\" to connect", event.head)); - } else { - _patchage.canvas()->make_connection(port_1, port_2); - } - } - - void operator()(const DisconnectionEvent& event) - { - CanvasPort* port_1 = _patchage.canvas()->find_port(event.tail); - CanvasPort* port_2 = _patchage.canvas()->find_port(event.head); - - if (!port_1) { - _patchage.log().error(fmt::format( - "Unable to find port \"{}\" to disconnect", event.tail)); - } else if (!port_2) { - _patchage.log().error(fmt::format( - "Unable to find port \"{}\" to disconnect", event.head)); - } else { - _patchage.canvas()->remove_edge_between(port_1, port_2); - } - } + using result_type = void; ///< For boost::apply_visitor + + explicit EventHandler(Patchage& patchage) + : _patchage{patchage} + {} + + void operator()(const DriverAttachmentEvent& event) + { + _patchage.driver_attached(event.type); + } + + void operator()(const DriverDetachmentEvent& event) + { + _patchage.driver_detached(event.type); + } + + void operator()(const ClientCreationEvent& event) + { + // Don't create empty modules, they will be created when ports are added + _patchage.metadata().set_client(event.id, event.info); + } + + void operator()(const ClientDestructionEvent& event) + { + _patchage.canvas()->remove_module(event.id); + _patchage.metadata().erase_client(event.id); + } + + void operator()(const PortCreationEvent& event) + { + _patchage.metadata().set_port(event.id, event.info); + + auto* const port = + _patchage.canvas()->create_port(_patchage, event.id, event.info); + + if (!port) { + _patchage.log().error( + fmt::format("Unable to create view for port \"{}\"", event.id)); + } + } + + void operator()(const PortDestructionEvent& event) + { + _patchage.canvas()->remove_port(event.id); + _patchage.metadata().erase_port(event.id); + } + + void operator()(const ConnectionEvent& event) + { + CanvasPort* port_1 = _patchage.canvas()->find_port(event.tail); + CanvasPort* port_2 = _patchage.canvas()->find_port(event.head); + + if (!port_1) { + _patchage.log().error( + fmt::format("Unable to find port \"{}\" to connect", event.tail)); + } else if (!port_2) { + _patchage.log().error( + fmt::format("Unable to find port \"{}\" to connect", event.head)); + } else { + _patchage.canvas()->make_connection(port_1, port_2); + } + } + + void operator()(const DisconnectionEvent& event) + { + CanvasPort* port_1 = _patchage.canvas()->find_port(event.tail); + CanvasPort* port_2 = _patchage.canvas()->find_port(event.head); + + if (!port_1) { + _patchage.log().error( + fmt::format("Unable to find port \"{}\" to disconnect", event.tail)); + } else if (!port_2) { + _patchage.log().error( + fmt::format("Unable to find port \"{}\" to disconnect", event.head)); + } else { + _patchage.canvas()->remove_edge_between(port_1, port_2); + } + } private: - Patchage& _patchage; + Patchage& _patchage; }; } // namespace @@ -130,8 +130,8 @@ private: void handle_event(Patchage& patchage, const Event& event) { - EventHandler handler{patchage}; - boost::apply_visitor(handler, event); + EventHandler handler{patchage}; + boost::apply_visitor(handler, event); } } // namespace patchage diff --git a/src/main.cpp b/src/main.cpp index c677e01..499db30 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,14 +15,14 @@ */ #ifdef __APPLE__ -# include "binary_location.h" +# include "binary_location.h" -# include +# include -# include +# include -# include -# include +# include +# include #endif #include "Options.hpp" @@ -44,53 +44,53 @@ namespace { void set_bundle_environment() { - const std::string bundle = patchage::bundle_location(); - const std::string lib_path = bundle + "/lib"; - if (!Glib::file_test(lib_path, Glib::FILE_TEST_EXISTS)) { - // If lib does not exist, we have not been bundleified, do nothing - return; - } - - setenv("GTK_PATH", lib_path.c_str(), 1); - setenv("DYLD_LIBRARY_PATH", lib_path.c_str(), 1); - - const std::string pangorc_path(bundle + "/Resources/pangorc"); - if (Glib::file_test(pangorc_path, Glib::FILE_TEST_EXISTS)) { - setenv("PANGO_RC_FILE", pangorc_path.c_str(), 1); - } - - const std::string fonts_conf_path(bundle + "/Resources/fonts.conf"); - if (Glib::file_test(fonts_conf_path, Glib::FILE_TEST_EXISTS)) { - setenv("FONTCONFIG_FILE", fonts_conf_path.c_str(), 1); - } - - const std::string loaders_cache_path(bundle + "/Resources/loaders.cache"); - if (Glib::file_test(loaders_cache_path, Glib::FILE_TEST_EXISTS)) { - setenv("GDK_PIXBUF_MODULE_FILE", loaders_cache_path.c_str(), 1); - } - - const std::string gtkrc_path(bundle + "/Resources/gtkrc"); - if (Glib::file_test(gtkrc_path, Glib::FILE_TEST_EXISTS)) { - gtk_rc_parse(gtkrc_path.c_str()); - } + const std::string bundle = patchage::bundle_location(); + const std::string lib_path = bundle + "/lib"; + if (!Glib::file_test(lib_path, Glib::FILE_TEST_EXISTS)) { + // If lib does not exist, we have not been bundleified, do nothing + return; + } + + setenv("GTK_PATH", lib_path.c_str(), 1); + setenv("DYLD_LIBRARY_PATH", lib_path.c_str(), 1); + + const std::string pangorc_path(bundle + "/Resources/pangorc"); + if (Glib::file_test(pangorc_path, Glib::FILE_TEST_EXISTS)) { + setenv("PANGO_RC_FILE", pangorc_path.c_str(), 1); + } + + const std::string fonts_conf_path(bundle + "/Resources/fonts.conf"); + if (Glib::file_test(fonts_conf_path, Glib::FILE_TEST_EXISTS)) { + setenv("FONTCONFIG_FILE", fonts_conf_path.c_str(), 1); + } + + const std::string loaders_cache_path(bundle + "/Resources/loaders.cache"); + if (Glib::file_test(loaders_cache_path, Glib::FILE_TEST_EXISTS)) { + setenv("GDK_PIXBUF_MODULE_FILE", loaders_cache_path.c_str(), 1); + } + + const std::string gtkrc_path(bundle + "/Resources/gtkrc"); + if (Glib::file_test(gtkrc_path, Glib::FILE_TEST_EXISTS)) { + gtk_rc_parse(gtkrc_path.c_str()); + } } #endif void print_usage() { - std::cout << "Usage: patchage [OPTION]...\n"; - std::cout << "Visually connect JACK and ALSA Audio and MIDI ports.\n\n"; - std::cout << "Options:\n"; - std::cout << " -h, --help Display this help and exit.\n"; - std::cout << " -A, --no-alsa Do not automatically attach to ALSA.\n"; - std::cout << " -J, --no-jack Do not automatically attack to JACK.\n"; + std::cout << "Usage: patchage [OPTION]...\n"; + std::cout << "Visually connect JACK and ALSA Audio and MIDI ports.\n\n"; + std::cout << "Options:\n"; + std::cout << " -h, --help Display this help and exit.\n"; + std::cout << " -A, --no-alsa Do not automatically attach to ALSA.\n"; + std::cout << " -J, --no-jack Do not automatically attack to JACK.\n"; } void print_version() { - std::cout << "Patchage " PATCHAGE_VERSION << R"( + std::cout << "Patchage " PATCHAGE_VERSION << R"( Copyright 2007-2020 David Robillard . License GPLv3+: . This is free software: you are free to change and redistribute it. @@ -104,54 +104,53 @@ int main(int argc, char** argv) { #ifdef __APPLE__ - set_bundle_environment(); + set_bundle_environment(); #endif - try { - - Glib::thread_init(); - - Gtk::Main app(argc, argv); - ++argv; - --argc; - - // Parse command line options - patchage::Options options; - while (argc > 0) { - if (!strcmp(*argv, "-h") || !strcmp(*argv, "--help")) { - print_usage(); - return 0; - } - - if (!strcmp(*argv, "-A") || !strcmp(*argv, "--no-alsa")) { - options.alsa_driver_autoattach = false; - } else if (!strcmp(*argv, "-J") || !strcmp(*argv, "--no-jack")) { - options.jack_driver_autoattach = false; - } else if (!strcmp(*argv, "-V") || !strcmp(*argv, "--version")) { - print_version(); - return 0; - } else { - std::cerr << "patchage: invalid option -- '" << *argv << "'\n"; - print_usage(); - return 1; - } - - ++argv; - --argc; - } - - // Run until main loop is finished - patchage::Patchage patchage(options); - Gtk::Main::run(*patchage.window()); - patchage.save(); - - } catch (std::exception& e) { - std::cerr << "patchage: error: " << e.what() << std::endl; - return 1; - } catch (Glib::Exception& e) { - std::cerr << "patchage: error: " << e.what() << std::endl; - return 1; - } - - return 0; + try { + Glib::thread_init(); + + Gtk::Main app(argc, argv); + ++argv; + --argc; + + // Parse command line options + patchage::Options options; + while (argc > 0) { + if (!strcmp(*argv, "-h") || !strcmp(*argv, "--help")) { + print_usage(); + return 0; + } + + if (!strcmp(*argv, "-A") || !strcmp(*argv, "--no-alsa")) { + options.alsa_driver_autoattach = false; + } else if (!strcmp(*argv, "-J") || !strcmp(*argv, "--no-jack")) { + options.jack_driver_autoattach = false; + } else if (!strcmp(*argv, "-V") || !strcmp(*argv, "--version")) { + print_version(); + return 0; + } else { + std::cerr << "patchage: invalid option -- '" << *argv << "'\n"; + print_usage(); + return 1; + } + + ++argv; + --argc; + } + + // Run until main loop is finished + patchage::Patchage patchage(options); + Gtk::Main::run(*patchage.window()); + patchage.save(); + + } catch (std::exception& e) { + std::cerr << "patchage: error: " << e.what() << std::endl; + return 1; + } catch (Glib::Exception& e) { + std::cerr << "patchage: error: " << e.what() << std::endl; + return 1; + } + + return 0; } diff --git a/src/make_alsa_driver.hpp b/src/make_alsa_driver.hpp index 8762718..f72da99 100644 --- a/src/make_alsa_driver.hpp +++ b/src/make_alsa_driver.hpp @@ -36,7 +36,7 @@ make_alsa_driver(ILog& log, Driver::EventSink emit_event); inline std::unique_ptr make_alsa_driver(ILog&, Driver::EventSink) { - return nullptr; + return nullptr; } #endif diff --git a/src/make_jack_driver.hpp b/src/make_jack_driver.hpp index c8420d3..abd1ba1 100644 --- a/src/make_jack_driver.hpp +++ b/src/make_jack_driver.hpp @@ -37,7 +37,7 @@ make_jack_driver(ILog& log, Driver::EventSink emit_event); inline std::unique_ptr make_jack_driver(ILog&, Driver::EventSink) { - return nullptr; + return nullptr; } #endif diff --git a/src/warnings.hpp b/src/warnings.hpp index f7f1779..e8337a1 100644 --- a/src/warnings.hpp +++ b/src/warnings.hpp @@ -19,12 +19,11 @@ #if defined(__clang__) -# define PATCHAGE_DISABLE_FMT_WARNINGS \ - _Pragma("clang diagnostic push") \ - _Pragma( \ - "clang diagnostic ignored \"-Wdocumentation-unknown-command\"") \ - _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \ - _Pragma("clang diagnostic ignored \"-Wsigned-enum-bitfield\"") +# define PATCHAGE_DISABLE_FMT_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdocumentation-unknown-command\"") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \ + _Pragma("clang diagnostic ignored \"-Wsigned-enum-bitfield\"") // clang-format off # define PATCHAGE_DISABLE_GANV_WARNINGS \ @@ -33,27 +32,27 @@ "clang diagnostic ignored \"-Wdocumentation-unknown-command\"") // clang-format on -# define PATCHAGE_RESTORE_WARNINGS _Pragma("clang diagnostic pop") +# define PATCHAGE_RESTORE_WARNINGS _Pragma("clang diagnostic pop") #elif defined(__GNUC__) -# define PATCHAGE_DISABLE_FMT_WARNINGS _Pragma("GCC diagnostic push") +# define PATCHAGE_DISABLE_FMT_WARNINGS _Pragma("GCC diagnostic push") -# define PATCHAGE_DISABLE_GANV_WARNINGS +# define PATCHAGE_DISABLE_GANV_WARNINGS -# define PATCHAGE_RESTORE_WARNINGS _Pragma("GCC diagnostic pop") +# define PATCHAGE_RESTORE_WARNINGS _Pragma("GCC diagnostic pop") #else -# define PATCHAGE_DISABLE_GANV_WARNINGS -# define PATCHAGE_RESTORE_WARNINGS +# define PATCHAGE_DISABLE_GANV_WARNINGS +# define PATCHAGE_RESTORE_WARNINGS #endif #if defined(__GNUC__) -# define PATCHAGE_UNREACHABLE() __builtin_unreachable() +# define PATCHAGE_UNREACHABLE() __builtin_unreachable() #else -# define PATCHAGE_UNREACHABLE() +# define PATCHAGE_UNREACHABLE() #endif #endif // PATCHAGE_WARNINGS_HPP -- cgit v1.2.1