Compare commits

...

10 Commits

Author SHA1 Message Date
Malte Jürgens
f2de080e1b update labels 2022-11-22 16:39:58 +01:00
Malte Jürgens
f4a60f281d reworked stream dialog 2022-11-22 16:35:47 +01:00
Malte Jürgens
d693535d53 Revert "add clipboard permission"
This reverts commit b0a8815bb8.
2022-11-09 22:13:34 +01:00
Malte Jürgens
e41af697f7 fix error 2022-11-05 00:08:25 +01:00
Malte Jürgens
b0a8815bb8 add clipboard permission 2022-11-04 23:20:46 +01:00
Malte Jürgens
150fd4364e add --notify-send option 2022-11-04 23:16:49 +01:00
Malte Jürgens
a0a2924796 remove Vencord folder 2022-11-04 20:45:55 +00:00
Malte Jürgens
3c48621427 add developer field to metainfo 2022-10-28 21:57:32 +02:00
Malte Jürgens
9faabe1f3e Merge pull request #66 from kherchel/fix/keybinds
Fix mute and deafen keybinds disconnecting from the call
2022-10-25 18:18:08 +00:00
Kacper Herchel
68473d04d8 Fix mute and deafen keybinds disconnecting from the call instead of performing their appropriate action 2022-10-25 17:01:10 +02:00
9 changed files with 172 additions and 95 deletions

View File

@@ -4,6 +4,7 @@
<metadata_license>CC0-1.0</metadata_license> <metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0+</project_license> <project_license>GPL-3.0+</project_license>
<name>discord-screenaudio</name> <name>discord-screenaudio</name>
<developer_name>Malte Jürgens</developer_name>
<releases> <releases>
<release version="${DISCORD_SCEENAUDIO_VERSION_FULL}" timestamp="${TIMESTAMP}" /> <release version="${DISCORD_SCEENAUDIO_VERSION_FULL}" timestamp="${TIMESTAMP}" />
</releases> </releases>

View File

@@ -25,7 +25,7 @@ const getAudioDevice = async (nameOfAudioDevice) => {
return audioDevice; return audioDevice;
}; };
function setGetDisplayMedia(overrideArgs = undefined) { function setGetDisplayMedia(video = true, overrideArgs = undefined) {
const getDisplayMedia = async (...args) => { const getDisplayMedia = async (...args) => {
var id; var id;
try { try {
@@ -63,6 +63,7 @@ function setGetDisplayMedia(overrideArgs = undefined) {
: args || [{ video: true, audio: true }]) : args || [{ video: true, audio: true }])
); );
gdm.addTrack(track); gdm.addTrack(track);
if (!video) for (const track of gdm.getVideoTracks()) track.enabled = false;
return gdm; return gdm;
}; };
navigator.mediaDevices.getDisplayMedia = getDisplayMedia; navigator.mediaDevices.getDisplayMedia = getDisplayMedia;
@@ -111,9 +112,16 @@ setInterval(() => {
const initialDisplay = el.style.display; const initialDisplay = el.style.display;
window.discordScreenaudioStartStream = (width, height, frameRate) => { window.discordScreenaudioStartStream = (
window.discordScreenaudioResolutionString = `${height}p ${frameRate}FPS`; video,
setGetDisplayMedia({ width,
height,
frameRate
) => {
window.discordScreenaudioResolutionString = video
? `${height}p ${frameRate}FPS`
: "Audio Only";
setGetDisplayMedia(video, {
audio: true, audio: true,
video: { width, height, frameRate }, video: { width, height, frameRate },
}); });
@@ -183,14 +191,28 @@ setInterval(() => {
el.appendChild(div); el.appendChild(div);
} }
const muteBtn = document.getElementsByClassName( const buttonContainer =
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F" document.getElementsByClassName("container-YkUktl")[0];
)[0]; if (!buttonContainer) {
window.discordScreenaudioToggleMute = () => muteBtn.click(); console.log(
const deafenBtn = document.getElementsByClassName( "dsa: Cannot locate Mute/Deafen/Settings button container, please report this on GitHub"
"button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F" );
)[1]; }
window.discordScreenaudioToggleDeafen = () => deafenBtn.click();
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) { if (window.discordScreenaudioResolutionString) {
for (const el of document.getElementsByClassName( for (const el of document.getElementsByClassName(

View File

@@ -186,10 +186,8 @@ void DiscordPage::stopVirtmic() {
} }
void DiscordPage::startVirtmic(QString target) { void DiscordPage::startVirtmic(QString target) {
if (target != "None") { qDebug(virtmicLog) << "Starting Virtmic with target" << target;
qDebug(virtmicLog) << "Starting Virtmic with target" << target; m_virtmicProcess.start(QApplication::arguments()[0], {"--virtmic", target});
m_virtmicProcess.start(QApplication::arguments()[0], {"--virtmic", target});
}
} }
void DiscordPage::javaScriptConsoleMessage( void DiscordPage::javaScriptConsoleMessage(
@@ -230,16 +228,18 @@ void DiscordPage::javaScriptConsoleMessage(
} }
} }
void DiscordPage::startStream(QString target, uint width, uint height, void DiscordPage::startStream(bool video, bool audio, uint width, uint height,
uint frameRate) { uint frameRate, QString target) {
stopVirtmic(); stopVirtmic();
startVirtmic(target); startVirtmic(audio ? target : "[None]");
// Wait a bit for the virtmic to start // Wait a bit for the virtmic to start
QTimer::singleShot(target == "None" ? 0 : 200, [=]() { QTimer::singleShot(200, [=]() {
runJavaScript(QString("window.discordScreenaudioStartStream(%1, %2, %3);") runJavaScript(
.arg(width) QString("window.discordScreenaudioStartStream(%1, %2, %3, %4);")
.arg(height) .arg(video)
.arg(frameRate)); .arg(video ? width : 32)
.arg(video ? height : 16)
.arg(video ? frameRate : 1));
}); });
} }

View File

@@ -47,7 +47,8 @@ private:
private Q_SLOTS: private Q_SLOTS:
void featurePermissionRequested(const QUrl &securityOrigin, void featurePermissionRequested(const QUrl &securityOrigin,
QWebEnginePage::Feature feature); QWebEnginePage::Feature feature);
void startStream(QString target, uint width, uint height, uint frameRate); 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

View File

@@ -30,6 +30,9 @@ int main(int argc, char *argv[]) {
QCommandLineOption degubOption("remote-debugging", QCommandLineOption degubOption("remote-debugging",
"Open Chromium Remote Debugging on port 9222"); "Open Chromium Remote Debugging on port 9222");
parser.addOption(degubOption); parser.addOption(degubOption);
QCommandLineOption notifySendOption(
"notify-send", "Use notify-send instead of QT/KF5 notifications");
parser.addOption(notifySendOption);
parser.process(app); parser.process(app);
@@ -46,7 +49,7 @@ int main(int argc, char *argv[]) {
"--remote-debugging-port=9222 " + "--remote-debugging-port=9222 " +
qgetenv("QTWEBENGINE_CHROMIUM_FLAGS")); qgetenv("QTWEBENGINE_CHROMIUM_FLAGS"));
MainWindow w; MainWindow w(parser.isSet(notifySendOption));
w.show(); w.show();
return app.exec(); return app.exec();

View File

@@ -24,9 +24,11 @@
MainWindow *MainWindow::m_instance = nullptr; MainWindow *MainWindow::m_instance = nullptr;
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { MainWindow::MainWindow(bool useNotifySend, QWidget *parent)
: QMainWindow(parent) {
assert(MainWindow::m_instance == nullptr); assert(MainWindow::m_instance == nullptr);
MainWindow::m_instance = this; MainWindow::m_instance = this;
m_useNotifySend = useNotifySend;
setupWebView(); setupWebView();
resize(1000, 700); resize(1000, 700);
showMaximized(); showMaximized();
@@ -40,22 +42,36 @@ void MainWindow::setupWebView() {
m_webView = new QWebEngineView(this); m_webView = new QWebEngineView(this);
m_webView->setPage(page); m_webView->setPage(page);
if (m_useKF5Notifications || m_useNotifySend)
QWebEngineProfile::defaultProfile()->setNotificationPresenter(
[&](std::unique_ptr<QWebEngineNotification> notificationInfo) {
if (m_useNotifySend) {
auto title = notificationInfo->title();
auto message = notificationInfo->message();
auto image_path =
QString("/tmp/discord-screenaudio-%1.png").arg(title);
notificationInfo->icon().save(image_path);
QProcess::execute("notify-send",
{"--icon", image_path, "--app-name",
"discord-screenaudio", title, message});
} else if (m_useKF5Notifications) {
#ifdef KNOTIFICATIONS #ifdef KNOTIFICATIONS
QWebEngineProfile::defaultProfile()->setNotificationPresenter( KNotification *notification =
[&](std::unique_ptr<QWebEngineNotification> notificationInfo) { new KNotification("discordNotification");
KNotification *notification = new KNotification("discordNotification"); notification->setTitle(notificationInfo->title());
notification->setTitle(notificationInfo->title()); notification->setText(notificationInfo->message());
notification->setText(notificationInfo->message()); notification->setPixmap(
notification->setPixmap(QPixmap::fromImage(notificationInfo->icon())); QPixmap::fromImage(notificationInfo->icon()));
notification->setDefaultAction("View"); notification->setDefaultAction("View");
connect(notification, &KNotification::defaultActivated, connect(notification, &KNotification::defaultActivated,
[&, notificationInfo = std::move(notificationInfo)]() { [&, notificationInfo = std::move(notificationInfo)]() {
notificationInfo->click(); notificationInfo->click();
activateWindow(); activateWindow();
}); });
notification->sendEvent(); notification->sendEvent();
});
#endif #endif
}
});
setCentralWidget(m_webView); setCentralWidget(m_webView);
} }

View File

@@ -14,7 +14,7 @@ class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
public: public:
explicit MainWindow(QWidget *parent = nullptr); explicit MainWindow(bool useNotifySend = false, QWidget *parent = nullptr);
static MainWindow *instance(); static MainWindow *instance();
private: private:
@@ -25,6 +25,12 @@ private:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
bool m_wasMaximized; bool m_wasMaximized;
static MainWindow *m_instance; static MainWindow *m_instance;
bool m_useNotifySend;
#ifdef KNOTIFICATIONS
bool m_useKF5Notifications = true;
#else
bool m_useKF5Notifications = false;
#endif
private Q_SLOTS: private Q_SLOTS:
void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest);

View File

@@ -12,70 +12,96 @@
StreamDialog::StreamDialog() : QWidget() { StreamDialog::StreamDialog() : QWidget() {
setAttribute(Qt::WA_QuitOnClose, false); setAttribute(Qt::WA_QuitOnClose, false);
auto layout = new QVBoxLayout(this); {
layout->setSizeConstraint(QLayout::SetFixedSize); auto layout = new QVBoxLayout(this);
layout->setSizeConstraint(QLayout::SetFixedSize);
auto targetLabel = new QLabel(this); m_videoGroupBox = new QGroupBox(this);
targetLabel->setText("Which app do you want to stream sound from?"); m_videoGroupBox->setTitle("Video");
layout->addWidget(targetLabel); m_videoGroupBox->setCheckable(true);
layout->addWidget(m_videoGroupBox);
auto targetHBox = new QHBoxLayout(this); {
layout->addLayout(targetHBox); auto videoLayout = new QVBoxLayout(this);
m_videoGroupBox->setLayout(videoLayout);
m_targetComboBox = new QComboBox(this); auto resolutionLabel = new QLabel(this);
updateTargets(); resolutionLabel->setText("Resolution");
targetHBox->addWidget(m_targetComboBox); videoLayout->addWidget(resolutionLabel);
auto refreshTargetsButton = new QPushButton(this); m_resolutionComboBox = new QComboBox(this);
refreshTargetsButton->setFixedSize(30, 30); m_resolutionComboBox->addItem("2160p", "3840x2160");
refreshTargetsButton->setIcon(QIcon::fromTheme("view-refresh")); m_resolutionComboBox->addItem("1440p", "2560x1440");
connect(refreshTargetsButton, &QPushButton::clicked, this, m_resolutionComboBox->addItem("1080p", "1920x1080");
&StreamDialog::updateTargets); m_resolutionComboBox->addItem("720p", "1280x720");
targetHBox->addWidget(refreshTargetsButton); m_resolutionComboBox->addItem("480p", "854x480");
m_resolutionComboBox->addItem("360p", "640x360");
m_resolutionComboBox->addItem("240p", "426x240");
m_resolutionComboBox->setCurrentText("720p");
videoLayout->addWidget(m_resolutionComboBox);
auto qualityLabel = new QLabel(this); auto framerateLabel = new QLabel(this);
qualityLabel->setText("Stream Quality"); framerateLabel->setText("Framerate");
layout->addWidget(qualityLabel); videoLayout->addWidget(framerateLabel);
auto qualityHBox = new QHBoxLayout(this); m_framerateComboBox = new QComboBox(this);
layout->addLayout(qualityHBox); m_framerateComboBox->addItem("144 FPS", 144);
m_framerateComboBox->addItem("60 FPS", 60);
m_framerateComboBox->addItem("30 FPS", 30);
m_framerateComboBox->addItem("15 FPS", 15);
m_framerateComboBox->addItem("5 FPS", 5);
m_framerateComboBox->setCurrentText("30 FPS");
videoLayout->addWidget(m_framerateComboBox);
}
m_qualityResolutionComboBox = new QComboBox(this); m_audioGroupBox = new QGroupBox(this);
m_qualityResolutionComboBox->addItem("2160p", "3840x2160"); m_audioGroupBox->setCheckable(true);
m_qualityResolutionComboBox->addItem("1440p", "2560x1440"); m_audioGroupBox->setTitle("Audio");
m_qualityResolutionComboBox->addItem("1080p", "1920x1080"); layout->addWidget(m_audioGroupBox);
m_qualityResolutionComboBox->addItem("720p", "1280x720");
m_qualityResolutionComboBox->addItem("480p", "854x480");
m_qualityResolutionComboBox->addItem("360p", "640x360");
m_qualityResolutionComboBox->addItem("240p", "426x240");
m_qualityResolutionComboBox->setCurrentText("720p");
qualityHBox->addWidget(m_qualityResolutionComboBox);
m_qualityFPSComboBox = new QComboBox(this); {
m_qualityFPSComboBox->addItem("144 FPS", 144); auto audioLayout = new QVBoxLayout(this);
m_qualityFPSComboBox->addItem("60 FPS", 60); m_audioGroupBox->setLayout(audioLayout);
m_qualityFPSComboBox->addItem("30 FPS", 30);
m_qualityFPSComboBox->addItem("15 FPS", 15);
m_qualityFPSComboBox->addItem("5 FPS", 5);
m_qualityFPSComboBox->setCurrentText("30 FPS");
qualityHBox->addWidget(m_qualityFPSComboBox);
auto button = new QPushButton(this); auto targetLabel = new QLabel(this);
button->setText("Start Stream"); targetLabel->setText("Audio Source");
connect(button, &QPushButton::clicked, this, &StreamDialog::startStream); audioLayout->addWidget(targetLabel);
layout->addWidget(button, Qt::AlignRight | Qt::AlignBottom);
setLayout(layout); {
auto targetLayout = new QHBoxLayout(this);
audioLayout->addLayout(targetLayout);
m_targetComboBox = new QComboBox(this);
updateTargets();
targetLayout->addWidget(m_targetComboBox);
auto refreshTargetsButton = new QPushButton(this);
refreshTargetsButton->setFixedSize(30, 30);
refreshTargetsButton->setIcon(QIcon::fromTheme("view-refresh"));
connect(refreshTargetsButton, &QPushButton::clicked, this,
&StreamDialog::updateTargets);
targetLayout->addWidget(refreshTargetsButton);
}
}
auto button = new QPushButton(this);
button->setText("Start Stream");
connect(button, &QPushButton::clicked, this, &StreamDialog::startStream);
layout->addWidget(button, Qt::AlignRight | Qt::AlignBottom);
setLayout(layout);
}
setWindowTitle("discord-screenaudio Stream Dialog"); setWindowTitle("discord-screenaudio Stream Dialog");
} }
void StreamDialog::startStream() { void StreamDialog::startStream() {
auto resolution = auto resolution = m_resolutionComboBox->currentData().toString().split('x');
m_qualityResolutionComboBox->currentData().toString().split('x'); emit requestedStreamStart(m_videoGroupBox->isChecked(),
emit requestedStreamStart(m_targetComboBox->currentText(), m_audioGroupBox->isChecked(),
resolution[0].toUInt(), resolution[1].toUInt(), resolution[0].toUInt(), resolution[1].toUInt(),
m_qualityFPSComboBox->currentData().toUInt()); m_framerateComboBox->currentData().toUInt(),
m_targetComboBox->currentText());
setHidden(true); setHidden(true);
} }
@@ -83,7 +109,6 @@ void StreamDialog::updateTargets() {
auto lastTarget = m_targetComboBox->currentText(); auto lastTarget = m_targetComboBox->currentText();
m_targetComboBox->clear(); m_targetComboBox->clear();
m_targetComboBox->addItem("[None]");
m_targetComboBox->addItem("[All Desktop Audio]"); m_targetComboBox->addItem("[All Desktop Audio]");
for (auto target : Virtmic::getTargets()) { for (auto target : Virtmic::getTargets()) {
m_targetComboBox->addItem(target); m_targetComboBox->addItem(target);

View File

@@ -2,6 +2,7 @@
#include <QComboBox> #include <QComboBox>
#include <QDialog> #include <QDialog>
#include <QGroupBox>
#include <QWidget> #include <QWidget>
class StreamDialog : public QWidget { class StreamDialog : public QWidget {
@@ -12,12 +13,14 @@ public:
private: private:
QComboBox *m_targetComboBox; QComboBox *m_targetComboBox;
QComboBox *m_qualityResolutionComboBox; QComboBox *m_resolutionComboBox;
QComboBox *m_qualityFPSComboBox; QComboBox *m_framerateComboBox;
QGroupBox *m_videoGroupBox;
QGroupBox *m_audioGroupBox;
Q_SIGNALS: Q_SIGNALS:
void requestedStreamStart(QString target, uint width, uint height, void requestedStreamStart(bool video, bool audio, uint width, uint height,
uint frameRate); uint frameRate, QString target);
public Q_SLOTS: public Q_SLOTS:
void updateTargets(); void updateTargets();