Skip to content

Commit

Permalink
feat: allow include and exclude to be mixed
Browse files Browse the repository at this point in the history
  • Loading branch information
Curve committed Dec 4, 2023
1 parent 5653e08 commit b93b0f4
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 70 deletions.
2 changes: 1 addition & 1 deletion 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 2.1.4)
project(venmic LANGUAGES CXX VERSION 3.0.0)

# --------------------------------------------------------------------------------------------------------
# Library options
Expand Down
27 changes: 10 additions & 17 deletions addon/addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,35 +140,28 @@ struct patchbay : public Napi::ObjectWrap<patchbay>

auto data = info[0].ToObject();

if (!data.Has("props") || !data.Has("mode"))
if (!data.Has("include") && !data.Has("exclude"))
{
Napi::Error::New(env, "[venmic] expected keys 'props' and 'mode'").ThrowAsJavaScriptException();
return Napi::Boolean::New(env, false);
}

auto mode = convert<std::string>(data.Get("mode"));
auto props = to_array<vencord::prop>(data.Get("props"));

if (!mode || !props)
{
Napi::Error::New(env, "[venmic] expected 'mode' to be string and 'props' to be array of key-value pairs")
Napi::Error::New(env, "[venmic] expected at least one of keys 'include' or 'exclude'")
.ThrowAsJavaScriptException();

return Napi::Boolean::New(env, false);
}

if (mode.value() != "include" && mode.value() != "exclude")
auto include = to_array<vencord::prop>(data.Get("include"));
auto exclude = to_array<vencord::prop>(data.Get("exclude"));

if (!include && !exclude)
{
Napi::Error::New(env, "[venmic] expected mode to be either exclude or include")
Napi::Error::New(env, "[venmic] expected either 'include' or 'exclude' or both to be present and to be "
"arrays of key-value pairs")
.ThrowAsJavaScriptException();

return Napi::Boolean::New(env, false);
}

vencord::patchbay::get().link({
.mode = mode.value() == "include" ? vencord::target_mode::include : vencord::target_mode::exclude,
.props = props.value(),
});
vencord::patchbay::get().link(include.value_or(std::vector<vencord::prop>{}),
exclude.value_or(std::vector<vencord::prop>{}));

return Napi::Boolean::New(env, true);
}
Expand Down
10 changes: 2 additions & 8 deletions include/vencord/patchbay.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once

#include <map>
#include <vector>
#include <memory>
#include <string>
#include <cstdint>

namespace vencord
{
Expand All @@ -19,12 +19,6 @@ namespace vencord
std::string value;
};

struct target
{
target_mode mode;
std::vector<prop> props;
};

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

class patchbay
Expand All @@ -41,7 +35,7 @@ namespace vencord
patchbay();

public:
void link(target targets);
void link(std::vector<prop> include, std::vector<prop> exclude);

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: {props: Prop[], mode: "include" | "exclude"}): boolean;
link(data: {include: Prop[], exclude: Prop[]}): 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": "2.1.4",
"version": "3.0.0",
"main": "./lib/index.js",
"types": "./lib/module.d.ts",
"scripts": {
Expand Down
10 changes: 7 additions & 3 deletions private/message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ namespace vencord
std::vector<std::string> props;
};

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

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

struct target;

using pw_recipe = pw::recipe<list_nodes, target, unset_target, quit>;
using pw_recipe = pw::recipe<list_nodes, set_target, unset_target, quit>;
using cr_recipe = cr::recipe<std::vector<node>, ready>;
} // namespace vencord
5 changes: 3 additions & 2 deletions private/patchbay.impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ namespace vencord
std::unique_ptr<cr_recipe::receiver> receiver;

private:
std::optional<vencord::target> target;
std::multimap<std::uint32_t, pw::link> created;
std::vector<prop> include;
std::vector<prop> exclude;

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

private:
std::map<std::uint32_t, pw::link_info> links;
Expand Down
17 changes: 12 additions & 5 deletions server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ struct glz::meta<vencord::prop>
static constexpr auto value = object("key", &T::key, "value", &T::value);
};

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

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

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

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

if (error)
Expand All @@ -76,7 +83,7 @@ int main(int argc, char **args)
return;
}

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

response.status = 200;
});
Expand Down
4 changes: 2 additions & 2 deletions src/patchbay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ namespace vencord

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

void patchbay::link(target target)
void patchbay::link(std::vector<prop> include, std::vector<prop> exclude)
{
m_impl->sender->send(target);
m_impl->sender->send(set_target{.include = std::move(include), .exclude = std::move(exclude)});
}

void patchbay::unlink()
Expand Down
55 changes: 30 additions & 25 deletions src/patchbay.impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ namespace vencord
{
created.erase(id);

if (!mic)
{
return;
}

if (!nodes.contains(id))
{
return;
Expand Down Expand Up @@ -119,10 +124,10 @@ namespace vencord

for (auto &other : others)
{
auto link = core->create<pw::link>(pw::link_factory{
other.id,
port.id,
})
auto link = core->create<pw::link, pw::link_factory>({
other.id,
port.id,
})
.get();

if (!link.has_value())
Expand Down Expand Up @@ -258,12 +263,7 @@ namespace vencord

void patchbay::impl::on_link(std::uint32_t id)
{
if (!target || !speaker)
{
return;
}

if (target->mode != target_mode::exclude)
if (!include.empty() || !speaker)
{
return;
}
Expand All @@ -279,12 +279,12 @@ namespace vencord
// "Output" = the node that is emitting sound
auto &output = nodes[info.output.node];

auto match = [&](const auto &target)
auto match = [&](const auto &prop)
{
return output.info.props[target.key] == target.value;
return output.info.props[prop.key] == prop.value;
};

if (ranges::any_of(target->props, match))
if (ranges::any_of(exclude, match))
{
return;
}
Expand All @@ -296,24 +296,25 @@ namespace vencord

void patchbay::impl::on_node(std::uint32_t id)
{
if (!target)
if (include.empty())
{
return;
}

if (target->mode != target_mode::include)
auto match = [&](const auto &prop)
{
return;
}
return nodes[id].info.props[prop.key] == prop.value;
};

auto match = [&](const auto &target)
if (ranges::any_of(exclude, match))
{
return nodes[id].info.props[target.key] == target.value;
};
logger::get()->debug("ignoring {}: explicitly excluded", id);
return;
}

if (!ranges::any_of(target->props, match))
if (!ranges::any_of(include, match))
{
logger::get()->debug("ignoring {}: no props match", id);
logger::get()->debug("ignoring {}: no target matched", id);
return;
}

Expand Down Expand Up @@ -370,15 +371,17 @@ namespace vencord
}

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

created.clear();
target.emplace(std::move(req));

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

for (const auto &[id, info] : nodes)
{
Expand All @@ -394,7 +397,9 @@ namespace vencord
template <>
void patchbay::impl::receive([[maybe_unused]] cr_recipe::sender &, [[maybe_unused]] unset_target &)
{
target.reset();
include.clear();
exclude.clear();

created.clear();

mic.reset();
Expand Down
14 changes: 9 additions & 5 deletions tests/node/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ assert.throws(() => patchbay.list([10]), /expected list of strings/ig);

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

assert.throws(() => patchbay.link({ a: "A", b: "B", c: "C" }), /expected keys/ig);
assert.throws(() => patchbay.link({ key: "node.name", value: "Firefox", mode: "gibberish" }), /expected keys/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({ props: [{ a: 0, b: 0 }], mode: "gibberish" }), /key-value/ig);
assert.throws(() => patchbay.link({ props: [{ key: "", value: "" }], mode: "gibberish" }), /expected mode/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({ include: [{ key: "node.name", value: "Firefox" }], exclude: [{ key: "object.id", value: "100" }] }));

assert.doesNotThrow(() => patchbay.link({ props: [{ key: "node.name", value: "Firefox" }], mode: "include" }));
assert.doesNotThrow(() => patchbay.unlink());

0 comments on commit b93b0f4

Please sign in to comment.