Compare commits
35 Commits
Author | SHA1 | Date |
---|---|---|
Wizzard | b8d3bbd3e0 | |
Wizzard | a8d7965c43 | |
Wizzard | 1a60367c0a | |
Wizzard | 65b7556523 | |
Wizzard | 4ab61017db | |
Wizzard | f87096f627 | |
Wizzard | 74bbe65688 | |
Wizzard | 89c9a6651e | |
Wizzard | 73d49795ea | |
Wizzard | 33a0f68cf1 | |
Wizzard | 17517d1b46 | |
Wizzard | 12c8a7e49a | |
Wizzard | 1fc8436618 | |
Wizzard | 03f52e221f | |
Wizzard | 18e6598a95 | |
Wizzard | 829729aef2 | |
Wizzard | 58c3ac0b71 | |
Wizzard | 2858eb3854 | |
Malte Jürgens | 94b27f5b6a | |
Malte Jürgens | 8a6f49b949 | |
Malte Jürgens | 47fd620876 | |
Vitalya | c15250498b | |
Vitalya | 6f0303206e | |
Malte Jürgens | 6e86647c95 | |
Vitalya | 798fb3d5e4 | |
Malte Jürgens | 6c9b76ed90 | |
Vitalya | b582584c69 | |
Malte Jürgens | 7b6e8fc473 | |
Malte Jürgens | 8f0a810539 | |
Malte Jürgens | a6eb82948f | |
Malte Jürgens | 24727f398a | |
Daniel Mensinger | c43e9953a5 | |
Malte Jürgens | 08cb713e8c | |
Malte Jürgens | 27faed4a3a | |
Malte Jürgens | 10fff86ca4 |
|
@ -1,3 +1,20 @@
|
||||||
/build
|
# Ignore build and output directories
|
||||||
.vscode
|
/build/
|
||||||
/submodules/arrpc
|
/.flatpak-builder/
|
||||||
|
|
||||||
|
# Ignore flatpak-builder cache
|
||||||
|
/.flatpak-builder-cache/
|
||||||
|
|
||||||
|
# Ignore flatpak-builder log files
|
||||||
|
/*.log
|
||||||
|
|
||||||
|
# Ignore flatpak-builder generated files
|
||||||
|
/*.flatpak
|
||||||
|
/*.flatpak-builder
|
||||||
|
/*.flatpak-origin
|
||||||
|
|
||||||
|
# Ignore specific files or directories
|
||||||
|
/override.json
|
||||||
|
/metadata/
|
||||||
|
/manifest.json
|
||||||
|
/CMakeLists.txt.user
|
||||||
|
|
|
@ -14,13 +14,8 @@ string(TIMESTAMP TIMESTAMP %s)
|
||||||
# set(CMAKE_AUTOUIC ON)
|
# set(CMAKE_AUTOUIC ON)
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS Widgets)
|
find_package(Qt5 COMPONENTS Widgets)
|
||||||
if (Qt5_FOUND AND NOT DEFINED USE_QT6)
|
if (Qt5_FOUND)
|
||||||
message(STATUS "Using Qt 5")
|
|
||||||
find_package(Qt5 CONFIG REQUIRED COMPONENTS Widgets WebEngineWidgets)
|
find_package(Qt5 CONFIG REQUIRED COMPONENTS Widgets WebEngineWidgets)
|
||||||
else()
|
|
||||||
message(STATUS "Using Qt 6")
|
|
||||||
find_package(Qt6 CONFIG REQUIRED COMPONENTS Widgets WebEngineWidgets)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(KF5Notifications)
|
find_package(KF5Notifications)
|
||||||
if(KF5Notifications_FOUND)
|
if(KF5Notifications_FOUND)
|
||||||
|
@ -36,6 +31,10 @@ find_package(KF5GlobalAccel)
|
||||||
if(KF5GlobalAccel_FOUND)
|
if(KF5GlobalAccel_FOUND)
|
||||||
add_definitions( -DKGLOBALACCEL )
|
add_definitions( -DKGLOBALACCEL )
|
||||||
endif()
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "Qt 5 was not found on your system and Qt 6 will be used. You will not be able to use any features using KDE Frameworks.")
|
||||||
|
find_package(Qt6 CONFIG REQUIRED COMPONENTS Widgets WebEngineWidgets)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(discord-screenaudio_SRC
|
set(discord-screenaudio_SRC
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
@ -46,6 +45,15 @@ set(discord-screenaudio_SRC
|
||||||
src/log.cpp
|
src/log.cpp
|
||||||
src/userscript.cpp
|
src/userscript.cpp
|
||||||
src/centralwidget.cpp
|
src/centralwidget.cpp
|
||||||
|
src/localserver.cpp
|
||||||
|
src/centralwidget.h
|
||||||
|
src/discordpage.h
|
||||||
|
src/localserver.h
|
||||||
|
src/log.h
|
||||||
|
src/mainwindow.h
|
||||||
|
src/streamdialog.h
|
||||||
|
src/userscript.h
|
||||||
|
src/virtmic.h
|
||||||
resources.qrc
|
resources.qrc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,9 @@ You have multiple options:
|
||||||
With apt:
|
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`
|
`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
|
### Building
|
||||||
|
|
||||||
First, clone the repository:
|
First, clone the repository:
|
||||||
|
|
5636
assets/arrpc.js
5636
assets/arrpc.js
File diff suppressed because one or more lines are too long
|
@ -1,65 +1 @@
|
||||||
setTimeout(e => {
|
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);
|
||||||
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)
|
|
|
@ -28,7 +28,7 @@ function setGetDisplayMedia(video = true, overrideArgs = undefined) {
|
||||||
var id;
|
var id;
|
||||||
try {
|
try {
|
||||||
let myDiscordAudioSink = await getAudioDevice(
|
let myDiscordAudioSink = await getAudioDevice(
|
||||||
"discord-screenaudio-virtmic"
|
"discord-awesomeaudio-virtmic"
|
||||||
);
|
);
|
||||||
id = myDiscordAudioSink.deviceId;
|
id = myDiscordAudioSink.deviceId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -240,7 +240,7 @@ function main() {
|
||||||
} else {
|
} else {
|
||||||
aboutEl = document.createElement("div");
|
aboutEl = document.createElement("div");
|
||||||
}
|
}
|
||||||
aboutEl.innerText = `discord-screenaudio ${userscript.version}`;
|
aboutEl.innerText = `discord-awesomeaudio ${userscript.version}`;
|
||||||
aboutEl.style.fontSize = "12px";
|
aboutEl.style.fontSize = "12px";
|
||||||
aboutEl.style.color = "var(--text-muted)";
|
aboutEl.style.color = "var(--text-muted)";
|
||||||
aboutEl.style.textTransform = "none";
|
aboutEl.style.textTransform = "none";
|
||||||
|
@ -319,7 +319,7 @@ function main() {
|
||||||
const title = document.createElement("h2");
|
const title = document.createElement("h2");
|
||||||
title.className =
|
title.className =
|
||||||
"h1-3iMExa title-lXcL8p defaultColor-3Olr-9 defaultMarginh1-1UYutH";
|
"h1-3iMExa title-lXcL8p defaultColor-3Olr-9 defaultMarginh1-1UYutH";
|
||||||
title.innerText = "discord-screenaudio";
|
title.innerText = "discord-awesomeaudio";
|
||||||
section.appendChild(title);
|
section.appendChild(title);
|
||||||
|
|
||||||
section.appendChild(
|
section.appendChild(
|
||||||
|
@ -342,7 +342,17 @@ function main() {
|
||||||
|
|
||||||
section.appendChild(
|
section.appendChild(
|
||||||
createSwitch(
|
createSwitch(
|
||||||
"Move discord-screenaudio to the system tray instead of closing",
|
"Allow audio from your mic (and audio you pass through) to become stereo",
|
||||||
|
await userscript.getBoolPref("stereoMic", false),
|
||||||
|
(enabled) => {
|
||||||
|
userscript.setStereoMic(enabled);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
section.appendChild(
|
||||||
|
createSwitch(
|
||||||
|
"Move discord-awesomeaudio to the system tray instead of closing",
|
||||||
await userscript.getBoolPref("trayIcon", false),
|
await userscript.getBoolPref("trayIcon", false),
|
||||||
(enabled) => {
|
(enabled) => {
|
||||||
userscript.setTrayIcon(enabled);
|
userscript.setTrayIcon(enabled);
|
||||||
|
@ -352,7 +362,7 @@ function main() {
|
||||||
|
|
||||||
section.appendChild(
|
section.appendChild(
|
||||||
createSwitch(
|
createSwitch(
|
||||||
"Start discord-screenaudio hidden to tray",
|
"Start discord-awesomeaudio hidden to tray",
|
||||||
await userscript.getPref("startHidden", false),
|
await userscript.getPref("startHidden", false),
|
||||||
(hidden) => {
|
(hidden) => {
|
||||||
userscript.setPref("startHidden", hidden);
|
userscript.setPref("startHidden", hidden);
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Vencord, a modification for Discord's desktop app
|
||||||
|
* Copyright (c) 2022 Vendicated and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference path="../src/modules.d.ts" />
|
||||||
|
/// <reference path="../src/globals.d.ts" />
|
||||||
|
|
||||||
|
import monacoHtml from "~fileContent/../src/components/monacoWin.html";
|
||||||
|
import * as DataStore from "../src/api/DataStore";
|
||||||
|
import { debounce } from "../src/utils";
|
||||||
|
import { getTheme, Theme } from "../src/utils/discord";
|
||||||
|
|
||||||
|
// Discord deletes this so need to store in variable
|
||||||
|
const { localStorage } = window;
|
||||||
|
|
||||||
|
// listeners for ipc.on
|
||||||
|
const cssListeners = new Set<(css: string) => void>();
|
||||||
|
const NOOP = () => { };
|
||||||
|
const NOOP_ASYNC = async () => { };
|
||||||
|
|
||||||
|
const setCssDebounced = debounce((css: string) => VencordNative.quickCss.set(css));
|
||||||
|
|
||||||
|
// probably should make this less cursed at some point
|
||||||
|
window.VencordNative = {
|
||||||
|
native: {
|
||||||
|
getVersions: () => ({}),
|
||||||
|
openExternal: async (url) => void open(url, "_blank")
|
||||||
|
},
|
||||||
|
|
||||||
|
updater: {
|
||||||
|
getRepo: async () => ({ ok: true, value: "https://github.com/Vendicated/Vencord" }),
|
||||||
|
getUpdates: async () => ({ ok: true, value: [] }),
|
||||||
|
update: async () => ({ ok: true, value: false }),
|
||||||
|
rebuild: async () => ({ ok: true, value: true }),
|
||||||
|
},
|
||||||
|
|
||||||
|
quickCss: {
|
||||||
|
get: () => DataStore.get("VencordQuickCss").then(s => s ?? ""),
|
||||||
|
set: async (css: string) => {
|
||||||
|
await DataStore.set("VencordQuickCss", css);
|
||||||
|
cssListeners.forEach(l => l(css));
|
||||||
|
},
|
||||||
|
addChangeListener(cb) {
|
||||||
|
cssListeners.add(cb);
|
||||||
|
},
|
||||||
|
openFile: NOOP_ASYNC,
|
||||||
|
async openEditor() {
|
||||||
|
const features = `popup,width=${Math.min(window.innerWidth, 1000)},height=${Math.min(window.innerHeight, 1000)}`;
|
||||||
|
const win = open("about:blank", "VencordQuickCss", features);
|
||||||
|
if (!win) {
|
||||||
|
alert("Failed to open QuickCSS popup. Make sure to allow popups!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win.setCss = setCssDebounced;
|
||||||
|
win.getCurrentCss = () => VencordNative.quickCss.get();
|
||||||
|
win.getTheme = () =>
|
||||||
|
getTheme() === Theme.Light
|
||||||
|
? "vs-light"
|
||||||
|
: "vs-dark";
|
||||||
|
|
||||||
|
win.document.write(monacoHtml);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
get: () => localStorage.getItem("VencordSettings") || "{}",
|
||||||
|
set: async (s: string) => localStorage.setItem("VencordSettings", s),
|
||||||
|
getSettingsDir: async () => "LocalStorage"
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,14 @@
|
||||||
|
import definePlugin from "../utils/types";
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
name: "discord-awesomeaudio",
|
||||||
|
authors: [
|
||||||
|
{
|
||||||
|
name: "retard",
|
||||||
|
id: 205966226709676099n,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
required: true,
|
||||||
|
description: "UI patches for discord-screenaudio.",
|
||||||
|
patches: [],
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
--- a/src/components/VencordSettings/VencordTab.tsx
|
||||||
|
+++ b/src/components/VencordSettings/VencordTab.tsx
|
||||||
|
@@ -87,10 +87,10 @@ function VencordSettings() {
|
||||||
|
<Card className={cl("quick-actions-card")}>
|
||||||
|
{IS_WEB ? (
|
||||||
|
<Button
|
||||||
|
- onClick={() => require("../Monaco").launchMonacoEditor()}
|
||||||
|
+ onClick={() => VencordNative.ipc.send(IpcEvents.OPEN_EXTERNAL, settingsDir)}
|
||||||
|
size={Button.Sizes.SMALL}
|
||||||
|
disabled={settingsDir === "Loading..."}>
|
||||||
|
- Open QuickCSS File
|
||||||
|
+ Launch Directory
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<React.Fragment>
|
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
|
@ -0,0 +1,42 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
is_package_installed() {
|
||||||
|
if command -v "$1" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -f /etc/os-release ]]; then
|
||||||
|
. /etc/os-release
|
||||||
|
if [[ "$ID" == "ubuntu" || "$ID_LIKE" == "ubuntu" ]]; then
|
||||||
|
if ! is_package_installed flatpak-builder; then
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y flatpak-builder
|
||||||
|
fi
|
||||||
|
elif [[ "$ID" == "fedora" || "$ID_LIKE" == "fedora" ]]; then
|
||||||
|
if ! is_package_installed flatpak-builder; then
|
||||||
|
sudo dnf install -y flatpak-builder
|
||||||
|
fi
|
||||||
|
elif [[ "$ID" == "void" ]]; then
|
||||||
|
if ! is_package_installed flatpak-builder; then
|
||||||
|
sudo xbps-install -Sy flatpak-builder
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
flatpak install flathub org.kde.Sdk//5.15-22.08
|
||||||
|
|
||||||
|
flatpak install flathub io.qt.qtwebengine.BaseApp//5.15-22.08
|
||||||
|
|
||||||
|
flatpak-builder build-dir lol.deadzone.discord-awesomeaudio.json --install --user --force-clean
|
||||||
|
|
||||||
|
echo "[Desktop Entry]
|
||||||
|
Name=Discord Awesome Audio
|
||||||
|
Exec=flatpak run lol.deadzone.discord-awesomeaudio
|
||||||
|
Icon=/path/to/application/icon.png
|
||||||
|
Type=Application
|
||||||
|
Categories=AudioVideo;Network;" > ~/.local/share/applications/discord-awesomeaudio.desktop
|
||||||
|
|
||||||
|
chmod +x ~/.local/share/applications/discord-awesomeaudio.desktop
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"app-id": "lol.deadzone.discord-awesomeaudio",
|
||||||
|
"runtime": "org.kde.Platform",
|
||||||
|
"runtime-version": "5.15-22.08",
|
||||||
|
"sdk": "org.kde.Sdk",
|
||||||
|
"base": "io.qt.qtwebengine.BaseApp",
|
||||||
|
"base-version": "5.15-22.08",
|
||||||
|
"command": "discord-screenaudio",
|
||||||
|
"finish-args": [
|
||||||
|
"--share=ipc",
|
||||||
|
"--share=network",
|
||||||
|
"--socket=wayland",
|
||||||
|
"--socket=fallback-x11",
|
||||||
|
"--socket=pulseaudio",
|
||||||
|
"--filesystem=xdg-videos:ro",
|
||||||
|
"--filesystem=xdg-pictures:ro",
|
||||||
|
"--filesystem=xdg-download",
|
||||||
|
"--filesystem=xdg-run/pipewire-0",
|
||||||
|
"--device=all",
|
||||||
|
"--talk-name=org.kde.StatusNotifierWatcher",
|
||||||
|
"--env=QTWEBENGINEPROCESS_PATH=/app/bin/QtWebEngineProcess",
|
||||||
|
"--talk-name=org.freedesktop.Notifications",
|
||||||
|
"--talk-name=org.kde.kglobalaccel"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"name": "discord-screenaudio",
|
||||||
|
"buildsystem": "cmake-ninja",
|
||||||
|
"config-opts": [
|
||||||
|
"-DCMAKE_BUILD_TYPE=RelWithDebInfo",
|
||||||
|
"-DGIT_SUBMODULE=OFF"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"type": "dir",
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"finish-install": {
|
||||||
|
"desktop-file": "[Desktop Entry]\nName=Discord Awesome Audio\nExec=flatpak run lol.deadzone.discord-awesomeaudio\nIcon=/path/to/application/icon.png\nType=Application\nCategories=AudioVideo;Network;"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,12 @@
|
||||||
<!DOCTYPE RCC>
|
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource>
|
<qresource prefix="/">
|
||||||
<file>assets/userscript.js</file>
|
<file>assets/userscript.js</file>
|
||||||
<file>assets/arrpc_bridge_mod.js</file>
|
<file>assets/arrpc_bridge_mod.js</file>
|
||||||
<file>assets/arrpc.js</file>
|
<file>assets/arrpc.js</file>
|
||||||
<file>assets/de.shorsh.discord-screenaudio.png</file>
|
<file>assets/de.shorsh.discord-screenaudio.png</file>
|
||||||
|
<file>assets/vencord/vencord.js</file>
|
||||||
|
<file>assets/vencord/settings.patch</file>
|
||||||
|
<file>assets/vencord/plugin.js</file>
|
||||||
|
<file>assets/vencord/VencordNativeStub.ts</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
|
@ -30,7 +30,7 @@ echo_status "Patching arRPC"
|
||||||
sed -i 's/"type": "module",//' package.json
|
sed -i 's/"type": "module",//' package.json
|
||||||
|
|
||||||
echo_status "Building arRPC"
|
echo_status "Building arRPC"
|
||||||
pnpm exec ncc build src/index.js
|
pnpm exec ncc build -m src/index.js
|
||||||
|
|
||||||
echo_status "Copying built file"
|
echo_status "Copying built file"
|
||||||
cp -v ./dist/index.js ../../assets/arrpc.js
|
cp -v ./dist/index.js ../../assets/arrpc.js
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/../submodules"
|
||||||
|
|
||||||
|
echo_status() {
|
||||||
|
echo
|
||||||
|
echo
|
||||||
|
echo "-> $1..."
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ ! -d "Vencord" ]; then
|
||||||
|
echo_status "Cloning Vencord"
|
||||||
|
git clone https://github.com/Vendicated/Vencord.git
|
||||||
|
cd Vencord
|
||||||
|
else
|
||||||
|
echo_status "Fetching Vencord changes"
|
||||||
|
cd Vencord
|
||||||
|
git fetch
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo_status "Checking out latest commit"
|
||||||
|
git reset --hard HEAD
|
||||||
|
git checkout main
|
||||||
|
#git reset --hard devbuild
|
||||||
|
|
||||||
|
echo_status "Installing dependencies"
|
||||||
|
pnpm i
|
||||||
|
|
||||||
|
echo_status "Patching Vencord"
|
||||||
|
cp -v ../../assets/vencord/plugin.js ./src/plugins/discord-screenaudio.js
|
||||||
|
cp -v ../../assets/vencord/VencordNativeStub.ts ./browser/VencordNativeStub.ts
|
||||||
|
patch -p1 -i ../../assets/vencord/settings.patch
|
||||||
|
|
||||||
|
echo_status "Building Vencord"
|
||||||
|
pnpm run buildWeb
|
||||||
|
|
||||||
|
echo_status "Copying built file"
|
||||||
|
cp -v ./dist/browser.js ../../assets/vencord/vencord.js
|
|
@ -7,10 +7,12 @@
|
||||||
#include <QWebEngineScript>
|
#include <QWebEngineScript>
|
||||||
#include <QWebEngineScriptCollection>
|
#include <QWebEngineScriptCollection>
|
||||||
#include <QWebEngineSettings>
|
#include <QWebEngineSettings>
|
||||||
|
#include <QWebEngineView>
|
||||||
|
|
||||||
CentralWidget::CentralWidget(QWidget *parent) : QWidget(parent) {
|
CentralWidget::CentralWidget(QWidget *parent) : QWidget(parent) {
|
||||||
setStyleSheet("background-color:#313338;");
|
setStyleSheet("background-color:#313338;");
|
||||||
m_layout = new QVBoxLayout(this);
|
m_layout = new QVBoxLayout(this);
|
||||||
|
m_layout->setMargin(0);
|
||||||
m_layout->setSpacing(0);
|
m_layout->setSpacing(0);
|
||||||
setupWebView();
|
setupWebView();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#ifndef CENTRALWIDGET_H
|
||||||
|
#define CENTRALWIDGET_H
|
||||||
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
@ -7,23 +8,28 @@
|
||||||
#include <QWebEngineView>
|
#include <QWebEngineView>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#ifdef KNOTIFICATIONS
|
||||||
|
constexpr bool USE_KF5_NOTIFICATIONS = true;
|
||||||
|
#else
|
||||||
|
constexpr bool USE_KF5_NOTIFICATIONS = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
class CentralWidget : public QWidget {
|
class CentralWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CentralWidget(QWidget *parent = nullptr);
|
CentralWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setLoadingIndicator(QString text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupWebView();
|
void setupWebView();
|
||||||
|
|
||||||
QVBoxLayout *m_layout;
|
QVBoxLayout *m_layout;
|
||||||
QWebEngineView *m_webView;
|
QWebEngineView *m_webView;
|
||||||
#ifdef KNOTIFICATIONS
|
QLabel *m_loadingLabel;
|
||||||
bool m_useKF5Notifications = true;
|
bool m_useKF5Notifications;
|
||||||
#else
|
|
||||||
bool m_useKF5Notifications = false;
|
|
||||||
#endif
|
|
||||||
QLabel *m_loadingLabel = nullptr;
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
void setLoadingIndicator(QString text);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // CENTRALWIDGET_H
|
||||||
|
|
|
@ -36,7 +36,16 @@ DiscordPage::DiscordPage(QWidget *parent) : QWebEnginePage(parent) {
|
||||||
|
|
||||||
injectFile(&DiscordPage::injectScript, "userscript.js",
|
injectFile(&DiscordPage::injectScript, "userscript.js",
|
||||||
":/assets/userscript.js");
|
":/assets/userscript.js");
|
||||||
|
QFile vencord(":/assets/vencord/vencord.js");
|
||||||
|
if (!vencord.open(QIODevice::ReadOnly))
|
||||||
|
qFatal("Failed to load vencord source with error: %s",
|
||||||
|
vencord.errorString().toLatin1().constData());
|
||||||
|
injectScript(
|
||||||
|
"vencord.js",
|
||||||
|
QString("window.discordScreenaudioVencordSettings = `%1`; %2")
|
||||||
|
.arg(m_userScript.vencordSend("VencordGetSettings", {}).toString(),
|
||||||
|
vencord.readAll()));
|
||||||
|
vencord.close();
|
||||||
setupUserStyles();
|
setupUserStyles();
|
||||||
setupArrpc();
|
setupArrpc();
|
||||||
}
|
}
|
||||||
|
@ -282,6 +291,7 @@ void DiscordPage::javaScriptConsoleMessage(
|
||||||
ansi += "\033[" + cssAnsiColorMap[color] + "m";
|
ansi += "\033[" + cssAnsiColorMap[color] + "m";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (endOfStyles < lines.length())
|
||||||
qDebug(discordLog) << (ansi + lines[0].trimmed() + "\033[0m " +
|
qDebug(discordLog) << (ansi + lines[0].trimmed() + "\033[0m " +
|
||||||
lines[endOfStyles].trimmed())
|
lines[endOfStyles].trimmed())
|
||||||
.toUtf8()
|
.toUtf8()
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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);
|
23
src/main.cpp
23
src/main.cpp
|
@ -1,3 +1,4 @@
|
||||||
|
#include "localserver.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "virtmic.h"
|
#include "virtmic.h"
|
||||||
|
|
||||||
|
@ -7,15 +8,19 @@
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
QApplication::setApplicationName("discord-screenaudio");
|
|
||||||
|
QApplication::setApplicationName("discord-awesomeaudio");
|
||||||
QApplication::setWindowIcon(
|
QApplication::setWindowIcon(
|
||||||
QIcon(":assets/de.shorsh.discord-screenaudio.png"));
|
QIcon(":assets/de.shorsh.discord-screenaudio.png"));
|
||||||
QApplication::setApplicationVersion(DISCORD_SCEENAUDIO_VERSION_FULL);
|
QApplication::setApplicationVersion(DISCORD_SCEENAUDIO_VERSION_FULL);
|
||||||
QApplication::setDesktopFileName("de.shorsh.discord-screenaudio");
|
QApplication::setDesktopFileName("lol.deadzone.discord-awesomeaudio");
|
||||||
|
|
||||||
qSetMessagePattern("[%{category}] %{message}");
|
qSetMessagePattern("[%{category}] %{message}");
|
||||||
|
|
||||||
|
@ -50,6 +55,20 @@ int main(int argc, char *argv[]) {
|
||||||
qgetenv("QTWEBENGINE_CHROMIUM_FLAGS"));
|
qgetenv("QTWEBENGINE_CHROMIUM_FLAGS"));
|
||||||
|
|
||||||
MainWindow w(parser.isSet(notifySendOption));
|
MainWindow w(parser.isSet(notifySendOption));
|
||||||
|
|
||||||
|
// Check if discord is already running
|
||||||
|
QString program_name = "discord-awesomeaudio";
|
||||||
|
if (isProgramRunning(program_name)) {
|
||||||
|
// if running show error message
|
||||||
|
showErrorMessage("discord-awesomeaudio 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();
|
w.show();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
|
@ -12,13 +12,28 @@
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
#include <QShortcut>
|
||||||
#include <QSpacerItem>
|
#include <QSpacerItem>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QWebEngineFullScreenRequest>
|
#include <QWebEngineFullScreenRequest>
|
||||||
|
#include <QWebEngineProfile>
|
||||||
|
#include <QWebEngineUrlRequestInterceptor>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
// Custom network interceptor class
|
||||||
|
class NetworkInterceptor : public QWebEngineUrlRequestInterceptor {
|
||||||
|
public:
|
||||||
|
NetworkInterceptor(QObject* parent = nullptr) : QWebEngineUrlRequestInterceptor(parent) {}
|
||||||
|
|
||||||
|
void interceptRequest(QWebEngineUrlRequestInfo& info) override {
|
||||||
|
// Modify the request headers here as needed
|
||||||
|
info.setHttpHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
info.setHttpHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
MainWindow *MainWindow::m_instance = nullptr;
|
MainWindow *MainWindow::m_instance = nullptr;
|
||||||
|
|
||||||
MainWindow::MainWindow(bool useNotifySend, QWidget *parent)
|
MainWindow::MainWindow(bool useNotifySend, QWidget *parent)
|
||||||
|
@ -29,7 +44,15 @@ MainWindow::MainWindow(bool useNotifySend, QWidget *parent)
|
||||||
m_settings->setValue("useNotifySend", useNotifySend);
|
m_settings->setValue("useNotifySend", useNotifySend);
|
||||||
m_centralWidget = new CentralWidget(this);
|
m_centralWidget = new CentralWidget(this);
|
||||||
setCentralWidget(m_centralWidget);
|
setCentralWidget(m_centralWidget);
|
||||||
|
|
||||||
|
// Create and install the network interceptor
|
||||||
|
NetworkInterceptor* networkInterceptor = new NetworkInterceptor(this);
|
||||||
|
QWebEngineProfile::defaultProfile()->setRequestInterceptor(networkInterceptor);
|
||||||
|
|
||||||
setupTrayIcon();
|
setupTrayIcon();
|
||||||
|
setMinimumSize(800, 300);
|
||||||
|
connect(new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this),
|
||||||
|
&QShortcut::activated, this, &MainWindow::toggleOrCloseWindow);
|
||||||
if (m_settings->contains("geometry")) {
|
if (m_settings->contains("geometry")) {
|
||||||
restoreGeometry(m_settings->value("geometry").toByteArray());
|
restoreGeometry(m_settings->value("geometry").toByteArray());
|
||||||
} else {
|
} else {
|
||||||
|
@ -48,6 +71,9 @@ void MainWindow::fullScreenRequested(
|
||||||
fullScreenRequest.accept();
|
fullScreenRequest.accept();
|
||||||
if (fullScreenRequest.toggleOn()) {
|
if (fullScreenRequest.toggleOn()) {
|
||||||
m_wasMaximized = isMaximized();
|
m_wasMaximized = isMaximized();
|
||||||
|
if (!m_wasMaximized) {
|
||||||
|
showNormal();
|
||||||
|
}
|
||||||
showFullScreen();
|
showFullScreen();
|
||||||
} else {
|
} else {
|
||||||
m_wasMaximized ? showMaximized() : showNormal();
|
m_wasMaximized ? showMaximized() : showNormal();
|
||||||
|
@ -60,7 +86,7 @@ void MainWindow::setupTrayIcon() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto aboutAction = new QAction(
|
auto aboutAction = new QAction(
|
||||||
"discord-screenaudio v" + QString(DISCORD_SCEENAUDIO_VERSION_FULL), this);
|
"discord-awesomeaudio v" + QString(DISCORD_SCEENAUDIO_VERSION_FULL), this);
|
||||||
aboutAction->setIcon(QIcon(":assets/de.shorsh.discord-screenaudio.png"));
|
aboutAction->setIcon(QIcon(":assets/de.shorsh.discord-screenaudio.png"));
|
||||||
aboutAction->setEnabled(false);
|
aboutAction->setEnabled(false);
|
||||||
|
|
||||||
|
@ -78,12 +104,7 @@ void MainWindow::setupTrayIcon() {
|
||||||
|
|
||||||
connect(m_trayIcon, &QSystemTrayIcon::activated, [this](auto reason) {
|
connect(m_trayIcon, &QSystemTrayIcon::activated, [this](auto reason) {
|
||||||
if (reason == QSystemTrayIcon::Trigger) {
|
if (reason == QSystemTrayIcon::Trigger) {
|
||||||
if (isVisible()) {
|
toggleOrCloseWindow();
|
||||||
hide();
|
|
||||||
} else {
|
|
||||||
show();
|
|
||||||
activateWindow();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -100,7 +121,7 @@ void MainWindow::cleanTrayIcon() {
|
||||||
|
|
||||||
void MainWindow::setupSettings() {
|
void MainWindow::setupSettings() {
|
||||||
m_settings =
|
m_settings =
|
||||||
new QSettings("discord-screenaudio", "discord-screenaudio", this);
|
new QSettings("discord-awesomeaudio", "discord-awesomeaudio", this);
|
||||||
m_settings->beginGroup("settings");
|
m_settings->beginGroup("settings");
|
||||||
m_settings->endGroup();
|
m_settings->endGroup();
|
||||||
}
|
}
|
||||||
|
@ -130,3 +151,15 @@ MainWindow *MainWindow::instance() { return m_instance; }
|
||||||
CentralWidget *MainWindow::centralWidget() {
|
CentralWidget *MainWindow::centralWidget() {
|
||||||
return instance()->m_centralWidget;
|
return instance()->m_centralWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void MainWindow::toggleOrCloseWindow() {
|
||||||
|
if (isVisible()) {
|
||||||
|
if (m_trayIcon == nullptr)
|
||||||
|
QApplication::quit();
|
||||||
|
else
|
||||||
|
hide();
|
||||||
|
} else {
|
||||||
|
show();
|
||||||
|
activateWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <QSystemTrayIcon>
|
#include <QSystemTrayIcon>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QWebEngineUrlRequestInterceptor>
|
||||||
|
|
||||||
class MainWindow : public QMainWindow {
|
class MainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -24,7 +25,6 @@ private:
|
||||||
void setupTrayIcon();
|
void setupTrayIcon();
|
||||||
void cleanTrayIcon();
|
void cleanTrayIcon();
|
||||||
void setupSettings();
|
void setupSettings();
|
||||||
QWebEngineProfile *prepareProfile();
|
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
QSystemTrayIcon *m_trayIcon = nullptr;
|
QSystemTrayIcon *m_trayIcon = nullptr;
|
||||||
QMenu *m_trayIconMenu;
|
QMenu *m_trayIconMenu;
|
||||||
|
@ -36,4 +36,5 @@ private:
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void setTrayIcon(bool enabled);
|
void setTrayIcon(bool enabled);
|
||||||
void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest);
|
void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest);
|
||||||
|
void toggleOrCloseWindow();
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@ UserScript::UserScript() : QObject() {
|
||||||
setupVirtmic();
|
setupVirtmic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UserScript::setupHelpMenu() {
|
void UserScript::setupHelpMenu() {
|
||||||
#ifdef KXMLGUI
|
#ifdef KXMLGUI
|
||||||
m_kxmlgui = true;
|
m_kxmlgui = true;
|
||||||
|
@ -44,6 +45,10 @@ void UserScript::setupHelpMenu() {
|
||||||
QString(), "https://github.com/Curve");
|
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.3",
|
||||||
"https://github.com/Soundux/rohrkabel");
|
"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);
|
m_helpMenu = new KHelpMenu(MainWindow::instance(), aboutData);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -79,8 +84,7 @@ void UserScript::setupShortcutsDialog() {
|
||||||
|
|
||||||
void UserScript::setupStreamDialog() {
|
void UserScript::setupStreamDialog() {
|
||||||
m_streamDialog = new StreamDialog(MainWindow::instance());
|
m_streamDialog = new StreamDialog(MainWindow::instance());
|
||||||
connect(m_streamDialog, &StreamDialog::requestedStreamStart, this,
|
connect(m_streamDialog, &StreamDialog::requestedStreamStart, this, &UserScript::startStream);
|
||||||
&UserScript::startStream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserScript::setupVirtmic() {
|
void UserScript::setupVirtmic() {
|
||||||
|
@ -151,13 +155,13 @@ void UserScript::startVirtmic(QString target) {
|
||||||
m_virtmicProcess.start(QApplication::arguments()[0], {"--virtmic", target});
|
m_virtmicProcess.start(QApplication::arguments()[0], {"--virtmic", target});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserScript::startStream(bool video, bool audio, int width, int height,
|
void UserScript::startStream(bool video, bool audio, int width, int height, int frameRate, QString target) {
|
||||||
int frameRate, QString target) {
|
|
||||||
stopVirtmic();
|
stopVirtmic();
|
||||||
startVirtmic(audio ? target : "[None]");
|
startVirtmic(audio ? target : "[None]");
|
||||||
// Wait a bit for the virtmic to start
|
// Wait a bit for the virtmic to start
|
||||||
QTimer::singleShot(
|
QTimer::singleShot(200, [=]() {
|
||||||
200, [=]() { emit streamStarted(video, width, height, frameRate); });
|
emit streamStarted(video, width, height, frameRate);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserScript::showStreamDialog() {
|
void UserScript::showStreamDialog() {
|
||||||
|
@ -169,8 +173,7 @@ void UserScript::showStreamDialog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserScript::showThemeDialog() {
|
void UserScript::showThemeDialog() {
|
||||||
auto url = QInputDialog::getText(MainWindow::instance(), "Theme Installation",
|
auto url = QInputDialog::getText(MainWindow::instance(), "Theme Installation", "Please enter the URL of the Theme");
|
||||||
"Please enter the URL of the Theme");
|
|
||||||
if (url != "")
|
if (url != "")
|
||||||
emit shouldInstallUserStyles(url);
|
emit shouldInstallUserStyles(url);
|
||||||
}
|
}
|
||||||
|
@ -178,3 +181,68 @@ void UserScript::showThemeDialog() {
|
||||||
void UserScript::installUserStyles(QString url) {
|
void UserScript::installUserStyles(QString url) {
|
||||||
emit shouldInstallUserStyles(url);
|
emit shouldInstallUserStyles(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant UserScript::vencordSend(QString event, QVariantList args) {
|
||||||
|
QString configFolder =
|
||||||
|
QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) +
|
||||||
|
"/vencord";
|
||||||
|
QString quickCssFile = configFolder + "/quickCss.css";
|
||||||
|
QString settingsFile = configFolder + "/settings.json";
|
||||||
|
|
||||||
|
if (!QDir().exists(configFolder))
|
||||||
|
QDir().mkpath(configFolder);
|
||||||
|
|
||||||
|
if (event == "VencordGetRepo") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event == "VencordGetSettingsDir") {
|
||||||
|
return configFolder;
|
||||||
|
}
|
||||||
|
if (event == "VencordGetQuickCss") {
|
||||||
|
if (QFile::exists(quickCssFile)) {
|
||||||
|
QFile file(quickCssFile);
|
||||||
|
if (!file.open(QIODevice::ReadOnly))
|
||||||
|
qFatal("Failed to load %s with error: %s",
|
||||||
|
quickCssFile.toLatin1().constData(),
|
||||||
|
file.errorString().toLatin1().constData());
|
||||||
|
auto content = file.readAll();
|
||||||
|
file.close();
|
||||||
|
return QString(content);
|
||||||
|
} else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (event == "VencordGetSettings") {
|
||||||
|
if (QFile::exists(settingsFile)) {
|
||||||
|
QFile file(settingsFile);
|
||||||
|
if (!file.open(QIODevice::ReadOnly))
|
||||||
|
qFatal("Failed to load %s with error: %s",
|
||||||
|
settingsFile.toLatin1().constData(),
|
||||||
|
file.errorString().toLatin1().constData());
|
||||||
|
auto content = file.readAll();
|
||||||
|
file.close();
|
||||||
|
return QString(content);
|
||||||
|
} else
|
||||||
|
return "{}";
|
||||||
|
}
|
||||||
|
if (event == "VencordSetSettings") {
|
||||||
|
QFile file(settingsFile);
|
||||||
|
if (!file.open(QIODevice::WriteOnly))
|
||||||
|
qFatal("Failed to load %s with error: %s",
|
||||||
|
settingsFile.toLatin1().constData(),
|
||||||
|
file.errorString().toLatin1().constData());
|
||||||
|
file.write(args[0].toString().toUtf8());
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event == "VencordGetUpdates") {
|
||||||
|
return QVariantMap{{"ok", true}, {"value", QVariantList()}};
|
||||||
|
}
|
||||||
|
if (event == "VencordOpenExternal") {
|
||||||
|
QDesktopServices::openUrl(QUrl(args[0].toString()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event == "VencordOpenQuickCss") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "streamdialog.h"
|
#include "streamdialog.h"
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
#ifdef KXMLGUI
|
#ifdef KXMLGUI
|
||||||
#include <KAboutData>
|
#include <KAboutData>
|
||||||
|
@ -28,12 +29,11 @@ class UserScript : public QObject {
|
||||||
public:
|
public:
|
||||||
UserScript();
|
UserScript();
|
||||||
bool isVirtmicRunning();
|
bool isVirtmicRunning();
|
||||||
Q_PROPERTY(QString version READ version CONSTANT);
|
Q_PROPERTY(QString version READ version CONSTANT)
|
||||||
Q_PROPERTY(bool kxmlgui MEMBER m_kxmlgui CONSTANT);
|
Q_PROPERTY(bool kxmlgui MEMBER m_kxmlgui CONSTANT)
|
||||||
Q_PROPERTY(bool kglobalaccel MEMBER m_kglobalaccel CONSTANT);
|
Q_PROPERTY(bool kglobalaccel MEMBER m_kglobalaccel CONSTANT)
|
||||||
Q_PROPERTY(QString userstyles MEMBER m_userstyles NOTIFY userstylesChanged);
|
Q_PROPERTY(QString userstyles MEMBER m_userstyles NOTIFY userstylesChanged)
|
||||||
Q_PROPERTY(QString loadingMessage MEMBER m_loadingMessage NOTIFY
|
Q_PROPERTY(QString loadingMessage MEMBER m_loadingMessage NOTIFY loadingMessageChanged)
|
||||||
loadingMessageChanged);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QProcess m_virtmicProcess;
|
QProcess m_virtmicProcess;
|
||||||
|
@ -42,17 +42,22 @@ private:
|
||||||
bool m_kglobalaccel = false;
|
bool m_kglobalaccel = false;
|
||||||
QString m_userstyles;
|
QString m_userstyles;
|
||||||
QString m_loadingMessage;
|
QString m_loadingMessage;
|
||||||
|
|
||||||
|
QString m_vencordSettings;
|
||||||
|
|
||||||
|
void setupHelpMenu();
|
||||||
|
void setupShortcutsDialog();
|
||||||
|
void setupStreamDialog();
|
||||||
|
void setupVirtmic();
|
||||||
|
|
||||||
#ifdef KXMLGUI
|
#ifdef KXMLGUI
|
||||||
KHelpMenu *m_helpMenu;
|
KHelpMenu *m_helpMenu;
|
||||||
#ifdef KGLOBALACCEL
|
#ifdef KGLOBALACCEL
|
||||||
KActionCollection *m_actionCollection;
|
KActionCollection *m_actionCollection;
|
||||||
KShortcutsDialog *m_shortcutsDialog;
|
KShortcutsDialog *m_shortcutsDialog;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
void setupHelpMenu();
|
|
||||||
void setupShortcutsDialog();
|
|
||||||
void setupStreamDialog();
|
|
||||||
void setupVirtmic();
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void muteToggled();
|
void muteToggled();
|
||||||
|
@ -76,8 +81,9 @@ public Q_SLOTS:
|
||||||
void startVirtmic(QString target);
|
void startVirtmic(QString target);
|
||||||
void showThemeDialog();
|
void showThemeDialog();
|
||||||
void installUserStyles(QString url);
|
void installUserStyles(QString url);
|
||||||
|
QVariant vencordSend(QString event, QVariantList args);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void startStream(bool video, bool audio, int width, int height, int frameRate,
|
void startStream(bool video, bool audio, int width, int height, int frameRate, QString target);
|
||||||
QString target);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,26 @@
|
||||||
|
|
||||||
namespace Virtmic {
|
namespace Virtmic {
|
||||||
|
|
||||||
const QStringList EXCLUDE_TARGETS{"Chromium input", "discord-screenaudio"};
|
const QStringList EXCLUDE_TARGETS{"Chromium input", "discord-awesomeaudio", "pavucontrol", "PulseAudio Volume Control", "OBS", "OBS-Monitor", "OBS/OBS-MONITOR"};
|
||||||
|
|
||||||
|
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() {
|
QVector<QString> getTargets() {
|
||||||
auto main_loop = pipewire::main_loop();
|
auto main_loop = pipewire::main_loop();
|
||||||
|
@ -22,14 +41,7 @@ QVector<QString> getTargets() {
|
||||||
if (global.type == pipewire::node::type) {
|
if (global.type == pipewire::node::type) {
|
||||||
auto node = reg.bind<pipewire::node>(global.id);
|
auto node = reg.bind<pipewire::node>(global.id);
|
||||||
auto info = node.info();
|
auto info = node.info();
|
||||||
QString name;
|
QString name = qGetTarget(info.props);
|
||||||
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) &&
|
if (name != "" && !EXCLUDE_TARGETS.contains(name) &&
|
||||||
!targets.contains(name)) {
|
!targets.contains(name)) {
|
||||||
targets.append(name);
|
targets.append(name);
|
||||||
|
@ -73,12 +85,12 @@ void start(QString _target) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto &parent = nodes.at(parent_id);
|
auto &parent = nodes.at(parent_id);
|
||||||
std::string name;
|
std::string name = getTarget(parent.props);
|
||||||
if (parent.props.count("application.name") &&
|
if (EXCLUDE_TARGETS.contains(QString::fromStdString(name)))
|
||||||
parent.props["application.name"] != "")
|
continue;
|
||||||
name = parent.props["application.name"];
|
|
||||||
else
|
if (parent.props.count("media.class") && (parent.props.at("media.class") == "Audio/Source" || parent.props.at("media.class") == "Audio/Source/Virtual"))
|
||||||
name = parent.props["application.process.binary"];
|
continue;
|
||||||
|
|
||||||
if (name == target ||
|
if (name == target ||
|
||||||
(target == "[All Desktop Audio]" &&
|
(target == "[All Desktop Audio]" &&
|
||||||
|
@ -99,10 +111,10 @@ void start(QString _target) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string target = _target.toLatin1().toStdString();
|
std::string target = _target.toUtf8().toStdString();
|
||||||
|
|
||||||
auto virtual_mic = core.create("adapter",
|
auto virtual_mic = core.create("adapter",
|
||||||
{{"node.name", "discord-screenaudio-virtmic"},
|
{{"node.name", "discord-awesomeaudio-virtmic"},
|
||||||
{"media.class", "Audio/Source/Virtual"},
|
{"media.class", "Audio/Source/Virtual"},
|
||||||
{"factory.name", "support.null-audio-sink"},
|
{"factory.name", "support.null-audio-sink"},
|
||||||
{"audio.channels", "2"},
|
{"audio.channels", "2"},
|
||||||
|
@ -123,13 +135,8 @@ void start(QString _target) {
|
||||||
if (global.type == pipewire::node::type) {
|
if (global.type == pipewire::node::type) {
|
||||||
auto node = reg.bind<pipewire::node>(global.id);
|
auto node = reg.bind<pipewire::node>(global.id);
|
||||||
auto info = node.info();
|
auto info = node.info();
|
||||||
std::string name;
|
std::string name = getTarget(info.props);
|
||||||
if (info.props.count("application.name") &&
|
if (name == nullstr)
|
||||||
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;
|
return;
|
||||||
qDebug(virtmicLog) << QString("Added: %1")
|
qDebug(virtmicLog) << QString("Added: %1")
|
||||||
.arg(QString::fromStdString(name))
|
.arg(QString::fromStdString(name))
|
||||||
|
@ -168,12 +175,9 @@ void start(QString _target) {
|
||||||
[&](const std::uint32_t id) {
|
[&](const std::uint32_t id) {
|
||||||
if (nodes.count(id)) {
|
if (nodes.count(id)) {
|
||||||
auto info = nodes.at(id);
|
auto info = nodes.at(id);
|
||||||
std::string name;
|
std::string name = getTarget(info.props);
|
||||||
if (info.props.count("application.name") &&
|
if (name == nullstr)
|
||||||
info.props["application.name"] != "")
|
return;
|
||||||
name = info.props["application.name"];
|
|
||||||
else
|
|
||||||
name = info.props["application.process.binary"];
|
|
||||||
qDebug(virtmicLog) << QString("Removed: %1")
|
qDebug(virtmicLog) << QString("Removed: %1")
|
||||||
.arg(QString::fromStdString(name))
|
.arg(QString::fromStdString(name))
|
||||||
.toUtf8()
|
.toUtf8()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 62b2acebe6806c7b0e2ca6a43c6b2419a627b8dc
|
|
@ -0,0 +1,2 @@
|
||||||
|
flatpak remove lol.deadzone.discord-awesomeaudio
|
||||||
|
rm ~/.local/share/applications/discord-awesomeaudio.desktop
|
Loading…
Reference in New Issue