Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd2aca55c7 | ||
|
|
8a6f49b949 | ||
|
|
47fd620876 | ||
|
|
c15250498b | ||
|
|
6f0303206e | ||
|
|
6e86647c95 | ||
|
|
798fb3d5e4 | ||
|
|
6c9b76ed90 | ||
|
|
b582584c69 | ||
|
|
7b6e8fc473 | ||
|
|
8f0a810539 | ||
|
|
a6eb82948f | ||
|
|
24727f398a | ||
|
|
c43e9953a5 | ||
|
|
08cb713e8c | ||
|
|
27faed4a3a | ||
|
|
10fff86ca4 | ||
|
|
87e84dec5c | ||
|
|
4b782133ae | ||
|
|
423884ae0c | ||
|
|
7ea3d0aab1 | ||
|
|
18b15f5cf4 | ||
|
|
3540774c82 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
/build
|
||||
.vscode
|
||||
/submodules/arrpc
|
||||
|
||||
@@ -45,6 +45,7 @@ set(discord-screenaudio_SRC
|
||||
src/log.cpp
|
||||
src/userscript.cpp
|
||||
src/centralwidget.cpp
|
||||
src/localserver.cpp
|
||||
resources.qrc
|
||||
)
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ You have multiple options:
|
||||
With apt:
|
||||
`apt install -y build-essential cmake qtbase5-dev qtwebengine5-dev libkf5notifications-dev libkf5xmlgui-dev libkf5globalaccel-dev pkg-config libpipewire-0.3-dev git`
|
||||
|
||||
With dnf:
|
||||
`dnf install @development-tools cmake qt5-qtbase-devel qt5-qtwebengine-devel kf5-knotifications-devel kf5-kxmlgui-devel kf5-kglobalaccel-devel pkgconfig pipewire-devel git`
|
||||
|
||||
### Building
|
||||
|
||||
First, clone the repository:
|
||||
|
||||
1
assets/arrpc.js
Normal file
1
assets/arrpc.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/arrpc_bridge_mod.js
Normal file
1
assets/arrpc_bridge_mod.js
Normal file
@@ -0,0 +1 @@
|
||||
setTimeout((i=>{let t,a,s,e={};new WebSocket("ws://127.0.0.1:1337").onmessage=async i=>{if(msg=JSON.parse(i.data),console.log(msg),!t){const i=window.webpackChunkdiscord_app.push([[Symbol()],{},i=>i]),e=i.c;window.webpackChunkdiscord_app.pop();for(const i in e){let a=e[i].exports;if(a=a&&(a.Z??a.ZP),a&&a.register&&a.wait){t=a;break}}const n=i.m;for(const t in n)if(n[t].toString().includes("getAssetImage: size must === [number, number] for Twitch")){const s=i(t),e=Object.values(s).find((i=>"function"==typeof i&&i.toString().includes("apply(")));a=async(i,t)=>(await e(i,[t,void 0]))[0];break}for(const t in n)if(n[t].toString().includes("e.application={")){const a=i(t),e=Object.values(a).find((i=>"function"==typeof i&&i.toString().includes("e.application={")));s=async i=>{let t={};return await e(t,i),t.application};break}}if(msg.activity?.assets?.large_image&&(msg.activity.assets.large_image=await a(msg.activity.application_id,msg.activity.assets.large_image)),msg.activity?.assets?.small_image&&(msg.activity.assets.small_image=await a(msg.activity.application_id,msg.activity.assets.small_image)),msg.activity){const i=msg.activity.application_id;e[i]||(e[i]=await s(i));const t=e[i];msg.activity.name||(msg.activity.name=t.name)}t.dispatch({type:"LOCAL_ACTIVITY_UPDATE",...msg})}}),1e4);
|
||||
@@ -1,65 +0,0 @@
|
||||
setTimeout(e => {
|
||||
let Dispatcher, lookupAsset, lookupApp, apps = {};
|
||||
|
||||
const ws = new WebSocket('ws://127.0.0.1:1337'); // connect to arRPC bridge websocket
|
||||
ws.onmessage = async x => {
|
||||
msg = JSON.parse(x.data);
|
||||
console.log(msg);
|
||||
|
||||
if (!Dispatcher) {
|
||||
const wpRequire = window.webpackChunkdiscord_app.push([[Symbol()], {}, x => x]);
|
||||
const cache = wpRequire.c;
|
||||
window.webpackChunkdiscord_app.pop();
|
||||
|
||||
for (const id in cache) {
|
||||
let mod = cache[id].exports;
|
||||
mod = mod && (mod.Z ?? mod.ZP);
|
||||
|
||||
if (mod && mod.register && mod.wait) {
|
||||
Dispatcher = mod;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const factories = wpRequire.m;
|
||||
for (const id in factories) {
|
||||
if (factories[id].toString().includes('getAssetImage: size must === [number, number] for Twitch')) {
|
||||
const mod = wpRequire(id);
|
||||
|
||||
const _lookupAsset = Object.values(mod).find(e => typeof e === "function" && e.toString().includes("apply("));
|
||||
lookupAsset = async (appId, name) => (await _lookupAsset(appId, [name, undefined]))[0];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const id in factories) {
|
||||
if (factories[id].toString().includes(`e.application={`)) {
|
||||
const mod = wpRequire(id);
|
||||
|
||||
const _lookupApp = Object.values(mod).find(e => typeof e === "function" && e.toString().includes(`e.application={`));
|
||||
lookupApp = async appId => {
|
||||
let socket = {};
|
||||
await _lookupApp(socket, appId);
|
||||
return socket.application;
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.activity?.assets?.large_image) msg.activity.assets.large_image = await lookupAsset(msg.activity.application_id, msg.activity.assets.large_image);
|
||||
if (msg.activity?.assets?.small_image) msg.activity.assets.small_image = await lookupAsset(msg.activity.application_id, msg.activity.assets.small_image);
|
||||
|
||||
if (msg.activity) {
|
||||
const appId = msg.activity.application_id;
|
||||
if (!apps[appId]) apps[appId] = await lookupApp(appId);
|
||||
|
||||
const app = apps[appId];
|
||||
if (!msg.activity.name) msg.activity.name = app.name;
|
||||
}
|
||||
|
||||
Dispatcher.dispatch({ type: "LOCAL_ACTIVITY_UPDATE", ...msg }); // set RPC status
|
||||
};
|
||||
}, 10000)
|
||||
@@ -1,12 +1,14 @@
|
||||
navigator.mediaDevices.chromiumGetDisplayMedia =
|
||||
navigator.mediaDevices.getDisplayMedia;
|
||||
navigator.mediaDevices.chromiumGetUserMedia =
|
||||
navigator.mediaDevices.getUserMedia;
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
const getAudioDevice = async (nameOfAudioDevice) => {
|
||||
await navigator.mediaDevices.getUserMedia({
|
||||
await navigator.mediaDevices.chromiumGetUserMedia({
|
||||
audio: true,
|
||||
});
|
||||
let audioDevice;
|
||||
@@ -23,6 +25,16 @@ const getAudioDevice = async (nameOfAudioDevice) => {
|
||||
return audioDevice;
|
||||
};
|
||||
|
||||
function setGetUserMedia() {
|
||||
const getUserMedia = async (constraints) => {
|
||||
return await navigator.mediaDevices.chromiumGetUserMedia({
|
||||
video: constraints?.video || false,
|
||||
audio: { ...constraints?.audio, autoGainControl },
|
||||
});
|
||||
};
|
||||
navigator.mediaDevices.getUserMedia = getUserMedia;
|
||||
}
|
||||
|
||||
function setGetDisplayMedia(video = true, overrideArgs = undefined) {
|
||||
const getDisplayMedia = async (...args) => {
|
||||
var id;
|
||||
@@ -34,26 +46,27 @@ function setGetDisplayMedia(video = true, overrideArgs = undefined) {
|
||||
} catch (error) {
|
||||
id = "default";
|
||||
}
|
||||
let captureSystemAudioStream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
// We add our audio constraints here, to get a list of supported constraints use navigator.mediaDevices.getSupportedConstraints();
|
||||
// We must capture a microphone, we use default since its the only deviceId that is the same for every Chromium user
|
||||
deviceId: {
|
||||
exact: id,
|
||||
let captureSystemAudioStream =
|
||||
await navigator.mediaDevices.chromiumGetUserMedia({
|
||||
audio: {
|
||||
// We add our audio constraints here, to get a list of supported constraints use navigator.mediaDevices.getSupportedConstraints();
|
||||
// We must capture a microphone, we use default since its the only deviceId that is the same for every Chromium user
|
||||
deviceId: {
|
||||
exact: id,
|
||||
},
|
||||
// We want auto gain control, noise cancellation and noise suppression disabled so that our stream won't sound bad
|
||||
autoGainControl: false,
|
||||
echoCancellation: false,
|
||||
noiseSuppression: false,
|
||||
// By default Chromium sets channel count for audio devices to 1, we want it to be stereo in case we find a way for Discord to accept stereo screenshare too
|
||||
channelCount: 2,
|
||||
// You can set more audio constraints here, bellow are some examples
|
||||
//latency: 0,
|
||||
//sampleRate: 48000,
|
||||
//sampleSize: 16,
|
||||
//volume: 1.0
|
||||
},
|
||||
// We want auto gain control, noise cancellation and noise suppression disabled so that our stream won't sound bad
|
||||
autoGainControl: false,
|
||||
echoCancellation: false,
|
||||
noiseSuppression: false,
|
||||
// By default Chromium sets channel count for audio devices to 1, we want it to be stereo in case we find a way for Discord to accept stereo screenshare too
|
||||
channelCount: 2,
|
||||
// You can set more audio constraints here, bellow are some examples
|
||||
//latency: 0,
|
||||
//sampleRate: 48000,
|
||||
//sampleSize: 16,
|
||||
//volume: 1.0
|
||||
},
|
||||
});
|
||||
});
|
||||
let [track] = captureSystemAudioStream.getAudioTracks();
|
||||
const gdm = await navigator.mediaDevices.chromiumGetDisplayMedia(
|
||||
...(overrideArgs
|
||||
@@ -68,6 +81,7 @@ function setGetDisplayMedia(video = true, overrideArgs = undefined) {
|
||||
}
|
||||
|
||||
setGetDisplayMedia();
|
||||
setGetUserMedia();
|
||||
|
||||
let userscript;
|
||||
let muteBtn;
|
||||
@@ -76,6 +90,7 @@ let streamStartBtn;
|
||||
let streamStartBtnInitialDisplay;
|
||||
let streamStartBtnClone;
|
||||
let resolutionString;
|
||||
let autoGainControl = true;
|
||||
const clonedElements = [];
|
||||
const hiddenElements = [];
|
||||
let wasStreamActive = false;
|
||||
@@ -159,6 +174,10 @@ function main() {
|
||||
streamStartBtnClone.remove();
|
||||
});
|
||||
|
||||
userscript.getPref("disableAutomaticGain", false).then((disabled) => {
|
||||
autoGainControl = !disabled;
|
||||
});
|
||||
|
||||
function updateUserstyles() {
|
||||
userscript.log("Loading userstyles...");
|
||||
userscript.loadingMessage = "Loading userstyles...";
|
||||
@@ -368,5 +387,29 @@ function main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const el of document.getElementsByClassName("sensitivity-3A7Gs9")) {
|
||||
if (
|
||||
el.getElementsByTagName("div").length > 0 &&
|
||||
!document.getElementById("discord-screenaudio-gaintoggle")
|
||||
) {
|
||||
const toggle = createSwitch(
|
||||
"Disable automatic gain",
|
||||
await userscript.getPref("disableAutomaticGain", false),
|
||||
async (disabled) => {
|
||||
await userscript.setPref("disableAutomaticGain", disabled);
|
||||
autoGainControl = !disabled;
|
||||
setGetUserMedia();
|
||||
if (disabled)
|
||||
userscript.showInformation(
|
||||
"discord-screenaudio",
|
||||
"If you are currently in a call, this setting may only take effect after you rejoin the call or restart discord-screenaudio."
|
||||
);
|
||||
}
|
||||
);
|
||||
toggle.id = "discord-screenaudio-gaintoggle";
|
||||
el.getElementsByTagName("div")[0].appendChild(toggle);
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>assets/userscript.js</file>
|
||||
<file>assets/bridge_mod.js</file>
|
||||
<file>assets/arrpc_bridge_mod.js</file>
|
||||
<file>assets/arrpc.js</file>
|
||||
<file>assets/de.shorsh.discord-screenaudio.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
36
scripts/build_arrpc.sh
Executable file
36
scripts/build_arrpc.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/bash
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/../submodules"
|
||||
|
||||
echo_status() {
|
||||
echo
|
||||
echo
|
||||
echo "-> $1..."
|
||||
}
|
||||
|
||||
if [ ! -d "arrpc" ]; then
|
||||
echo_status "Cloning arRPC"
|
||||
git clone https://github.com/OpenAsar/arrpc.git
|
||||
cd arrpc
|
||||
else
|
||||
echo_status "Fetching arRPC changes"
|
||||
cd arrpc
|
||||
git fetch
|
||||
fi
|
||||
|
||||
echo_status "Checking out latest commit"
|
||||
git reset --hard HEAD
|
||||
git checkout main
|
||||
|
||||
echo_status "Installing dependencies"
|
||||
pnpm i -D @vercel/ncc
|
||||
|
||||
echo_status "Patching arRPC"
|
||||
sed -i 's/"type": "module",//' package.json
|
||||
|
||||
echo_status "Building arRPC"
|
||||
pnpm exec ncc build -m src/index.js
|
||||
|
||||
echo_status "Copying built file"
|
||||
cp -v ./dist/index.js ../../assets/arrpc.js
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkReply>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTimer>
|
||||
#include <QWebChannel>
|
||||
#include <QWebEngineScript>
|
||||
@@ -35,11 +36,9 @@ DiscordPage::DiscordPage(QWidget *parent) : QWebEnginePage(parent) {
|
||||
|
||||
injectFile(&DiscordPage::injectScript, "userscript.js",
|
||||
":/assets/userscript.js");
|
||||
|
||||
injectFile(&DiscordPage::injectScript, "bridge_mod.js",
|
||||
":/assets/bridge_mod.js");
|
||||
|
||||
setupUserStyles();
|
||||
setupArrpc();
|
||||
}
|
||||
|
||||
void DiscordPage::setupPermissions() {
|
||||
@@ -283,10 +282,11 @@ void DiscordPage::javaScriptConsoleMessage(
|
||||
ansi += "\033[" + cssAnsiColorMap[color] + "m";
|
||||
}
|
||||
}
|
||||
qDebug(discordLog) << (ansi + lines[0].trimmed() + "\033[0m " +
|
||||
lines[endOfStyles].trimmed())
|
||||
.toUtf8()
|
||||
.constData();
|
||||
if (endOfStyles < lines.length())
|
||||
qDebug(discordLog) << (ansi + lines[0].trimmed() + "\033[0m " +
|
||||
lines[endOfStyles].trimmed())
|
||||
.toUtf8()
|
||||
.constData();
|
||||
for (auto line : lines.mid(endOfStyles + 1)) {
|
||||
qDebug(discordLog) << line.toUtf8().constData();
|
||||
}
|
||||
@@ -294,3 +294,19 @@ void DiscordPage::javaScriptConsoleMessage(
|
||||
}
|
||||
|
||||
UserScript *DiscordPage::userScript() { return &m_userScript; }
|
||||
|
||||
void DiscordPage::setupArrpc() {
|
||||
QFile nodejs("/usr/bin/node");
|
||||
if (nodejs.exists()) {
|
||||
auto arrpcSource = QTemporaryFile::createNativeFile(":/assets/arrpc.js");
|
||||
qDebug(mainLog).noquote()
|
||||
<< "NodeJS found, starting arRPC located at" << arrpcSource->fileName();
|
||||
m_arrpcProcess.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
m_arrpcProcess.setProgram(nodejs.fileName());
|
||||
m_arrpcProcess.setArguments(QStringList{arrpcSource->fileName()});
|
||||
m_arrpcProcess.start();
|
||||
|
||||
injectFile(&DiscordPage::injectScript, "arrpc_bridge_mod.js",
|
||||
":/assets/arrpc_bridge_mod.js");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QProcess>
|
||||
#include <QStandardPaths>
|
||||
#include <QWebEngineFullScreenRequest>
|
||||
#include <QWebEnginePage>
|
||||
@@ -22,10 +23,12 @@ private:
|
||||
QFile *m_userStylesFile;
|
||||
QString m_userStylesContent;
|
||||
QNetworkAccessManager m_networkAccessManager;
|
||||
QProcess m_arrpcProcess;
|
||||
const QDir m_configLocation =
|
||||
QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
void setupPermissions();
|
||||
void setupUserStyles();
|
||||
void setupArrpc();
|
||||
void fetchUserStyles();
|
||||
bool acceptNavigationRequest(const QUrl &url,
|
||||
QWebEnginePage::NavigationType type,
|
||||
|
||||
22
src/localserver.cpp
Normal file
22
src/localserver.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "localserver.h"
|
||||
|
||||
bool isProgramRunning(const QString &program_name) {
|
||||
QLocalSocket socket;
|
||||
socket.connectToServer(program_name);
|
||||
if (socket.waitForConnected()) {
|
||||
return true; // program is already running
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void showErrorMessage(const char *text) {
|
||||
QMessageBox msgBox;
|
||||
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setText(text);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setWindowIcon(QIcon(":assets/de.shorsh.discord-screenaudio.png"));
|
||||
|
||||
msgBox.exec();
|
||||
}
|
||||
9
src/localserver.h
Normal file
9
src/localserver.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QMessageBox>
|
||||
|
||||
bool isProgramRunning(const QString &program_name);
|
||||
void showErrorMessage(const char *text);
|
||||
19
src/main.cpp
19
src/main.cpp
@@ -1,3 +1,4 @@
|
||||
#include "localserver.h"
|
||||
#include "mainwindow.h"
|
||||
#include "virtmic.h"
|
||||
|
||||
@@ -7,10 +8,14 @@
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QLoggingCategory>
|
||||
#include <QMessageBox>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
|
||||
QApplication::setApplicationName("discord-screenaudio");
|
||||
QApplication::setWindowIcon(
|
||||
QIcon(":assets/de.shorsh.discord-screenaudio.png"));
|
||||
@@ -50,6 +55,20 @@ int main(int argc, char *argv[]) {
|
||||
qgetenv("QTWEBENGINE_CHROMIUM_FLAGS"));
|
||||
|
||||
MainWindow w(parser.isSet(notifySendOption));
|
||||
|
||||
// Check if discord is already running
|
||||
QString program_name = "discord-screenaudio";
|
||||
if (isProgramRunning(program_name)) {
|
||||
// if running show error message
|
||||
showErrorMessage("discord-screenaudio is already running");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// open server so we can check if discord is running
|
||||
QLocalServer server;
|
||||
server.listen(program_name);
|
||||
QObject::connect(&server, &QLocalServer::newConnection, []() {});
|
||||
|
||||
w.show();
|
||||
|
||||
return app.exec();
|
||||
|
||||
@@ -30,6 +30,7 @@ MainWindow::MainWindow(bool useNotifySend, QWidget *parent)
|
||||
m_centralWidget = new CentralWidget(this);
|
||||
setCentralWidget(m_centralWidget);
|
||||
setupTrayIcon();
|
||||
setMinimumSize(800, 300);
|
||||
if (m_settings->contains("geometry")) {
|
||||
restoreGeometry(m_settings->value("geometry").toByteArray());
|
||||
} else {
|
||||
@@ -99,7 +100,8 @@ void MainWindow::cleanTrayIcon() {
|
||||
}
|
||||
|
||||
void MainWindow::setupSettings() {
|
||||
m_settings = new QSettings("maltejur", "discord-screenaudio", this);
|
||||
m_settings =
|
||||
new QSettings("discord-screenaudio", "discord-screenaudio", this);
|
||||
m_settings->beginGroup("settings");
|
||||
m_settings->endGroup();
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ void UserScript::setupHelpMenu() {
|
||||
QString(), "https://github.com/Curve");
|
||||
aboutData.addComponent("Rohrkabel", "A C++ RAII Pipewire-API Wrapper", "1.3",
|
||||
"https://github.com/Soundux/rohrkabel");
|
||||
aboutData.addComponent("arRPC",
|
||||
"An open implementation of Discord's local RPC "
|
||||
"servers<br>Copyright (c) 2022 OpenAsar",
|
||||
nullptr, "https://github.com/OpenAsar/arrpc");
|
||||
m_helpMenu = new KHelpMenu(MainWindow::instance(), aboutData);
|
||||
#endif
|
||||
}
|
||||
@@ -178,3 +182,7 @@ void UserScript::showThemeDialog() {
|
||||
void UserScript::installUserStyles(QString url) {
|
||||
emit shouldInstallUserStyles(url);
|
||||
}
|
||||
|
||||
void UserScript::showInformation(QString title, QString message) {
|
||||
QMessageBox::information(MainWindow::instance(), title, message);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ public Q_SLOTS:
|
||||
void showShortcutsDialog();
|
||||
void showHelpMenu();
|
||||
void showStreamDialog();
|
||||
void showInformation(QString title, QString message);
|
||||
void stopVirtmic();
|
||||
void startVirtmic(QString target);
|
||||
void showThemeDialog();
|
||||
|
||||
@@ -8,6 +8,25 @@ namespace Virtmic {
|
||||
|
||||
const QStringList EXCLUDE_TARGETS{"Chromium input", "discord-screenaudio"};
|
||||
|
||||
const std::string nullstr = "";
|
||||
const std::string &getTarget(const pipewire::spa::dict &props) {
|
||||
if (props.count("media.class") &&
|
||||
props.at("media.class") == "Stream/Output/Audio") {
|
||||
if (props.count("application.name") && props.at("application.name") != "")
|
||||
return props.at("application.name");
|
||||
else if (props.count("application.process.binary") &&
|
||||
props.at("application.process.binary") != "")
|
||||
return props.at("application.process.binary");
|
||||
else
|
||||
return props.at("node.name");
|
||||
} else
|
||||
return nullstr;
|
||||
}
|
||||
|
||||
QString qGetTarget(const pipewire::spa::dict &props) {
|
||||
return QString::fromStdString(getTarget(props));
|
||||
}
|
||||
|
||||
QVector<QString> getTargets() {
|
||||
auto main_loop = pipewire::main_loop();
|
||||
auto context = pipewire::context(main_loop);
|
||||
@@ -22,14 +41,7 @@ QVector<QString> getTargets() {
|
||||
if (global.type == pipewire::node::type) {
|
||||
auto node = reg.bind<pipewire::node>(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"]);
|
||||
|
||||
QString name = qGetTarget(info.props);
|
||||
if (name != "" && !EXCLUDE_TARGETS.contains(name) &&
|
||||
!targets.contains(name)) {
|
||||
targets.append(name);
|
||||
@@ -73,13 +85,7 @@ void start(QString _target) {
|
||||
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"];
|
||||
|
||||
std::string name = getTarget(parent.props);
|
||||
if (name == target ||
|
||||
(target == "[All Desktop Audio]" &&
|
||||
!EXCLUDE_TARGETS.contains(QString::fromStdString(name)))) {
|
||||
@@ -99,7 +105,7 @@ void start(QString _target) {
|
||||
}
|
||||
};
|
||||
|
||||
std::string target = _target.toLatin1().toStdString();
|
||||
std::string target = _target.toUtf8().toStdString();
|
||||
|
||||
auto virtual_mic = core.create("adapter",
|
||||
{{"node.name", "discord-screenaudio-virtmic"},
|
||||
@@ -123,13 +129,8 @@ void start(QString _target) {
|
||||
if (global.type == pipewire::node::type) {
|
||||
auto node = reg.bind<pipewire::node>(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
|
||||
std::string name = getTarget(info.props);
|
||||
if (name == nullstr)
|
||||
return;
|
||||
qDebug(virtmicLog) << QString("Added: %1")
|
||||
.arg(QString::fromStdString(name))
|
||||
@@ -168,12 +169,9 @@ void start(QString _target) {
|
||||
[&](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"];
|
||||
std::string name = getTarget(info.props);
|
||||
if (name == nullstr)
|
||||
return;
|
||||
qDebug(virtmicLog) << QString("Removed: %1")
|
||||
.arg(QString::fromStdString(name))
|
||||
.toUtf8()
|
||||
|
||||
Reference in New Issue
Block a user