use qtwebchannel to communicate with userscript
This commit is contained in:
parent
0b12487dfd
commit
1477a9d4c0
|
@ -43,6 +43,7 @@ set(discord-screenaudio_SRC
|
||||||
src/discordpage.cpp
|
src/discordpage.cpp
|
||||||
src/streamdialog.cpp
|
src/streamdialog.cpp
|
||||||
src/log.cpp
|
src/log.cpp
|
||||||
|
src/userscript.cpp
|
||||||
resources.qrc
|
resources.qrc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// From v0.4
|
|
||||||
|
|
||||||
navigator.mediaDevices.chromiumGetDisplayMedia =
|
navigator.mediaDevices.chromiumGetDisplayMedia =
|
||||||
navigator.mediaDevices.getDisplayMedia;
|
navigator.mediaDevices.getDisplayMedia;
|
||||||
|
|
||||||
|
@ -16,12 +14,12 @@ const getAudioDevice = async (nameOfAudioDevice) => {
|
||||||
let devices = await navigator.mediaDevices.enumerateDevices();
|
let devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
audioDevice = devices.find(({ label }) => label === nameOfAudioDevice);
|
audioDevice = devices.find(({ label }) => label === nameOfAudioDevice);
|
||||||
if (!audioDevice)
|
if (!audioDevice)
|
||||||
console.log(
|
userscript.log(
|
||||||
`dsa: Did not find '${nameOfAudioDevice}', trying again in 100ms`
|
`Did not find '${nameOfAudioDevice}', trying again in 100ms`
|
||||||
);
|
);
|
||||||
await sleep(100);
|
await sleep(100);
|
||||||
}
|
}
|
||||||
console.log(`dsa: Found '${nameOfAudioDevice}'`);
|
userscript.log(`Found '${nameOfAudioDevice}'`);
|
||||||
return audioDevice;
|
return audioDevice;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -71,6 +69,13 @@ function setGetDisplayMedia(video = true, overrideArgs = undefined) {
|
||||||
|
|
||||||
setGetDisplayMedia();
|
setGetDisplayMedia();
|
||||||
|
|
||||||
|
let userscript;
|
||||||
|
let muteBtn;
|
||||||
|
let deafenBtn;
|
||||||
|
let streamStartBtn;
|
||||||
|
let streamStartBtnInitialDisplay;
|
||||||
|
let streamStartBtnClone;
|
||||||
|
let resolutionString;
|
||||||
const clonedElements = [];
|
const clonedElements = [];
|
||||||
const hiddenElements = [];
|
const hiddenElements = [];
|
||||||
let wasStreamActive = false;
|
let wasStreamActive = false;
|
||||||
|
@ -121,208 +126,216 @@ function createSwitch(text, enabled, onClick) {
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
const streamActive =
|
|
||||||
document.getElementsByClassName("panel-2ZFCRb activityPanel-9icbyU")
|
|
||||||
.length > 0;
|
|
||||||
|
|
||||||
if (!streamActive && wasStreamActive)
|
|
||||||
console.log("!discord-screenaudio-stream-stopped");
|
|
||||||
wasStreamActive = streamActive;
|
|
||||||
|
|
||||||
if (streamActive) {
|
|
||||||
clonedElements.forEach((el) => {
|
|
||||||
el.remove();
|
|
||||||
});
|
|
||||||
clonedElements.length = 0;
|
|
||||||
|
|
||||||
hiddenElements.forEach((el) => {
|
|
||||||
el.style.display = "block";
|
|
||||||
});
|
|
||||||
hiddenElements.length = 0;
|
|
||||||
} else {
|
|
||||||
for (const el of [
|
|
||||||
document.getElementsByClassName("actionButtons-2vEOUh")?.[0]?.children[1],
|
|
||||||
document.querySelector(
|
|
||||||
".wrapper-3t3Yqv > div > div > div > div > .controlButton-2PMNom"
|
|
||||||
),
|
|
||||||
]) {
|
|
||||||
if (!el) continue;
|
|
||||||
if (el.classList.contains("discord-screenaudio-cloned")) continue;
|
|
||||||
el.classList.add("discord-screenaudio-cloned");
|
|
||||||
elClone = el.cloneNode(true);
|
|
||||||
elClone.title = "Share Your Screen with Audio";
|
|
||||||
elClone.addEventListener("click", () => {
|
|
||||||
console.log("!discord-screenaudio-start-stream");
|
|
||||||
});
|
|
||||||
|
|
||||||
const initialDisplay = el.style.display;
|
|
||||||
|
|
||||||
window.discordScreenaudioStartStream = (
|
|
||||||
video,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
frameRate
|
|
||||||
) => {
|
|
||||||
window.discordScreenaudioResolutionString = video
|
|
||||||
? `${height}p ${frameRate}FPS`
|
|
||||||
: "Audio Only";
|
|
||||||
setGetDisplayMedia(video, {
|
|
||||||
audio: true,
|
|
||||||
video: { width, height, frameRate },
|
|
||||||
});
|
|
||||||
el.click();
|
|
||||||
el.style.display = initialDisplay;
|
|
||||||
elClone.remove();
|
|
||||||
};
|
|
||||||
|
|
||||||
el.style.display = "none";
|
|
||||||
el.parentNode.insertBefore(elClone, el);
|
|
||||||
|
|
||||||
clonedElements.push(elClone);
|
|
||||||
hiddenElements.push(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add about text in settings
|
|
||||||
if (
|
|
||||||
document.getElementsByClassName("dirscordScreenaudioAboutText").length == 0
|
|
||||||
) {
|
|
||||||
for (const el of document.getElementsByClassName("info-3pQQBb")) {
|
|
||||||
let aboutEl;
|
|
||||||
if (window.discordScreenaudioKXMLGUI) {
|
|
||||||
aboutEl = document.createElement("a");
|
|
||||||
aboutEl.addEventListener("click", () => {
|
|
||||||
console.log("!discord-screenaudio-about");
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
aboutEl = document.createElement("div");
|
|
||||||
}
|
|
||||||
aboutEl.innerText = `discord-screenaudio ${window.discordScreenaudioVersion}`;
|
|
||||||
aboutEl.style.fontSize = "12px";
|
|
||||||
aboutEl.style.color = "var(--text-muted)";
|
|
||||||
aboutEl.style.textTransform = "none";
|
|
||||||
aboutEl.classList.add("dirscordScreenaudioAboutText");
|
|
||||||
aboutEl.style.cursor = "pointer";
|
|
||||||
el.appendChild(aboutEl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove stream settings if stream is active
|
|
||||||
document.getElementById("manage-streams-change-windows")?.remove();
|
|
||||||
document.querySelector(`[aria-label="Stream Settings"]`)?.remove();
|
|
||||||
|
|
||||||
// Add event listener for keybind tab
|
|
||||||
if (
|
|
||||||
document
|
|
||||||
.getElementById("keybinds-tab")
|
|
||||||
?.getElementsByClassName(
|
|
||||||
"container-3jbRo5 info-1hMolH browserNotice-1u-Y5o"
|
|
||||||
).length
|
|
||||||
) {
|
|
||||||
const el = document
|
|
||||||
.getElementById("keybinds-tab")
|
|
||||||
.getElementsByClassName("children-1xdcWE")[0];
|
|
||||||
const div = document.createElement("div");
|
|
||||||
div.style.marginBottom = "50px";
|
|
||||||
div.appendChild(
|
|
||||||
createButton("Edit Global Keybinds", () => {
|
|
||||||
console.log("!discord-screenaudio-keybinds");
|
|
||||||
})
|
|
||||||
);
|
|
||||||
el.innerHTML = "";
|
|
||||||
el.appendChild(div);
|
|
||||||
}
|
|
||||||
|
|
||||||
const buttonContainer =
|
|
||||||
document.getElementsByClassName("container-YkUktl")[0];
|
|
||||||
if (!buttonContainer) {
|
|
||||||
console.log(
|
|
||||||
"dsa: Cannot locate Mute/Deafen/Settings button container, please report this on GitHub"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const muteBtn = buttonContainer
|
|
||||||
? buttonContainer.getElementsByClassName(
|
|
||||||
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F"
|
|
||||||
)[0]
|
|
||||||
: null;
|
|
||||||
window.discordScreenaudioToggleMute = () => muteBtn && muteBtn.click();
|
|
||||||
|
|
||||||
const deafenBtn = buttonContainer
|
|
||||||
? buttonContainer.getElementsByClassName(
|
|
||||||
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F"
|
|
||||||
)[1]
|
|
||||||
: null;
|
|
||||||
|
|
||||||
window.discordScreenaudioToggleDeafen = () => deafenBtn && deafenBtn.click();
|
|
||||||
|
|
||||||
if (window.discordScreenaudioResolutionString) {
|
|
||||||
for (const el of document.getElementsByClassName(
|
|
||||||
"qualityIndicator-39wQDy"
|
|
||||||
)) {
|
|
||||||
el.innerHTML = window.discordScreenaudioResolutionString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const accountTab = document.getElementById("my-account-tab");
|
|
||||||
if (accountTab) {
|
|
||||||
const discordScreenaudioSettings = document.getElementById(
|
|
||||||
"discord-screenaudio-settings"
|
|
||||||
);
|
|
||||||
if (!discordScreenaudioSettings) {
|
|
||||||
const firstDivider = accountTab.getElementsByClassName(
|
|
||||||
"divider-3nqZNm marginTop40-Q4o1tS"
|
|
||||||
)[0];
|
|
||||||
if (firstDivider) {
|
|
||||||
const section = document.createElement("div");
|
|
||||||
section.className = "marginTop40-Q4o1tS";
|
|
||||||
section.id = "discord-screenaudio-settings";
|
|
||||||
|
|
||||||
const title = document.createElement("h2");
|
|
||||||
title.className =
|
|
||||||
"h1-3iMExa title-lXcL8p defaultColor-3Olr-9 defaultMarginh1-1UYutH";
|
|
||||||
title.innerText = "discord-screenaudio";
|
|
||||||
section.appendChild(title);
|
|
||||||
|
|
||||||
section.appendChild(
|
|
||||||
createButton("Edit Global Keybinds", () => {
|
|
||||||
console.log("!discord-screenaudio-keybinds");
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
section.appendChild(
|
|
||||||
createSwitch(
|
|
||||||
"Move discord-screenaudio to the system tray instead of closing",
|
|
||||||
window.discordScreenaudioTrayEnabled,
|
|
||||||
(enabled) => {
|
|
||||||
window.discordScreenaudioTrayEnabled = enabled;
|
|
||||||
console.log(`!discord-screenaudio-tray-${enabled}`);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
section.appendChild(
|
|
||||||
createSwitch(
|
|
||||||
"Start discord-screenaudio hidden to tray",
|
|
||||||
window.discordScreenaudioStartHidden,
|
|
||||||
(hidden) => {
|
|
||||||
window.discordScreenaudioStartHidden = hidden;
|
|
||||||
console.log(`!discord-screenaudio-starthidden-${hidden}`);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const divider = document.createElement("div");
|
|
||||||
divider.className = "divider-3nqZNm marginTop40-Q4o1tS";
|
|
||||||
|
|
||||||
firstDivider.after(section);
|
|
||||||
section.after(divider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
// Fix for broken discord notifications after restart
|
// Fix for broken discord notifications after restart
|
||||||
// (https://github.com/maltejur/discord-screenaudio/issues/17)
|
// (https://github.com/maltejur/discord-screenaudio/issues/17)
|
||||||
Notification.requestPermission();
|
Notification.requestPermission();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
new QWebChannel(qt.webChannelTransport, (channel) => {
|
||||||
|
userscript = channel.objects.userscript;
|
||||||
|
main();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
userscript.muteToggled.connect(() => {
|
||||||
|
muteBtn && muteBtn.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
userscript.deafenToggled.connect(() => {
|
||||||
|
deafenBtn && deafenBtn.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
userscript.streamStarted.connect((video, width, height, frameRate) => {
|
||||||
|
resolutionString = video ? `${height}p ${frameRate}FPS` : "Audio Only";
|
||||||
|
setGetDisplayMedia(video, {
|
||||||
|
audio: true,
|
||||||
|
video: { width, height, frameRate },
|
||||||
|
});
|
||||||
|
streamStartBtn.click();
|
||||||
|
streamStartBtn.style.display = streamStartBtnInitialDisplay;
|
||||||
|
streamStartBtnClone.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
setInterval(async () => {
|
||||||
|
const streamActive =
|
||||||
|
document.getElementsByClassName("panel-2ZFCRb activityPanel-9icbyU")
|
||||||
|
.length > 0;
|
||||||
|
|
||||||
|
if (!streamActive && wasStreamActive) userscript.stopVirtmic();
|
||||||
|
wasStreamActive = streamActive;
|
||||||
|
|
||||||
|
if (streamActive) {
|
||||||
|
clonedElements.forEach((el) => {
|
||||||
|
el.remove();
|
||||||
|
});
|
||||||
|
clonedElements.length = 0;
|
||||||
|
|
||||||
|
hiddenElements.forEach((el) => {
|
||||||
|
el.style.display = "block";
|
||||||
|
});
|
||||||
|
hiddenElements.length = 0;
|
||||||
|
} else {
|
||||||
|
for (const el of [
|
||||||
|
document.getElementsByClassName("actionButtons-2vEOUh")?.[0]
|
||||||
|
?.children[1],
|
||||||
|
document.querySelector(
|
||||||
|
".wrapper-3t3Yqv > div > div > div > div > .controlButton-2PMNom"
|
||||||
|
),
|
||||||
|
]) {
|
||||||
|
if (!el) continue;
|
||||||
|
if (el.classList.contains("discord-screenaudio-cloned")) continue;
|
||||||
|
streamStartBtn = el;
|
||||||
|
streamStartBtn.classList.add("discord-screenaudio-cloned");
|
||||||
|
|
||||||
|
streamStartBtnClone = streamStartBtn.cloneNode(true);
|
||||||
|
streamStartBtnClone.title = "Share Your Screen with Audio";
|
||||||
|
streamStartBtnClone.addEventListener("click", () => {
|
||||||
|
userscript.showStreamDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
streamStartBtnInitialDisplay = streamStartBtn.style.display;
|
||||||
|
|
||||||
|
streamStartBtn.style.display = "none";
|
||||||
|
streamStartBtn.parentNode.insertBefore(streamStartBtnClone, el);
|
||||||
|
|
||||||
|
clonedElements.push(streamStartBtnClone);
|
||||||
|
hiddenElements.push(streamStartBtn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add about text in settings
|
||||||
|
if (
|
||||||
|
document.getElementsByClassName("dirscordScreenaudioAboutText").length ==
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
for (const el of document.getElementsByClassName("info-3pQQBb")) {
|
||||||
|
let aboutEl;
|
||||||
|
if (userscript.kxmlgui) {
|
||||||
|
aboutEl = document.createElement("a");
|
||||||
|
aboutEl.addEventListener("click", () => {
|
||||||
|
userscript.showHelpMenu();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
aboutEl = document.createElement("div");
|
||||||
|
}
|
||||||
|
aboutEl.innerText = `discord-screenaudio ${userscript.version}`;
|
||||||
|
aboutEl.style.fontSize = "12px";
|
||||||
|
aboutEl.style.color = "var(--text-muted)";
|
||||||
|
aboutEl.style.textTransform = "none";
|
||||||
|
aboutEl.classList.add("dirscordScreenaudioAboutText");
|
||||||
|
aboutEl.style.cursor = "pointer";
|
||||||
|
el.appendChild(aboutEl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove stream settings if stream is active
|
||||||
|
document.getElementById("manage-streams-change-windows")?.remove();
|
||||||
|
document.querySelector(`[aria-label="Stream Settings"]`)?.remove();
|
||||||
|
|
||||||
|
// Add event listener for keybind tab
|
||||||
|
if (
|
||||||
|
document
|
||||||
|
.getElementById("keybinds-tab")
|
||||||
|
?.getElementsByClassName(
|
||||||
|
"container-3jbRo5 info-1hMolH browserNotice-1u-Y5o"
|
||||||
|
).length
|
||||||
|
) {
|
||||||
|
const el = document
|
||||||
|
.getElementById("keybinds-tab")
|
||||||
|
.getElementsByClassName("children-1xdcWE")[0];
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.style.marginBottom = "50px";
|
||||||
|
div.appendChild(
|
||||||
|
createButton("Edit Global Keybinds", () => {
|
||||||
|
userscript.log("!discord-screenaudio-keybinds");
|
||||||
|
})
|
||||||
|
);
|
||||||
|
el.innerHTML = "";
|
||||||
|
el.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonContainer =
|
||||||
|
document.getElementsByClassName("container-YkUktl")[0];
|
||||||
|
if (!buttonContainer) {
|
||||||
|
userscript.log(
|
||||||
|
"Cannot locate Mute/Deafen/Settings button container, please report this on GitHub"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
muteBtn = buttonContainer
|
||||||
|
? buttonContainer.getElementsByClassName(
|
||||||
|
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F"
|
||||||
|
)[0]
|
||||||
|
: null;
|
||||||
|
|
||||||
|
deafenBtn = buttonContainer
|
||||||
|
? buttonContainer.getElementsByClassName(
|
||||||
|
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F"
|
||||||
|
)[1]
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (resolutionString) {
|
||||||
|
for (const el of document.getElementsByClassName(
|
||||||
|
"qualityIndicator-39wQDy"
|
||||||
|
)) {
|
||||||
|
el.innerHTML = resolutionString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const accountTab = document.getElementById("my-account-tab");
|
||||||
|
if (accountTab) {
|
||||||
|
const discordScreenaudioSettings = document.getElementById(
|
||||||
|
"discord-screenaudio-settings"
|
||||||
|
);
|
||||||
|
if (!discordScreenaudioSettings) {
|
||||||
|
const firstDivider = accountTab.getElementsByClassName(
|
||||||
|
"divider-3nqZNm marginTop40-Q4o1tS"
|
||||||
|
)[0];
|
||||||
|
if (firstDivider) {
|
||||||
|
const section = document.createElement("div");
|
||||||
|
section.className = "marginTop40-Q4o1tS";
|
||||||
|
section.id = "discord-screenaudio-settings";
|
||||||
|
|
||||||
|
const title = document.createElement("h2");
|
||||||
|
title.className =
|
||||||
|
"h1-3iMExa title-lXcL8p defaultColor-3Olr-9 defaultMarginh1-1UYutH";
|
||||||
|
title.innerText = "discord-screenaudio";
|
||||||
|
section.appendChild(title);
|
||||||
|
|
||||||
|
section.appendChild(
|
||||||
|
createButton("Edit Global Keybinds", () => {
|
||||||
|
userscript.log("!discord-screenaudio-keybinds");
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
section.appendChild(
|
||||||
|
createSwitch(
|
||||||
|
"Move discord-screenaudio to the system tray instead of closing",
|
||||||
|
await userscript.getBoolPref("trayIcon", false),
|
||||||
|
(enabled) => {
|
||||||
|
userscript.setTrayIcon(enabled);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
section.appendChild(
|
||||||
|
createSwitch(
|
||||||
|
"Start discord-screenaudio hidden to tray",
|
||||||
|
await userscript.getPref("startHidden", false),
|
||||||
|
(hidden) => {
|
||||||
|
userscript.setPref("startHidden", hidden);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const divider = document.createElement("div");
|
||||||
|
divider.className = "divider-3nqZNm marginTop40-Q4o1tS";
|
||||||
|
|
||||||
|
firstDivider.after(section);
|
||||||
|
section.after(divider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
|
@ -3,19 +3,6 @@
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "virtmic.h"
|
#include "virtmic.h"
|
||||||
|
|
||||||
#ifdef KXMLGUI
|
|
||||||
#include <KAboutData>
|
|
||||||
#include <KHelpMenu>
|
|
||||||
#include <KShortcutsDialog>
|
|
||||||
#include <KXmlGuiWindow>
|
|
||||||
#include <QAction>
|
|
||||||
|
|
||||||
#ifdef KGLOBALACCEL
|
|
||||||
#include <KGlobalAccel>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
@ -29,7 +16,6 @@
|
||||||
|
|
||||||
DiscordPage::DiscordPage(QWidget *parent) : QWebEnginePage(parent) {
|
DiscordPage::DiscordPage(QWidget *parent) : QWebEnginePage(parent) {
|
||||||
setBackgroundColor(QColor("#202225"));
|
setBackgroundColor(QColor("#202225"));
|
||||||
m_virtmicProcess.setProcessChannelMode(QProcess::ForwardedChannels);
|
|
||||||
|
|
||||||
connect(this, &QWebEnginePage::featurePermissionRequested, this,
|
connect(this, &QWebEnginePage::featurePermissionRequested, this,
|
||||||
&DiscordPage::featurePermissionRequested);
|
&DiscordPage::featurePermissionRequested);
|
||||||
|
@ -51,77 +37,14 @@ DiscordPage::DiscordPage(QWidget *parent) : QWebEnginePage(parent) {
|
||||||
settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
|
settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, false);
|
||||||
settings()->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, true);
|
settings()->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, true);
|
||||||
|
|
||||||
|
injectScriptFile("qwebchannel.js", ":/qtwebchannel/qwebchannel.js");
|
||||||
|
|
||||||
setUrl(QUrl("https://discord.com/app"));
|
setUrl(QUrl("https://discord.com/app"));
|
||||||
|
|
||||||
|
setWebChannel(new QWebChannel(this));
|
||||||
|
webChannel()->registerObject("userscript", &m_userScript);
|
||||||
|
|
||||||
injectScriptFile("userscript.js", ":/assets/userscript.js");
|
injectScriptFile("userscript.js", ":/assets/userscript.js");
|
||||||
|
|
||||||
injectScriptText("vars.js",
|
|
||||||
QString("window.discordScreenaudioVersion = '%1'; "
|
|
||||||
"window.discordScreenaudioTrayEnabled = %2; "
|
|
||||||
"window.discordScreenaudioStartHidden = %3;")
|
|
||||||
.arg(QApplication::applicationVersion())
|
|
||||||
.arg(MainWindow::instance()
|
|
||||||
->settings()
|
|
||||||
->value("trayIcon", false)
|
|
||||||
.toBool())
|
|
||||||
.arg(MainWindow::instance()
|
|
||||||
->settings()
|
|
||||||
->value("startHidden", false)
|
|
||||||
.toBool()));
|
|
||||||
|
|
||||||
#ifdef KXMLGUI
|
|
||||||
injectScriptText("xmlgui.js", "window.discordScreenaudioKXMLGUI = true;");
|
|
||||||
|
|
||||||
KAboutData aboutData(
|
|
||||||
"discord-screenaudio", "discord-screenaudio",
|
|
||||||
QApplication::applicationVersion(),
|
|
||||||
"Custom Discord client with the ability to stream audio on Linux",
|
|
||||||
KAboutLicense::GPL_V3, "Copyright 2022 (C) Malte Jürgens");
|
|
||||||
aboutData.setBugAddress("https://github.com/maltejur/discord-screenaudio");
|
|
||||||
aboutData.addAuthor("Malte Jürgens", "Author", "maltejur@dismail.de",
|
|
||||||
"https://github.com/maltejur");
|
|
||||||
aboutData.addCredit("edisionnano",
|
|
||||||
"For creating and documenting the approach for streaming "
|
|
||||||
"audio in Discord used in this project.",
|
|
||||||
QString(),
|
|
||||||
"https://github.com/edisionnano/"
|
|
||||||
"Screenshare-with-audio-on-Discord-with-Linux");
|
|
||||||
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",
|
|
||||||
"https://github.com/Soundux/rohrkabel");
|
|
||||||
m_helpMenu = new KHelpMenu(parent, aboutData);
|
|
||||||
|
|
||||||
#ifdef KGLOBALACCEL
|
|
||||||
injectScriptText("kglobalaccel.js",
|
|
||||||
"window.discordScreenaudioKGLOBALACCEL = true;");
|
|
||||||
|
|
||||||
auto toggleMuteAction = new QAction(this);
|
|
||||||
toggleMuteAction->setText("Toggle Mute");
|
|
||||||
toggleMuteAction->setIcon(QIcon::fromTheme("microphone-sensitivity-muted"));
|
|
||||||
connect(toggleMuteAction, &QAction::triggered, this,
|
|
||||||
&DiscordPage::toggleMute);
|
|
||||||
|
|
||||||
auto toggleDeafenAction = new QAction(this);
|
|
||||||
toggleDeafenAction->setText("Toggle Deafen");
|
|
||||||
toggleDeafenAction->setIcon(QIcon::fromTheme("audio-volume-muted"));
|
|
||||||
connect(toggleDeafenAction, &QAction::triggered, this,
|
|
||||||
&DiscordPage::toggleDeafen);
|
|
||||||
|
|
||||||
m_actionCollection = new KActionCollection(this);
|
|
||||||
m_actionCollection->addAction("toggleMute", toggleMuteAction);
|
|
||||||
KGlobalAccel::setGlobalShortcut(toggleMuteAction, QList<QKeySequence>{});
|
|
||||||
m_actionCollection->addAction("toggleDeafen", toggleDeafenAction);
|
|
||||||
KGlobalAccel::setGlobalShortcut(toggleDeafenAction, QList<QKeySequence>{});
|
|
||||||
|
|
||||||
m_shortcutsDialog = new KShortcutsDialog(KShortcutsEditor::GlobalAction);
|
|
||||||
m_shortcutsDialog->addCollection(m_actionCollection);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
connect(&m_streamDialog, &StreamDialog::requestedStreamStart, this,
|
|
||||||
&DiscordPage::startStream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiscordPage::injectScriptText(QString name, QString content) {
|
void DiscordPage::injectScriptText(QString name, QString content) {
|
||||||
|
@ -156,11 +79,10 @@ void DiscordPage::featurePermissionRequested(const QUrl &securityOrigin,
|
||||||
QWebEnginePage::PermissionGrantedByUser);
|
QWebEnginePage::PermissionGrantedByUser);
|
||||||
|
|
||||||
if (feature == QWebEnginePage::Feature::MediaAudioCapture) {
|
if (feature == QWebEnginePage::Feature::MediaAudioCapture) {
|
||||||
if (m_virtmicProcess.state() == QProcess::NotRunning) {
|
if (!m_userScript.isVirtmicRunning()) {
|
||||||
qDebug(virtmicLog) << "Starting Virtmic with no target to make sure "
|
qDebug(virtmicLog) << "Starting Virtmic with no target to make sure "
|
||||||
"Discord can find all the audio devices";
|
"Discord can find all the audio devices";
|
||||||
m_virtmicProcess.start(QApplication::arguments()[0],
|
m_userScript.startVirtmic("None");
|
||||||
{"--virtmic", "None"});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,86 +109,8 @@ QWebEnginePage *DiscordPage::createWindow(QWebEnginePage::WebWindowType type) {
|
||||||
return new ExternalPage;
|
return new ExternalPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiscordPage::stopVirtmic() {
|
|
||||||
if (m_virtmicProcess.state() == QProcess::Running) {
|
|
||||||
qDebug(virtmicLog) << "Stopping Virtmic";
|
|
||||||
m_virtmicProcess.kill();
|
|
||||||
m_virtmicProcess.waitForFinished();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DiscordPage::startVirtmic(QString target) {
|
|
||||||
qDebug(virtmicLog) << "Starting Virtmic with target" << target;
|
|
||||||
m_virtmicProcess.start(QApplication::arguments()[0], {"--virtmic", target});
|
|
||||||
}
|
|
||||||
|
|
||||||
void DiscordPage::javaScriptConsoleMessage(
|
void DiscordPage::javaScriptConsoleMessage(
|
||||||
QWebEnginePage::JavaScriptConsoleMessageLevel level, const QString &message,
|
QWebEnginePage::JavaScriptConsoleMessageLevel level, const QString &message,
|
||||||
int lineNumber, const QString &sourceID) {
|
int lineNumber, const QString &sourceID) {
|
||||||
if (message == "!discord-screenaudio-start-stream") {
|
qDebug(discordLog) << message;
|
||||||
if (m_streamDialog.isHidden())
|
|
||||||
m_streamDialog.setHidden(false);
|
|
||||||
else
|
|
||||||
m_streamDialog.activateWindow();
|
|
||||||
m_streamDialog.updateTargets();
|
|
||||||
} else if (message == "!discord-screenaudio-stream-stopped") {
|
|
||||||
stopVirtmic();
|
|
||||||
} else if (message == "!discord-screenaudio-about") {
|
|
||||||
#ifdef KXMLGUI
|
|
||||||
m_helpMenu->aboutApplication();
|
|
||||||
#endif
|
|
||||||
} else if (message == "!discord-screenaudio-keybinds") {
|
|
||||||
#ifdef KXMLGUI
|
|
||||||
#ifdef KGLOBALACCEL
|
|
||||||
m_shortcutsDialog->show();
|
|
||||||
#else
|
|
||||||
QMessageBox::information(MainWindow::instance(), "discord-screenaudio",
|
|
||||||
"Keybinds are not supported on this platform "
|
|
||||||
"(KGlobalAccel is not available).",
|
|
||||||
QMessageBox::Ok);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
QMessageBox::information(MainWindow::instance(), "discord-screenaudio",
|
|
||||||
"Keybinds are not supported on this platform "
|
|
||||||
"(KXmlGui and KGlobalAccel are not available).",
|
|
||||||
QMessageBox::Ok);
|
|
||||||
#endif
|
|
||||||
} else if (message == "!discord-screenaudio-tray-true") {
|
|
||||||
MainWindow::instance()->setTrayIcon(true);
|
|
||||||
} else if (message == "!discord-screenaudio-tray-false") {
|
|
||||||
MainWindow::instance()->setTrayIcon(false);
|
|
||||||
} else if (message == "!discord-screenaudio-starthidden-true") {
|
|
||||||
MainWindow::instance()->settings()->setValue("startHidden", true);
|
|
||||||
} else if (message == "!discord-screenaudio-starthidden-false") {
|
|
||||||
MainWindow::instance()->settings()->setValue("startHidden", false);
|
|
||||||
} else if (message.startsWith("dsa: ")) {
|
|
||||||
qDebug(userscriptLog) << message.mid(5).toUtf8().constData();
|
|
||||||
} else {
|
|
||||||
qDebug(discordLog) << message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DiscordPage::startStream(bool video, bool audio, uint width, uint height,
|
|
||||||
uint frameRate, QString target) {
|
|
||||||
stopVirtmic();
|
|
||||||
startVirtmic(audio ? target : "[None]");
|
|
||||||
// Wait a bit for the virtmic to start
|
|
||||||
QTimer::singleShot(200, [=]() {
|
|
||||||
runJavaScript(
|
|
||||||
QString("window.discordScreenaudioStartStream(%1, %2, %3, %4);")
|
|
||||||
.arg(video)
|
|
||||||
.arg(video ? width : 32)
|
|
||||||
.arg(video ? height : 16)
|
|
||||||
.arg(video ? frameRate : 1));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void DiscordPage::toggleMute() {
|
|
||||||
qDebug(shortcutLog) << "Toggling mute";
|
|
||||||
runJavaScript("window.discordScreenaudioToggleMute();");
|
|
||||||
}
|
|
||||||
|
|
||||||
void DiscordPage::toggleDeafen() {
|
|
||||||
qDebug(shortcutLog) << "Toggling deafen";
|
|
||||||
runJavaScript("window.discordScreenaudioToggleDeafen();");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "streamdialog.h"
|
#include "userscript.h"
|
||||||
#include "virtmic.h"
|
|
||||||
|
|
||||||
#ifdef KXMLGUI
|
|
||||||
#include <KActionCollection>
|
|
||||||
#include <KHelpMenu>
|
|
||||||
#include <KShortcutsDialog>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QWebEngineFullScreenRequest>
|
#include <QWebEngineFullScreenRequest>
|
||||||
#include <QWebEnginePage>
|
#include <QWebEnginePage>
|
||||||
|
|
||||||
|
@ -20,15 +12,7 @@ public:
|
||||||
explicit DiscordPage(QWidget *parent = nullptr);
|
explicit DiscordPage(QWidget *parent = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StreamDialog m_streamDialog;
|
UserScript m_userScript;
|
||||||
QProcess m_virtmicProcess;
|
|
||||||
#ifdef KXMLGUI
|
|
||||||
KHelpMenu *m_helpMenu;
|
|
||||||
#ifdef KGLOBALACCEL
|
|
||||||
KActionCollection *m_actionCollection;
|
|
||||||
KShortcutsDialog *m_shortcutsDialog;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
bool acceptNavigationRequest(const QUrl &url,
|
bool acceptNavigationRequest(const QUrl &url,
|
||||||
QWebEnginePage::NavigationType type,
|
QWebEnginePage::NavigationType type,
|
||||||
bool isMainFrame) override;
|
bool isMainFrame) override;
|
||||||
|
@ -39,16 +23,10 @@ private:
|
||||||
const QString &sourceID) override;
|
const QString &sourceID) override;
|
||||||
void injectScriptText(QString name, QString content);
|
void injectScriptText(QString name, QString content);
|
||||||
void injectScriptFile(QString name, QString source);
|
void injectScriptFile(QString name, QString source);
|
||||||
void stopVirtmic();
|
|
||||||
void startVirtmic(QString target);
|
|
||||||
void toggleMute();
|
|
||||||
void toggleDeafen();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void featurePermissionRequested(const QUrl &securityOrigin,
|
void featurePermissionRequested(const QUrl &securityOrigin,
|
||||||
QWebEnginePage::Feature feature);
|
QWebEnginePage::Feature feature);
|
||||||
void startStream(bool video, bool audio, uint width, uint height,
|
|
||||||
uint frameRate, QString target);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Will immediately get destroyed again but is needed for navigation to
|
// Will immediately get destroyed again but is needed for navigation to
|
||||||
|
|
|
@ -98,9 +98,9 @@ StreamDialog::StreamDialog() : QWidget() {
|
||||||
void StreamDialog::startStream() {
|
void StreamDialog::startStream() {
|
||||||
auto resolution = m_resolutionComboBox->currentData().toString().split('x');
|
auto resolution = m_resolutionComboBox->currentData().toString().split('x');
|
||||||
emit requestedStreamStart(m_videoGroupBox->isChecked(),
|
emit requestedStreamStart(m_videoGroupBox->isChecked(),
|
||||||
m_audioGroupBox->isChecked(),
|
m_audioGroupBox->isChecked(), resolution[0].toInt(),
|
||||||
resolution[0].toUInt(), resolution[1].toUInt(),
|
resolution[1].toInt(),
|
||||||
m_framerateComboBox->currentData().toUInt(),
|
m_framerateComboBox->currentData().toInt(),
|
||||||
m_targetComboBox->currentText());
|
m_targetComboBox->currentText());
|
||||||
setHidden(true);
|
setHidden(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ private:
|
||||||
QGroupBox *m_audioGroupBox;
|
QGroupBox *m_audioGroupBox;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void requestedStreamStart(bool video, bool audio, uint width, uint height,
|
void requestedStreamStart(bool video, bool audio, int width, int height,
|
||||||
uint frameRate, QString target);
|
int frameRate, QString target);
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void updateTargets();
|
void updateTargets();
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
#include "userscript.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#ifdef KXMLGUI
|
||||||
|
#include <KActionCollection>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UserScript::UserScript() : QObject() {
|
||||||
|
setupHelpMenu();
|
||||||
|
setupShortcutsDialog();
|
||||||
|
setupStreamDialog();
|
||||||
|
setupVirtmic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::setupHelpMenu() {
|
||||||
|
#ifdef KXMLGUI
|
||||||
|
m_kxmlgui = true;
|
||||||
|
|
||||||
|
KAboutData aboutData(
|
||||||
|
"discord-screenaudio", "discord-screenaudio",
|
||||||
|
QApplication::applicationVersion(),
|
||||||
|
"Custom Discord client with the ability to stream audio on Linux",
|
||||||
|
KAboutLicense::GPL_V3, "Copyright 2022 (C) Malte Jürgens");
|
||||||
|
aboutData.setBugAddress("https://github.com/maltejur/discord-screenaudio");
|
||||||
|
aboutData.addAuthor("Malte Jürgens", "Author", "maltejur@dismail.de",
|
||||||
|
"https://github.com/maltejur");
|
||||||
|
aboutData.addCredit("edisionnano",
|
||||||
|
"For creating and documenting the approach for streaming "
|
||||||
|
"audio in Discord used in this project.",
|
||||||
|
QString(),
|
||||||
|
"https://github.com/edisionnano/"
|
||||||
|
"Screenshare-with-audio-on-Discord-with-Linux");
|
||||||
|
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",
|
||||||
|
"https://github.com/Soundux/rohrkabel");
|
||||||
|
m_helpMenu = new KHelpMenu(MainWindow::instance(), aboutData);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::setupShortcutsDialog() {
|
||||||
|
#ifdef KXMLGUI
|
||||||
|
#ifdef KGLOBALACCEL
|
||||||
|
m_kglobalaccel = true;
|
||||||
|
|
||||||
|
auto toggleMuteAction = new QAction(this);
|
||||||
|
toggleMuteAction->setText("Toggle Mute");
|
||||||
|
toggleMuteAction->setIcon(QIcon::fromTheme("microphone-sensitivity-muted"));
|
||||||
|
connect(toggleMuteAction, &QAction::triggered, this,
|
||||||
|
&UserScript::muteToggled);
|
||||||
|
|
||||||
|
auto toggleDeafenAction = new QAction(this);
|
||||||
|
toggleDeafenAction->setText("Toggle Deafen");
|
||||||
|
toggleDeafenAction->setIcon(QIcon::fromTheme("audio-volume-muted"));
|
||||||
|
connect(toggleMuteAction, &QAction::triggered, this,
|
||||||
|
&UserScript::deafenToggled);
|
||||||
|
|
||||||
|
m_actionCollection = new KActionCollection(this);
|
||||||
|
m_actionCollection->addAction("toggleMute", toggleMuteAction);
|
||||||
|
KGlobalAccel::setGlobalShortcut(toggleMuteAction, QList<QKeySequence>{});
|
||||||
|
m_actionCollection->addAction("toggleDeafen", toggleDeafenAction);
|
||||||
|
KGlobalAccel::setGlobalShortcut(toggleDeafenAction, QList<QKeySequence>{});
|
||||||
|
|
||||||
|
m_shortcutsDialog = new KShortcutsDialog(KShortcutsEditor::GlobalAction);
|
||||||
|
m_shortcutsDialog->addCollection(m_actionCollection);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::setupStreamDialog() {
|
||||||
|
connect(&m_streamDialog, &StreamDialog::requestedStreamStart, this,
|
||||||
|
&UserScript::startStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::setupVirtmic() {
|
||||||
|
m_virtmicProcess.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserScript::isVirtmicRunning() {
|
||||||
|
return m_virtmicProcess.state() != QProcess::NotRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UserScript::version() { return QApplication::applicationVersion(); }
|
||||||
|
|
||||||
|
QVariant UserScript::getPref(QString name, QVariant fallback) {
|
||||||
|
return MainWindow::instance()->settings()->value(name, fallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserScript::getBoolPref(QString name, bool fallback) {
|
||||||
|
return getPref(name, fallback).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::setPref(QString name, QVariant value) {
|
||||||
|
return MainWindow::instance()->settings()->setValue(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::setTrayIcon(bool value) {
|
||||||
|
setPref("trayIcon", value);
|
||||||
|
MainWindow::instance()->setTrayIcon(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::log(QString message) {
|
||||||
|
qDebug(userscriptLog) << message.toUtf8().constData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::showShortcutsDialog() {
|
||||||
|
#ifdef KXMLGUI
|
||||||
|
#ifdef KGLOBALACCEL
|
||||||
|
m_shortcutsDialog->show();
|
||||||
|
#else
|
||||||
|
QMessageBox::information(MainWindow::instance(), "discord-screenaudio",
|
||||||
|
"Keybinds are not supported on this platform "
|
||||||
|
"(KGlobalAccel is not available).",
|
||||||
|
QMessageBox::Ok);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
QMessageBox::information(MainWindow::instance(), "discord-screenaudio",
|
||||||
|
"Keybinds are not supported on this platform "
|
||||||
|
"(KXmlGui and KGlobalAccel are not available).",
|
||||||
|
QMessageBox::Ok);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::showHelpMenu() {
|
||||||
|
#ifdef KXMLGUI
|
||||||
|
m_helpMenu->aboutApplication();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::stopVirtmic() {
|
||||||
|
if (m_virtmicProcess.state() == QProcess::Running) {
|
||||||
|
qDebug(virtmicLog) << "Stopping Virtmic";
|
||||||
|
m_virtmicProcess.kill();
|
||||||
|
m_virtmicProcess.waitForFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::startVirtmic(QString target) {
|
||||||
|
qDebug(virtmicLog) << "Starting Virtmic with target" << target;
|
||||||
|
m_virtmicProcess.start(QApplication::arguments()[0], {"--virtmic", target});
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::startStream(bool video, bool audio, int width, int height,
|
||||||
|
int frameRate, QString target) {
|
||||||
|
stopVirtmic();
|
||||||
|
startVirtmic(audio ? target : "[None]");
|
||||||
|
// Wait a bit for the virtmic to start
|
||||||
|
QTimer::singleShot(
|
||||||
|
200, [=]() { emit streamStarted(video, width, height, frameRate); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void UserScript::showStreamDialog() {
|
||||||
|
if (m_streamDialog.isHidden())
|
||||||
|
m_streamDialog.setHidden(false);
|
||||||
|
else
|
||||||
|
m_streamDialog.activateWindow();
|
||||||
|
m_streamDialog.updateTargets();
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "streamdialog.h"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QProcess>
|
||||||
|
|
||||||
|
#ifdef KXMLGUI
|
||||||
|
#include <KAboutData>
|
||||||
|
#include <KHelpMenu>
|
||||||
|
#include <KShortcutsDialog>
|
||||||
|
#include <KXmlGuiWindow>
|
||||||
|
#include <QAction>
|
||||||
|
|
||||||
|
#ifdef KGLOBALACCEL
|
||||||
|
#include <KGlobalAccel>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class UserScript : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
UserScript();
|
||||||
|
bool isVirtmicRunning();
|
||||||
|
Q_PROPERTY(QString version READ version);
|
||||||
|
Q_PROPERTY(bool kxmlgui MEMBER m_kxmlgui);
|
||||||
|
Q_PROPERTY(bool kglobalaccel MEMBER m_kglobalaccel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QProcess m_virtmicProcess;
|
||||||
|
StreamDialog m_streamDialog;
|
||||||
|
bool m_kxmlgui = false;
|
||||||
|
bool m_kglobalaccel = false;
|
||||||
|
#ifdef KXMLGUI
|
||||||
|
KHelpMenu *m_helpMenu;
|
||||||
|
#ifdef KGLOBALACCEL
|
||||||
|
KActionCollection *m_actionCollection;
|
||||||
|
KShortcutsDialog *m_shortcutsDialog;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
void setupHelpMenu();
|
||||||
|
void setupShortcutsDialog();
|
||||||
|
void setupStreamDialog();
|
||||||
|
void setupVirtmic();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void muteToggled();
|
||||||
|
void deafenToggled();
|
||||||
|
void streamStarted(bool video, int width, int height, int frameRate);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void log(QString message);
|
||||||
|
QString version();
|
||||||
|
QVariant getPref(QString name, QVariant fallback);
|
||||||
|
bool getBoolPref(QString name, bool fallback);
|
||||||
|
void setPref(QString name, QVariant value);
|
||||||
|
void setTrayIcon(bool value);
|
||||||
|
void showShortcutsDialog();
|
||||||
|
void showHelpMenu();
|
||||||
|
void showStreamDialog();
|
||||||
|
void stopVirtmic();
|
||||||
|
void startVirtmic(QString target);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void startStream(bool video, bool audio, int width, int height, int frameRate,
|
||||||
|
QString target);
|
||||||
|
};
|
Loading…
Reference in New Issue