diff --git a/CMakeLists.txt b/CMakeLists.txt index 86d7ef1..21740bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.21) -project(venmic LANGUAGES CXX VERSION 3.3.5) +project(venmic LANGUAGES CXX VERSION 3.4.0) # -------------------------------------------------------------------------------------------------------- # Library options @@ -87,7 +87,7 @@ include("cmake/cpm.cmake") CPMFindPackage( NAME rohrkabel - VERSION 5.0 + VERSION 5.1 GIT_REPOSITORY "https://github.com/Curve/rohrkabel" ) diff --git a/README.md b/README.md index 3995c31..bb6cfa9 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,11 @@ The Rest-Server exposes three simple endpoints The setting `ignore_devices` is optional and will default to `true`. When enabled it will prevent hardware-devices like speakers and microphones from being linked to the virtual microphone. + The setting `only_default_speakers` is optional and will default to `true`. + When enabled it will prevent linking against nodes that don't play to the default speaker. + The setting `workaround` is also optional and will default to an empty array. - When set, venmic will redirect the first node that matches the all of the specified properties to itself. + When set, venmic will redirect the first node that matches all of the specified properties to itself. * (GET) `/unlink` diff --git a/addon/addon.cpp b/addon/addon.cpp index da3791b..0abfeae 100644 --- a/addon/addon.cpp +++ b/addon/addon.cpp @@ -159,10 +159,11 @@ struct patchbay : public Napi::ObjectWrap return Napi::Boolean::New(env, false); } - auto include = to_array(data.Get("include")); - auto exclude = to_array(data.Get("exclude")); - auto ignore_devices = convert(data.Get("ignore_devices")); - auto workaround = to_array(data.Get("workaround")); + auto include = to_array(data.Get("include")); + auto exclude = to_array(data.Get("exclude")); + auto ignore_devices = convert(data.Get("ignore_devices")); + auto only_default_speakers = convert(data.Get("only_default_speakers")); + auto workaround = to_array(data.Get("workaround")); if (!include && !exclude) { @@ -174,10 +175,11 @@ struct patchbay : public Napi::ObjectWrap } vencord::patchbay::get().link({ - .include = include.value_or(std::vector{}), - .exclude = exclude.value_or(std::vector{}), - .ignore_devices = ignore_devices.value_or(true), - .workaround = workaround.value_or(std::vector{}), + .include = include.value_or(std::vector{}), + .exclude = exclude.value_or(std::vector{}), + .ignore_devices = ignore_devices.value_or(true), + .only_default_speakers = only_default_speakers.value_or(true), + .workaround = workaround.value_or(std::vector{}), }); return Napi::Boolean::New(env, true); diff --git a/include/vencord/patchbay.hpp b/include/vencord/patchbay.hpp index de8a2f6..9e7d0d8 100644 --- a/include/vencord/patchbay.hpp +++ b/include/vencord/patchbay.hpp @@ -18,8 +18,10 @@ namespace vencord std::vector include; std::vector exclude; - public: bool ignore_devices{true}; + bool only_default_speakers{true}; + + public: std::vector workaround; }; diff --git a/lib/module.d.ts b/lib/module.d.ts index 3e20b8f..b549b3f 100644 --- a/lib/module.d.ts +++ b/lib/module.d.ts @@ -22,6 +22,8 @@ export interface LinkData exclude: Prop[]; ignore_devices?: boolean; + only_default_speakers?: boolean; + workaround?: Prop[]; } diff --git a/package.json b/package.json index ddf97b9..582a172 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "private": false, "license": "MPL-2.0", "author": "Curve (https://github.com/Curve)", - "version": "3.3.5", + "version": "3.4.0", "main": "./lib/index.js", "types": "./lib/module.d.ts", "scripts": { diff --git a/server/main.cpp b/server/main.cpp index 7cddf15..8fe5a96 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -15,9 +15,10 @@ template <> struct glz::meta { using T = vencord::link_options; - static constexpr auto value = object("exclude", &T::exclude, // - "include", &T::include, // - "ignore_devices", &T::ignore_devices, // + static constexpr auto value = object("exclude", &T::exclude, // + "include", &T::include, // + "ignore_devices", &T::ignore_devices, // + "only_default_speakers", &T::only_default_speakers, // "workaround", &T::workaround); }; diff --git a/src/patchbay.impl.cpp b/src/patchbay.impl.cpp index 3be62ee..397a2d0 100644 --- a/src/patchbay.impl.cpp +++ b/src/patchbay.impl.cpp @@ -259,22 +259,30 @@ namespace vencord void patchbay::impl::on_link(std::uint32_t id) { - if (!speaker || !options.include.empty()) + if (!options.include.empty() || (options.only_default_speakers && !speaker)) { return; } auto &info = links[id]; - if (info.input.node != speaker->id) + const auto output_id = info.output.node; + const auto input_id = info.input.node; + + if (options.only_default_speakers && input_id != speaker->id) { - logger::get()->trace("[patchbay] (on_link) {} is not connected to speaker but with {}", id, - info.input.node); + logger::get()->trace("[patchbay] (on_link) {} is not connected to speaker but with {}", id, input_id); return; } - const auto node = info.output.node; - auto &output = nodes[node]; // The node emitting sound + auto &output = nodes[output_id]; // The node emitting sound + auto &input = nodes[input_id]; // The node receiving sound + + if (!options.only_default_speakers && input.info.props["device.id"].empty()) + { + logger::get()->trace("[patchbay] (on_link) {} is not playing to a device: {}", id, input_id); + return; + } auto match = [&output](const auto &prop) { @@ -288,7 +296,7 @@ namespace vencord core->update(); - link(node); + link(output_id); } void patchbay::impl::on_node(std::uint32_t id) @@ -439,9 +447,13 @@ namespace vencord logger::get()->info("[patchbay] (handle) found default metadata: {}", global.id); meta_listener->on( - [this](T &&...args) + [this](const char *key, auto property) { - meta_update(std::forward(args)...); + if (key) + { + meta_update(key, std::move(property)); + } + return 0; }); diff --git a/tests/node/api.test.js b/tests/node/api.test.js index 4f2f588..8b557f4 100644 --- a/tests/node/api.test.js +++ b/tests/node/api.test.js @@ -34,7 +34,10 @@ assert.throws(() => patchbay.link({ include: {} }), /key-value/ig); assert.doesNotThrow(() => patchbay.link({ include: [{ key: "node.name", value: "Firefox" }] })); assert.doesNotThrow(() => patchbay.link({ exclude: [{ key: "node.name", value: "Firefox" }] })); -assert.doesNotThrow(() => patchbay.link({ exclude: [{ key: "node.name", value: "Firefox" }], ignore_devices: true })); + assert.doesNotThrow(() => patchbay.link({ include: [{ key: "node.name", value: "Firefox" }], exclude: [{ key: "object.id", value: "100" }] })); +assert.doesNotThrow(() => patchbay.link({ exclude: [{ key: "node.name", value: "Firefox" }], ignore_devices: true })); +assert.doesNotThrow(() => patchbay.link({ exclude: [{ key: "node.name", value: "Firefox" }], ignore_devices: true, only_default_speakers: true })); + assert.doesNotThrow(() => patchbay.unlink());