diff --git a/.gitmodules b/.gitmodules index 900b7d9..66f963b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "submodules/rohrkabel"] path = submodules/rohrkabel url = https://github.com/Soundux/rohrkabel +[submodule "submodules/channel"] + path = submodules/channel + url = https://github.com/Soundux/channel.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 48544ac..8e7d853 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,15 +63,20 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") endif() endif() -if(NOT EXISTS "${PROJECT_SOURCE_DIR}/submodules/rohrkabel/CMakeLists.txt") - message(FATAL_ERROR "Rohrkabel was not found since you are not in a Git checkout or have GIT_SUBMODULE disabled. Please provide rohrkabel manually to `./submodules/rohrkabel`.") -endif() +function(add_git_subdirectory SUBMODULE) + if(NOT EXISTS "${PROJECT_SOURCE_DIR}/submodules/${SUBMODULE}/CMakeLists.txt") + message(FATAL_ERROR "Submodule ${SUBMODULE} was not found since you are not in a Git checkout or have GIT_SUBMODULE disabled. Please provide ${SUBMODULE} manually to `./submodules/${SUBMODULE}`.") + endif() -add_subdirectory(submodules/rohrkabel) + add_subdirectory(submodules/${SUBMODULE}) +endfunction() + +add_git_subdirectory(rohrkabel) +add_git_subdirectory(channel) add_executable(discord-screenaudio ${discord-screenaudio_SRC}) -target_link_libraries(discord-screenaudio Qt::Widgets Qt::WebEngineWidgets rohrkabel) +target_link_libraries(discord-screenaudio Qt::Widgets Qt::WebEngineWidgets rohrkabel channel) if(KF5Notifications_FOUND) target_link_libraries(discord-screenaudio KF5::Notifications) diff --git a/src/main.cpp b/src/main.cpp index df1fec8..61f3ada 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) { if (parser.isSet(virtmicOption)) { Virtmic::start(parser.value(virtmicOption)); + return 0; } qputenv("QTWEBENGINE_CHROMIUM_FLAGS", diff --git a/src/userscript.cpp b/src/userscript.cpp index 9402907..7474dbf 100644 --- a/src/userscript.cpp +++ b/src/userscript.cpp @@ -42,8 +42,12 @@ void UserScript::setupHelpMenu() { aboutData.addCredit( "Curve", "For creating the Rohrkabel library used in this project.", QString(), "https://github.com/Curve"); - aboutData.addComponent("Rohrkabel", "A C++ RAII Pipewire-API Wrapper", "1.3", + aboutData.addComponent("Rohrkabel", "A C++ RAII Pipewire-API Wrapper", "1.5", "https://github.com/Soundux/rohrkabel"); + aboutData.addComponent( + "Soundux/channel ", + "A C++ implementation of Rust's std::sync::mpsc::channel", nullptr, + "https://github.com/Soundux/channel"); m_helpMenu = new KHelpMenu(MainWindow::instance(), aboutData); #endif } diff --git a/src/virtmic.cpp b/src/virtmic.cpp index 2c0ba4f..97a372c 100644 --- a/src/virtmic.cpp +++ b/src/virtmic.cpp @@ -1,196 +1,13 @@ #include "virtmic.h" #include "log.h" -#include -#include +#include +#include namespace Virtmic { -const QStringList EXCLUDE_TARGETS{"Chromium input", "discord-screenaudio"}; +QVector getTargets() { return QVector{}; } -QVector getTargets() { - auto main_loop = pipewire::main_loop(); - auto context = pipewire::context(main_loop); - auto core = pipewire::core(context); - auto reg = pipewire::registry(core); - - QVector targets; - - auto reg_listener = reg.listen(); - reg_listener.on( - [&](const pipewire::global &global) { - if (global.type == pipewire::node::type) { - auto node = reg.bind(global.id); - auto info = node.info(); - QString name; - if (info.props.count("application.name") && - info.props["application.name"] != "") - name = QString::fromStdString(info.props["application.name"]); - else - name = QString::fromStdString( - info.props["application.process.binary"]); - - if (name != "" && !EXCLUDE_TARGETS.contains(name) && - !targets.contains(name)) { - targets.append(name); - } - } - }); - core.update(); - - return targets; -} - -void start(QString _target) { - std::map ports; - std::unique_ptr virt_fl, virt_fr; - - std::map nodes; - std::map links; - - auto main_loop = pipewire::main_loop(); - auto context = pipewire::context(main_loop); - auto core = pipewire::core(context); - auto reg = pipewire::registry(core); - - auto link = [&](const std::string &target, pipewire::core &core) { - for (const auto &[port_id, port] : ports) { - if (!virt_fl || !virt_fr) - continue; - - if (links.count(port_id)) - continue; - - if (port.info().direction == pipewire::port_direction::input) - continue; - - if (!port.info().props.count("node.id")) - continue; - - auto parent_id = std::stoul(port.info().props["node.id"]); - - if (!nodes.count(parent_id)) - continue; - - auto &parent = nodes.at(parent_id); - std::string name; - if (parent.props.count("application.name") && - parent.props["application.name"] != "") - name = parent.props["application.name"]; - else - name = parent.props["application.process.binary"]; - - if (name == target || - (target == "[All Desktop Audio]" && - !EXCLUDE_TARGETS.contains(QString::fromStdString(name)))) { - auto fl = port.info().props["audio.channel"] == "FL"; - links.emplace( - port_id, - core.create( - {fl ? virt_fl->info().id : virt_fr->info().id, port_id})); - qDebug(virtmicLog) << QString("Link: %1:%2 -> %3") - .arg(QString::fromStdString(name)) - .arg(port_id) - .arg(fl ? virt_fl->info().id - : virt_fr->info().id) - .toUtf8() - .data(); - } - } - }; - - std::string target = _target.toLatin1().toStdString(); - - auto virtual_mic = core.create("adapter", - {{"node.name", "discord-screenaudio-virtmic"}, - {"media.class", "Audio/Source/Virtual"}, - {"factory.name", "support.null-audio-sink"}, - {"audio.channels", "2"}, - {"audio.position", "FL,FR"}}, - pipewire::node::type, pipewire::node::version, - pipewire::update_strategy::none); - - if (target == "[None]") { - while (true) { - main_loop.run(); - } - return; - } - - auto reg_events = reg.listen(); - reg_events.on( - [&](const pipewire::global &global) { - if (global.type == pipewire::node::type) { - auto node = reg.bind(global.id); - auto info = node.info(); - std::string name; - if (info.props.count("application.name") && - info.props["application.name"] != "") - name = info.props["application.name"]; - else if (info.props.count("application.process.binary")) { - name = info.props["application.process.binary"]; - } else - return; - qDebug(virtmicLog) << QString("Added: %1") - .arg(QString::fromStdString(name)) - .toUtf8() - .data(); - - if (!nodes.count(global.id)) { - nodes.emplace(global.id, node.info()); - link(target, core); - } - } - if (global.type == pipewire::port::type) { - auto port = reg.bind(global.id); - auto info = port.info(); - - if (info.props.count("node.id")) { - auto node_id = std::stoul(info.props["node.id"]); - - if (node_id == virtual_mic.id() && - info.direction == pipewire::port_direction::input) { - if (info.props["audio.channel"] == "FL") { - virt_fl = std::make_unique(std::move(port)); - } else { - virt_fr = std::make_unique(std::move(port)); - } - } else { - ports.emplace(global.id, std::move(port)); - } - - link(target, core); - } - } - }); - - reg_events.on( - [&](const std::uint32_t id) { - if (nodes.count(id)) { - auto info = nodes.at(id); - std::string name; - if (info.props.count("application.name") && - info.props["application.name"] != "") - name = info.props["application.name"]; - else - name = info.props["application.process.binary"]; - qDebug(virtmicLog) << QString("Removed: %1") - .arg(QString::fromStdString(name)) - .toUtf8() - .data(); - nodes.erase(id); - } - if (ports.count(id)) { - ports.erase(id); - } - if (links.count(id)) { - links.erase(id); - } - }); - - while (true) { - main_loop.run(); - } -} +void start(QString _target) {} } // namespace Virtmic diff --git a/submodules/channel b/submodules/channel new file mode 160000 index 0000000..6977815 --- /dev/null +++ b/submodules/channel @@ -0,0 +1 @@ +Subproject commit 6977815409b4c3c02d74a7aee3fc29f01d632feb diff --git a/submodules/rohrkabel b/submodules/rohrkabel index 04bfb92..8a7705b 160000 --- a/submodules/rohrkabel +++ b/submodules/rohrkabel @@ -1 +1 @@ -Subproject commit 04bfb921c44fb0d2337df70f5660899bc8d2844f +Subproject commit 8a7705be070190a88b9a9d3619fa2fb7eabc951e