Skip to content

Commit

Permalink
feat: add ignore_devices
Browse files Browse the repository at this point in the history
* This setting will prevent hardware-devices like microphones and speakers from being linked to the virtual microphone
  • Loading branch information
Curve committed Jan 5, 2024
1 parent dda4f0e commit 59edf32
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 62 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.21)
project(venmic LANGUAGES CXX VERSION 3.1.0)
project(venmic LANGUAGES CXX VERSION 3.2.0)

# --------------------------------------------------------------------------------------------------------
# Library options
Expand Down Expand Up @@ -99,7 +99,7 @@ CPMFindPackage(

CPMFindPackage(
NAME glaze
VERSION 1.9.7
VERSION 2.0.2
GIT_REPOSITORY "https://github.com/stephenberry/glaze"
)

Expand Down
23 changes: 19 additions & 4 deletions addon/addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ std::optional<std::string> convert(Napi::Value value)
return value.ToString();
}

template <>
std::optional<bool> convert(Napi::Value value)
{
if (!value.IsBoolean())
{
return std::nullopt;
}

return value.ToBoolean();
}

template <>
std::optional<vencord::prop> convert(Napi::Value value)
{
Expand Down Expand Up @@ -148,8 +159,9 @@ struct patchbay : public Napi::ObjectWrap<patchbay>
return Napi::Boolean::New(env, false);
}

auto include = to_array<vencord::prop>(data.Get("include"));
auto exclude = to_array<vencord::prop>(data.Get("exclude"));
auto include = to_array<vencord::prop>(data.Get("include"));
auto exclude = to_array<vencord::prop>(data.Get("exclude"));
auto ignore_devices = convert<bool>(data.Get("ignore_devices"));

if (!include && !exclude)
{
Expand All @@ -160,8 +172,11 @@ struct patchbay : public Napi::ObjectWrap<patchbay>
return Napi::Boolean::New(env, false);
}

vencord::patchbay::get().link(include.value_or(std::vector<vencord::prop>{}),
exclude.value_or(std::vector<vencord::prop>{}));
vencord::patchbay::get().link({
.include = include.value_or(std::vector<vencord::prop>{}),
.exclude = exclude.value_or(std::vector<vencord::prop>{}),
.ignore_devices = ignore_devices.value_or(true),
});

return Napi::Boolean::New(env, true);
}
Expand Down
11 changes: 10 additions & 1 deletion include/vencord/patchbay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ namespace vencord
std::string value;
};

struct link_options
{
std::vector<prop> include;
std::vector<prop> exclude;

public:
bool ignore_devices{true};
};

using node = std::map<std::string, std::string>;

class patchbay
Expand All @@ -29,7 +38,7 @@ namespace vencord
patchbay();

public:
void link(std::vector<prop> include, std::vector<prop> exclude);
void link(link_options options);

public:
void unlink();
Expand Down
2 changes: 1 addition & 1 deletion lib/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class PatchBay
unlink(): void;

list<T extends string = DefaultProps>(props?: T[]): Record<LiteralUnion<T, string>, string>[];
link(data: {include: Prop[], exclude: Prop[]}): boolean;
link(data: {include: Prop[], exclude: Prop[], ignore_devices?: boolean}): boolean;

static hasPipeWire(): boolean;
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"private": false,
"license": "MIT",
"author": "Curve (https://github.com/Curve)",
"version": "3.1.0",
"version": "3.2.0",
"main": "./lib/index.js",
"types": "./lib/module.d.ts",
"scripts": {
Expand Down
9 changes: 2 additions & 7 deletions private/message.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once

#include "patchbay.hpp"

#include <string>
Expand All @@ -15,12 +16,6 @@ namespace vencord
std::vector<std::string> props;
};

struct set_target
{
std::vector<prop> include;
std::vector<prop> exclude;
};

struct unset_target
{
};
Expand All @@ -34,6 +29,6 @@ namespace vencord
bool success{true};
};

using pw_recipe = pw::recipe<list_nodes, set_target, unset_target, quit>;
using pw_recipe = pw::recipe<list_nodes, link_options, unset_target, quit>;
using cr_recipe = cr::recipe<std::vector<node>, ready>;
} // namespace vencord
6 changes: 3 additions & 3 deletions private/patchbay.impl.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once

#include "patchbay.hpp"
#include "message.hpp"

Expand Down Expand Up @@ -36,11 +37,10 @@ namespace vencord
std::unique_ptr<cr_recipe::receiver> receiver;

private:
std::vector<prop> include;
std::vector<prop> exclude;
link_options options;

private:
std::unique_ptr<pw::node> mic;
std::unique_ptr<pw::node> virt_mic;
std::optional<vencord::speaker> speaker;
std::multimap<std::uint32_t, pw::link> created;

Expand Down
18 changes: 7 additions & 11 deletions server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
#include <vencord/logger.hpp>
#include <vencord/patchbay.hpp>

struct targets
{
std::vector<vencord::prop> include;
std::vector<vencord::prop> exclude;
};

template <>
struct glz::meta<vencord::prop>
{
Expand All @@ -18,10 +12,12 @@ struct glz::meta<vencord::prop>
};

template <>
struct glz::meta<targets>
struct glz::meta<vencord::link_options>
{
using T = targets;
static constexpr auto value = object("include", &T::include, "exclude", &T::exclude);
using T = vencord::link_options;
static constexpr auto value = object("exclude", &T::exclude, //
"include", &T::include, //
"ignore_devices", &T::ignore_devices);
};

int main(int argc, char **args)
Expand Down Expand Up @@ -63,7 +59,7 @@ int main(int argc, char **args)
server.Post("/link",
[](const auto &req, auto &response)
{
targets parsed;
vencord::link_options parsed;

auto error = glz::read<glz::opts{.error_on_missing_keys = true}>(parsed, req.body);

Expand All @@ -73,7 +69,7 @@ int main(int argc, char **args)
return;
}

patchbay::get().link(parsed.include, parsed.exclude);
patchbay::get().link(std::move(parsed));

response.status = 200;
});
Expand Down
8 changes: 3 additions & 5 deletions src/patchbay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,10 @@ namespace vencord

patchbay::patchbay() : m_impl(std::make_unique<impl>()) {}

void patchbay::link(std::vector<prop> include, std::vector<prop> exclude)
void patchbay::link(link_options options)
{
const auto request = set_target{std::move(include), std::move(exclude)};
m_impl->sender->send(request);

logger::get()->trace(R"([patchbay] (link) request: "{}")", glz::write_json(request));
m_impl->sender->send(std::move(options));
logger::get()->trace(R"([patchbay] (link) request: "{}")", glz::write_json(options));
}

void patchbay::unlink()
Expand Down
49 changes: 25 additions & 24 deletions src/patchbay.impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
#include <glaze/glaze.hpp>

#include <range/v3/view.hpp>
#include <range/v3/range.hpp>

#include <range/v3/action.hpp>
#include <range/v3/algorithm.hpp>

#include <rohrkabel/device/device.hpp>

namespace vencord
{
struct pw_metadata_name
Expand Down Expand Up @@ -65,14 +64,14 @@ namespace vencord
core->update();
}

mic = std::make_unique<pw::node>(std::move(*node));
virt_mic = std::make_unique<pw::node>(std::move(*node));
}

void patchbay::impl::relink(std::uint32_t id)
{
created.erase(id);

if (!mic)
if (!virt_mic)
{
return;
}
Expand All @@ -82,16 +81,23 @@ namespace vencord
return;
}

if (id == mic->id())
if (id == virt_mic->id())
{
logger::get()->warn("[patchbay] (relink) prevented link to self", id, mic->id());
logger::get()->warn("[patchbay] (relink) prevented link to self", id, virt_mic->id());
return;
}

logger::get()->debug("[patchbay] (relink) linking {} [with mic = {}]", id, mic->id());

auto &target = nodes[id];
auto &source = nodes[mic->id()];

if (options.ignore_devices && !target.info.props["device.id"].empty())
{
logger::get()->warn("[patchbay] (relink) prevented link to device", id, virt_mic->id());
return;
}

logger::get()->debug("[patchbay] (relink) linking {} [with mic = {}]", id, virt_mic->id());

auto &source = nodes[virt_mic->id()];

auto is_output = [](const auto &item)
{
Expand Down Expand Up @@ -275,7 +281,7 @@ namespace vencord

void patchbay::impl::on_link(std::uint32_t id)
{
if (!include.empty() || !speaker)
if (!options.include.empty() || !speaker)
{
return;
}
Expand All @@ -297,7 +303,7 @@ namespace vencord
return output.info.props[prop.key] == prop.value;
};

if (ranges::any_of(exclude, match))
if (ranges::any_of(options.exclude, match))
{
return;
}
Expand All @@ -317,7 +323,7 @@ namespace vencord
speaker->id = id;
}

if (include.empty())
if (options.include.empty())
{
return;
}
Expand All @@ -327,13 +333,13 @@ namespace vencord
return info.props[prop.key] == prop.value;
};

if (ranges::any_of(exclude, match))
if (ranges::any_of(options.exclude, match))
{
logger::get()->debug("[patchbay] (on_node) {} is excluded", id);
return;
}

if (!ranges::any_of(include, match))
if (!ranges::any_of(options.include, match))
{
logger::get()->debug("[patchbay] (on_node) {} is not included", id);
return;
Expand Down Expand Up @@ -392,17 +398,16 @@ namespace vencord
}

template <>
void patchbay::impl::receive([[maybe_unused]] cr_recipe::sender &, set_target &req)
void patchbay::impl::receive([[maybe_unused]] cr_recipe::sender &, link_options &req)
{
if (!mic)
if (!virt_mic)
{
create_mic();
}

created.clear();

include = std::move(req.include);
exclude = std::move(req.exclude);
options = std::move(req);

for (const auto &[id, info] : nodes)
{
Expand All @@ -418,12 +423,8 @@ namespace vencord
template <>
void patchbay::impl::receive([[maybe_unused]] cr_recipe::sender &, [[maybe_unused]] unset_target &)
{
include.clear();
exclude.clear();

created.clear();

mic.reset();
virt_mic.reset();
}

template <>
Expand Down
7 changes: 4 additions & 3 deletions tests/node/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@ assert.throws(() => patchbay.list([10]), /expected list of strings/ig);

assert.throws(() => patchbay.link(10), /expected link object/ig);

assert.throws(() => patchbay.link({ }), /'include' and 'exclude'/ig);
assert.throws(() => patchbay.link({ a: "A", b: "B", c: "C" }), /'include' and 'exclude'/ig);
assert.throws(() => patchbay.link({ key: "node.name", value: "Firefox", mode: "gibberish" }), /'include' and 'exclude'/ig);
assert.throws(() => patchbay.link({ }), /'include' or 'exclude'/ig);
assert.throws(() => patchbay.link({ a: "A", b: "B", c: "C" }), /'include' or 'exclude'/ig);
assert.throws(() => patchbay.link({ key: "node.name", value: "Firefox", mode: "gibberish" }), /'include' or 'exclude'/ig);

assert.throws(() => patchbay.link({ include: "Firefox" }), /key-value/ig);
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.unlink());

0 comments on commit 59edf32

Please sign in to comment.