Skip to content

Commit

Permalink
feat: add redirect-workaround (resolves #15)
Browse files Browse the repository at this point in the history
Much love to @wwmm for this awesome approach <3!
  • Loading branch information
Curve committed Jan 24, 2024
1 parent 90165dc commit 7e26e92
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 15 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ include("cmake/cpm.cmake")

CPMFindPackage(
NAME rohrkabel
VERSION 2.7
VERSION 3.0
GIT_REPOSITORY "https://github.com/Curve/rohrkabel"
)

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ The Rest-Server exposes three simple endpoints
[
{ "key": "node.name", "value": "Chrome" }
]
"ignore_devices": true
"ignore_devices": true,
"workaround": [{ "key": "node.name", "value": "Chrome" }]
}
</pre>

Expand All @@ -50,6 +51,9 @@ 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 `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.
</blockquote>

* (GET) `/unlink`
Expand Down
2 changes: 2 additions & 0 deletions addon/addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ struct patchbay : public Napi::ObjectWrap<patchbay>
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"));
auto workaround = convert<vencord::prop>(data.Get("workaround"));

if (!include && !exclude)
{
Expand All @@ -176,6 +177,7 @@ struct patchbay : public Napi::ObjectWrap<patchbay>
.include = include.value_or(std::vector<vencord::prop>{}),
.exclude = exclude.value_or(std::vector<vencord::prop>{}),
.ignore_devices = ignore_devices.value_or(true),
.workaround = workaround,
});

return Napi::Boolean::New(env, true);
Expand Down
1 change: 1 addition & 0 deletions include/vencord/patchbay.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace vencord

public:
bool ignore_devices{true};
std::vector<prop> workaround;
};

using node = std::map<std::string, std::string>;
Expand Down
1 change: 1 addition & 0 deletions lib/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface LinkData
exclude: Prop[];

ignore_devices?: boolean;
workaround?: Prop;
}


Expand Down
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": "MPL-2.0",
"author": "Curve (https://github.com/Curve)",
"version": "3.2.3",
"version": "3.3.0",
"main": "./lib/index.js",
"types": "./lib/module.d.ts",
"scripts": {
Expand Down
5 changes: 5 additions & 0 deletions private/patchbay.impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ namespace vencord
std::shared_ptr<pw::core> core;
std::shared_ptr<pw::registry> registry;

private:
std::unique_ptr<pw::metadata> metadata;
std::optional<std::uint32_t> lettuce_target; // https://github.com/Vencord/venmic/issues/15

private:
std::atomic_bool should_exit{false};

Expand All @@ -63,6 +67,7 @@ namespace vencord

private:
void create_mic();
void cleanup(bool);
void relink(std::uint32_t);

private:
Expand Down
7 changes: 4 additions & 3 deletions server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ template <>
struct glz::meta<vencord::link_options>
{
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, //
"workaround", &T::workaround);
};

int main(int argc, char **args)
Expand Down
70 changes: 61 additions & 9 deletions src/patchbay.impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ namespace vencord

patchbay::impl::~impl()
{
cleanup(true);
should_exit = true;
sender->send(quit{});

sender->send(quit{});
thread.join();
}

Expand Down Expand Up @@ -67,6 +68,24 @@ namespace vencord
virt_mic = std::make_unique<pw::node>(std::move(*node));
}

void patchbay::impl::cleanup(bool mic)
{
created.clear();

if (metadata && lettuce_target)
{
metadata->clear_property(lettuce_target.value(), "target.node");
metadata->clear_property(lettuce_target.value(), "target.object");
}

if (!mic)
{
return;
}

virt_mic.reset();
}

void patchbay::impl::relink(std::uint32_t id)
{
created.erase(id);
Expand Down Expand Up @@ -165,10 +184,40 @@ namespace vencord

nodes[id].info = node.info();

logger::get()->trace("[patchbay] (add_global) new node: {} (name: \"{}\", app: \"{}\")", node.id(),
props["node.name"], props["application.name"]);
logger::get()->trace(R"([patchbay] (add_global) new node: {} (name: "{}", app: "{}"))", id, props["node.name"],
props["application.name"]);

if (options.workaround.empty() || !metadata || !virt_mic)
{
return on_node(id);
}

logger::get()->trace("[patchbay] (add_global) workaround is active ({})", glz::write_json(options.workaround));

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

if (!ranges::all_of(options.workaround, match))
{
return on_node(id);
}

const auto serial = virt_mic->info().props["object.serial"];

on_node(id);
logger::get()->debug("[patchbay] (add_global) applying workaround to {} (mic = {}, serial = {})", id,
virt_mic->id(), serial);

// https://github.com/Vencord/venmic/issues/13#issuecomment-1884975782

metadata->set_property(id, "target.object", "Spa:Id", serial);
metadata->set_property(id, "target.node", "Spa:Id", fmt::format("{}", virt_mic->id()));

lettuce_target.emplace(id);
options.workaround.clear();

core->update();
}

template <>
Expand Down Expand Up @@ -212,13 +261,17 @@ namespace vencord
template <>
void patchbay::impl::add_global<pw::metadata>(pw::metadata &data)
{
auto props = data.properties();
auto props = data.properties();
const auto name = data.props()["metadata.name"];

if (!props.contains("default.audio.sink"))
if (name != "default")
{
return;
}

metadata = std::make_unique<pw::metadata>(std::move(data));
logger::get()->info("[patchbay] (add_global) found metadata: {}", metadata->id());

auto parsed = glz::read_json<pw_metadata_name>(props["default.audio.sink"].value);

if (!parsed.has_value())
Expand Down Expand Up @@ -405,7 +458,7 @@ namespace vencord
create_mic();
}

created.clear();
cleanup(false);

options = std::move(req);

Expand All @@ -423,8 +476,7 @@ namespace vencord
template <>
void patchbay::impl::receive([[maybe_unused]] cr_recipe::sender &, [[maybe_unused]] unset_target &)
{
created.clear();
virt_mic.reset();
cleanup(true);
}

template <>
Expand Down

0 comments on commit 7e26e92

Please sign in to comment.