Compare commits
	
		
			8 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d6641a7a6e | ||
|  | b836be6530 | ||
|  | bfb0714b13 | ||
|  | 374b854261 | ||
|  | 1f6105f76b | ||
|  | 3071159332 | ||
|  | f2de080e1b | ||
|  | f4a60f281d | 
| @@ -13,24 +13,27 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") | |||||||
| string(TIMESTAMP TIMESTAMP %s) | string(TIMESTAMP TIMESTAMP %s) | ||||||
| # set(CMAKE_AUTOUIC ON) | # set(CMAKE_AUTOUIC ON) | ||||||
|  |  | ||||||
| find_package(Qt5 CONFIG REQUIRED COMPONENTS  | find_package(Qt5 COMPONENTS Widgets) | ||||||
|   Widgets | if (Qt5_FOUND) | ||||||
|   WebEngineWidgets |   find_package(Qt5 CONFIG REQUIRED COMPONENTS Widgets WebEngineWidgets) | ||||||
| ) |  | ||||||
|  |  | ||||||
| find_package(KF5Notifications) |   find_package(KF5Notifications) | ||||||
| if(KF5Notifications_FOUND) |   if(KF5Notifications_FOUND) | ||||||
|     add_definitions( -DKNOTIFICATIONS ) |     add_definitions( -DKNOTIFICATIONS ) | ||||||
| endif() |   endif() | ||||||
|  |  | ||||||
| find_package(KF5XmlGui) |   find_package(KF5XmlGui) | ||||||
| if(KF5XmlGui_FOUND) |   if(KF5XmlGui_FOUND) | ||||||
|     add_definitions( -DKXMLGUI ) |     add_definitions( -DKXMLGUI ) | ||||||
| endif() |   endif() | ||||||
|  |  | ||||||
| find_package(KF5GlobalAccel) |   find_package(KF5GlobalAccel) | ||||||
| if(KF5GlobalAccel_FOUND) |   if(KF5GlobalAccel_FOUND) | ||||||
|     add_definitions( -DKGLOBALACCEL ) |     add_definitions( -DKGLOBALACCEL ) | ||||||
|  |   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() | endif() | ||||||
|  |  | ||||||
| set(discord-screenaudio_SRC | set(discord-screenaudio_SRC | ||||||
| @@ -66,7 +69,7 @@ add_subdirectory(submodules/rohrkabel) | |||||||
|  |  | ||||||
| add_executable(discord-screenaudio ${discord-screenaudio_SRC}) | add_executable(discord-screenaudio ${discord-screenaudio_SRC}) | ||||||
|  |  | ||||||
| target_link_libraries(discord-screenaudio Qt5::Widgets Qt5::WebEngineWidgets rohrkabel) | target_link_libraries(discord-screenaudio Qt::Widgets Qt::WebEngineWidgets rohrkabel) | ||||||
|  |  | ||||||
| if(KF5Notifications_FOUND) | if(KF5Notifications_FOUND) | ||||||
|   target_link_libraries(discord-screenaudio KF5::Notifications) |   target_link_libraries(discord-screenaudio KF5::Notifications) | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ Unlike a lot of other solutions, the audio here is directly fed into the | |||||||
| screenshare and not passed to the user microphone | screenshare and not passed to the user microphone | ||||||
| ([see explanation](#how-it-works)). | ([see explanation](#how-it-works)). | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| The purpose of this project is **not** to provide an alternative to the original | The purpose of this project is **not** to provide an alternative to the original | ||||||
| Discord client. Rather, it should be used in addition to the original client in | Discord client. Rather, it should be used in addition to the original client in | ||||||
| @@ -50,6 +50,8 @@ You have multiple options: | |||||||
| ### Requirements | ### Requirements | ||||||
|  |  | ||||||
| - Basic building tools | - Basic building tools | ||||||
|  | - An up-to-date system (I can't guarantee that it works on Debian or Ubuntu | ||||||
|  |   20/21) | ||||||
| - CMake | - CMake | ||||||
| - Qt5 and QtWebEngine | - Qt5 and QtWebEngine | ||||||
| - **PipeWire** (it currently doesn't work with PulseAudio) | - **PipeWire** (it currently doesn't work with PulseAudio) | ||||||
| @@ -57,7 +59,7 @@ You have multiple options: | |||||||
| - _Kf5Notifications (optional, for better notifications)_ | - _Kf5Notifications (optional, for better notifications)_ | ||||||
| - _KXMLGui and KGlobalAccel (optional, for keybinds)_ | - _KXMLGui and KGlobalAccel (optional, for keybinds)_ | ||||||
|  |  | ||||||
| On Debian: | 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` | ||||||
|  |  | ||||||
| ### Building | ### Building | ||||||
|   | |||||||
| @@ -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; | ||||||
| @@ -74,6 +75,52 @@ const clonedElements = []; | |||||||
| const hiddenElements = []; | const hiddenElements = []; | ||||||
| let wasStreamActive = false; | let wasStreamActive = false; | ||||||
|  |  | ||||||
|  | function createButton(text, onClick) { | ||||||
|  |   const button = document.createElement("button"); | ||||||
|  |   button.style.marginBottom = "20px"; | ||||||
|  |   button.classList = | ||||||
|  |     "button-f2h6uQ lookFilled-yCfaCM colorBrand-I6CyqQ sizeSmall-wU2dO- grow-2sR_-F"; | ||||||
|  |   button.innerText = text; | ||||||
|  |   button.addEventListener("click", onClick); | ||||||
|  |   return button; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function createSwitch(text, enabled, onClick) { | ||||||
|  |   const container = document.createElement("div"); | ||||||
|  |   container.style.marginBottom = "20px"; | ||||||
|  |   container.className = "labelRow-2jl9gK"; | ||||||
|  |  | ||||||
|  |   const label = document.createElement("label"); | ||||||
|  |   label.innerText = text; | ||||||
|  |   label.className = "title-2dsDLn"; | ||||||
|  |   container.appendChild(label); | ||||||
|  |  | ||||||
|  |   const svg = document.createElement("div"); | ||||||
|  |   container.appendChild(svg); | ||||||
|  |  | ||||||
|  |   function setSvgDisabled() { | ||||||
|  |     svg.innerHTML = `<div class="container-2nx-BQ default-colors" style="opacity: 1; background-color: rgb(114, 118, 125);"><svg class="slider-32CRPX" viewBox="0 0 28 20" preserveAspectRatio="xMinYMid meet" aria-hidden="true" style="left: -3px;"><rect fill="white" x="4" y="0" height="20" width="20" rx="10"></rect><svg viewBox="0 0 20 20" fill="none"><path fill="rgba(114, 118, 125, 1)" d="M5.13231 6.72963L6.7233 5.13864L14.855 13.2704L13.264 14.8614L5.13231 6.72963Z"></path><path fill="rgba(114, 118, 125, 1)" d="M13.2704 5.13864L14.8614 6.72963L6.72963 14.8614L5.13864 13.2704L13.2704 5.13864Z"></path></svg></svg></div>`; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   function setSvgEnabled() { | ||||||
|  |     svg.innerHTML = `<div class="container-2nx-BQ default-colors checked-25WXMf" style="opacity: 1; background-color: rgb(59, 165, 92);"><svg class="slider-32CRPX" viewBox="0 0 28 20" preserveAspectRatio="xMinYMid meet" aria-hidden="true" style="left: 12px;"><rect fill="white" x="4" y="0" height="20" width="20" rx="10"></rect><svg viewBox="0 0 20 20" fill="none"><path fill="rgba(59, 165, 92, 1)" d="M7.89561 14.8538L6.30462 13.2629L14.3099 5.25755L15.9009 6.84854L7.89561 14.8538Z"></path><path fill="rgba(59, 165, 92, 1)" d="M4.08643 11.0903L5.67742 9.49929L9.4485 13.2704L7.85751 14.8614L4.08643 11.0903Z"></path></svg></svg></div>`; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   function updateSvg() { | ||||||
|  |     if (enabled) setSvgEnabled(); | ||||||
|  |     else setSvgDisabled(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   container.addEventListener("click", () => { | ||||||
|  |     enabled = !enabled; | ||||||
|  |     updateSvg(); | ||||||
|  |     onClick(enabled); | ||||||
|  |   }); | ||||||
|  |   updateSvg(); | ||||||
|  |  | ||||||
|  |   return container; | ||||||
|  | } | ||||||
|  |  | ||||||
| setInterval(() => { | setInterval(() => { | ||||||
|   const streamActive = |   const streamActive = | ||||||
|     document.getElementsByClassName("panel-2ZFCRb activityPanel-9icbyU") |     document.getElementsByClassName("panel-2ZFCRb activityPanel-9icbyU") | ||||||
| @@ -111,9 +158,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 }, | ||||||
|         }); |         }); | ||||||
| @@ -163,7 +217,7 @@ setInterval(() => { | |||||||
|     document |     document | ||||||
|       .getElementById("keybinds-tab") |       .getElementById("keybinds-tab") | ||||||
|       ?.getElementsByClassName( |       ?.getElementsByClassName( | ||||||
|         "container-3jbRo5 info-1hMolH fontSize16-3zr6Io browserNotice-1u-Y5o" |         "container-3jbRo5 info-1hMolH browserNotice-1u-Y5o" | ||||||
|       ).length |       ).length | ||||||
|   ) { |   ) { | ||||||
|     const el = document |     const el = document | ||||||
| @@ -171,31 +225,35 @@ setInterval(() => { | |||||||
|       .getElementsByClassName("children-1xdcWE")[0]; |       .getElementsByClassName("children-1xdcWE")[0]; | ||||||
|     const div = document.createElement("div"); |     const div = document.createElement("div"); | ||||||
|     div.style.marginBottom = "50px"; |     div.style.marginBottom = "50px"; | ||||||
|     const button = document.createElement("button"); |     div.appendChild( | ||||||
|     button.classList = |       createButton("Edit Global Keybinds", () => { | ||||||
|       "button-f2h6uQ lookFilled-yCfaCM colorBrand-I6CyqQ sizeSmall-wU2dO- grow-2sR_-F"; |  | ||||||
|     button.innerText = "Edit Global Keybinds"; |  | ||||||
|     button.addEventListener("click", () => { |  | ||||||
|         console.log("!discord-screenaudio-keybinds"); |         console.log("!discord-screenaudio-keybinds"); | ||||||
|     }); |       }) | ||||||
|     div.appendChild(button); |     ); | ||||||
|     el.innerHTML = ""; |     el.innerHTML = ""; | ||||||
|     el.appendChild(div); |     el.appendChild(div); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const buttonContainer = document.getElementsByClassName("container-YkUktl")[0]; |   const buttonContainer = | ||||||
|  |     document.getElementsByClassName("container-YkUktl")[0]; | ||||||
|   if (!buttonContainer) { |   if (!buttonContainer) { | ||||||
|     console.log('dsa: Cannot locate Mute/Deafen/Settings button container, please report this on GitHub'); |     console.log( | ||||||
|  |       "dsa: Cannot locate Mute/Deafen/Settings button container, please report this on GitHub" | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const muteBtn = buttonContainer ? buttonContainer.getElementsByClassName( |   const muteBtn = buttonContainer | ||||||
|  |     ? buttonContainer.getElementsByClassName( | ||||||
|         "button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F" |         "button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F" | ||||||
|   )[0] : null; |       )[0] | ||||||
|  |     : null; | ||||||
|   window.discordScreenaudioToggleMute = () => muteBtn && muteBtn.click(); |   window.discordScreenaudioToggleMute = () => muteBtn && muteBtn.click(); | ||||||
|  |  | ||||||
|   const deafenBtn = buttonContainer ? buttonContainer.getElementsByClassName( |   const deafenBtn = buttonContainer | ||||||
|  |     ? buttonContainer.getElementsByClassName( | ||||||
|         "button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F" |         "button-12Fmur enabled-9OeuTA button-f2h6uQ lookBlank-21BCro colorBrand-I6CyqQ grow-2sR_-F" | ||||||
|   )[1] : null; |       )[1] | ||||||
|  |     : null; | ||||||
|  |  | ||||||
|   window.discordScreenaudioToggleDeafen = () => deafenBtn && deafenBtn.click(); |   window.discordScreenaudioToggleDeafen = () => deafenBtn && deafenBtn.click(); | ||||||
|  |  | ||||||
| @@ -206,6 +264,51 @@ setInterval(() => { | |||||||
|       el.innerHTML = window.discordScreenaudioResolutionString; |       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-_0um2u 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-34Txb0 title-3hptVQ defaultColor-2cKwKo defaultMarginh1-EURXsm"; | ||||||
|  |         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) => { | ||||||
|  |               console.log(`!discord-screenaudio-tray-${enabled}`); | ||||||
|  |             } | ||||||
|  |           ) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         const divider = document.createElement("div"); | ||||||
|  |         divider.className = "divider-_0um2u marginTop40-Q4o1tS"; | ||||||
|  |  | ||||||
|  |         firstDivider.after(section); | ||||||
|  |         section.after(divider); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
| }, 500); | }, 500); | ||||||
|  |  | ||||||
| // Fix for broken discord notifications after restart | // Fix for broken discord notifications after restart | ||||||
|   | |||||||
| @@ -55,9 +55,14 @@ DiscordPage::DiscordPage(QWidget *parent) : QWebEnginePage(parent) { | |||||||
|  |  | ||||||
|   injectScriptFile("userscript.js", ":/assets/userscript.js"); |   injectScriptFile("userscript.js", ":/assets/userscript.js"); | ||||||
|  |  | ||||||
|   injectScriptText("version.js", |   injectScriptText("vars.js", | ||||||
|                    QString("window.discordScreenaudioVersion = '%1';") |                    QString("window.discordScreenaudioVersion = '%1'; " | ||||||
|                        .arg(QApplication::applicationVersion())); |                            "window.discordScreenaudioTrayEnabled = %2;") | ||||||
|  |                        .arg(QApplication::applicationVersion()) | ||||||
|  |                        .arg(MainWindow::instance() | ||||||
|  |                                 ->settings() | ||||||
|  |                                 ->value("trayIcon", false) | ||||||
|  |                                 .toBool())); | ||||||
|  |  | ||||||
| #ifdef KXMLGUI | #ifdef KXMLGUI | ||||||
|   injectScriptText("xmlgui.js", "window.discordScreenaudioKXMLGUI = true;"); |   injectScriptText("xmlgui.js", "window.discordScreenaudioKXMLGUI = true;"); | ||||||
| @@ -186,10 +191,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( | ||||||
| @@ -223,6 +226,10 @@ void DiscordPage::javaScriptConsoleMessage( | |||||||
|                              "(KXmlGui and KGlobalAccel are not available).", |                              "(KXmlGui and KGlobalAccel are not available).", | ||||||
|                              QMessageBox::Ok); |                              QMessageBox::Ok); | ||||||
| #endif | #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.startsWith("dsa: ")) { |   } else if (message.startsWith("dsa: ")) { | ||||||
|     qDebug(userscriptLog) << message.mid(5).toUtf8().constData(); |     qDebug(userscriptLog) << message.mid(5).toUtf8().constData(); | ||||||
|   } else { |   } else { | ||||||
| @@ -230,16 +237,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)); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -29,7 +29,9 @@ MainWindow::MainWindow(bool useNotifySend, QWidget *parent) | |||||||
|   assert(MainWindow::m_instance == nullptr); |   assert(MainWindow::m_instance == nullptr); | ||||||
|   MainWindow::m_instance = this; |   MainWindow::m_instance = this; | ||||||
|   m_useNotifySend = useNotifySend; |   m_useNotifySend = useNotifySend; | ||||||
|  |   setupSettings(); | ||||||
|   setupWebView(); |   setupWebView(); | ||||||
|  |   setupTrayIcon(); | ||||||
|   resize(1000, 700); |   resize(1000, 700); | ||||||
|   showMaximized(); |   showMaximized(); | ||||||
| } | } | ||||||
| @@ -66,6 +68,7 @@ void MainWindow::setupWebView() { | |||||||
|             connect(notification, &KNotification::defaultActivated, |             connect(notification, &KNotification::defaultActivated, | ||||||
|                     [&, notificationInfo = std::move(notificationInfo)]() { |                     [&, notificationInfo = std::move(notificationInfo)]() { | ||||||
|                       notificationInfo->click(); |                       notificationInfo->click(); | ||||||
|  |                       show(); | ||||||
|                       activateWindow(); |                       activateWindow(); | ||||||
|                     }); |                     }); | ||||||
|             notification->sendEvent(); |             notification->sendEvent(); | ||||||
| @@ -87,6 +90,70 @@ void MainWindow::fullScreenRequested( | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void MainWindow::closeEvent(QCloseEvent *event) { QApplication::quit(); } | void MainWindow::setupTrayIcon() { | ||||||
|  |   if (m_settings->value("trayIcon", false).toBool() == false || | ||||||
|  |       m_trayIcon != nullptr) | ||||||
|  |     return; | ||||||
|  |  | ||||||
|  |   auto aboutAction = new QAction( | ||||||
|  |       "discord-screenaudio v" + QString(DISCORD_SCEENAUDIO_VERSION_FULL), this); | ||||||
|  |   aboutAction->setIcon(QIcon(":assets/de.shorsh.discord-screenaudio.png")); | ||||||
|  |   aboutAction->setEnabled(false); | ||||||
|  |  | ||||||
|  |   auto exitAction = new QAction("Exit", this); | ||||||
|  |   connect(exitAction, &QAction::triggered, []() { QApplication::quit(); }); | ||||||
|  |  | ||||||
|  |   m_trayIconMenu = new QMenu(this); | ||||||
|  |   m_trayIconMenu->addAction(aboutAction); | ||||||
|  |   m_trayIconMenu->addAction(exitAction); | ||||||
|  |  | ||||||
|  |   m_trayIcon = new QSystemTrayIcon(this); | ||||||
|  |   m_trayIcon->setContextMenu(m_trayIconMenu); | ||||||
|  |   m_trayIcon->setIcon(QIcon(":assets/de.shorsh.discord-screenaudio.png")); | ||||||
|  |   m_trayIcon->show(); | ||||||
|  |  | ||||||
|  |   connect(m_trayIcon, &QSystemTrayIcon::activated, [this](auto reason) { | ||||||
|  |     if (reason == QSystemTrayIcon::Trigger) { | ||||||
|  |       if (isVisible()) { | ||||||
|  |         hide(); | ||||||
|  |       } else { | ||||||
|  |         show(); | ||||||
|  |         activateWindow(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MainWindow::cleanTrayIcon() { | ||||||
|  |   m_trayIcon->hide(); | ||||||
|  |   m_trayIconMenu->deleteLater(); | ||||||
|  |   m_trayIcon->deleteLater(); | ||||||
|  |   m_trayIconMenu = nullptr; | ||||||
|  |   m_trayIcon = nullptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MainWindow::setupSettings() { | ||||||
|  |   m_settings = new QSettings("maltejur", "discord-screenaudio", this); | ||||||
|  |   m_settings->beginGroup("settings"); | ||||||
|  |   m_settings->endGroup(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QSettings *MainWindow::settings() const { return m_settings; } | ||||||
|  |  | ||||||
|  | void MainWindow::setTrayIcon(bool enabled) { | ||||||
|  |   m_settings->setValue("trayIcon", enabled); | ||||||
|  |   if (enabled) { | ||||||
|  |     setupTrayIcon(); | ||||||
|  |   } else { | ||||||
|  |     cleanTrayIcon(); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MainWindow::closeEvent(QCloseEvent *event) { | ||||||
|  |   if (m_settings->value("trayIcon", false).toBool()) { | ||||||
|  |     hide(); | ||||||
|  |   } else | ||||||
|  |     QApplication::quit(); | ||||||
|  | } | ||||||
|  |  | ||||||
| MainWindow *MainWindow::instance() { return m_instance; } | MainWindow *MainWindow::instance() { return m_instance; } | ||||||
|   | |||||||
| @@ -3,8 +3,11 @@ | |||||||
| #include "discordpage.h" | #include "discordpage.h" | ||||||
|  |  | ||||||
| #include <QMainWindow> | #include <QMainWindow> | ||||||
|  | #include <QMenu> | ||||||
| #include <QScopedPointer> | #include <QScopedPointer> | ||||||
|  | #include <QSettings> | ||||||
| #include <QString> | #include <QString> | ||||||
|  | #include <QSystemTrayIcon> | ||||||
| #include <QVector> | #include <QVector> | ||||||
| #include <QWebEnginePage> | #include <QWebEnginePage> | ||||||
| #include <QWebEngineProfile> | #include <QWebEngineProfile> | ||||||
| @@ -16,13 +19,20 @@ class MainWindow : public QMainWindow { | |||||||
| public: | public: | ||||||
|   explicit MainWindow(bool useNotifySend = false, QWidget *parent = nullptr); |   explicit MainWindow(bool useNotifySend = false, QWidget *parent = nullptr); | ||||||
|   static MainWindow *instance(); |   static MainWindow *instance(); | ||||||
|  |   QSettings *settings() const; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   void setupWebView(); |   void setupWebView(); | ||||||
|  |   void setupTrayIcon(); | ||||||
|  |   void cleanTrayIcon(); | ||||||
|  |   void setupSettings(); | ||||||
|   QWebEngineView *m_webView; |   QWebEngineView *m_webView; | ||||||
|   QWebEngineProfile *prepareProfile(); |   QWebEngineProfile *prepareProfile(); | ||||||
|   DiscordPage *m_discordPage; |   DiscordPage *m_discordPage; | ||||||
|   void closeEvent(QCloseEvent *event) override; |   void closeEvent(QCloseEvent *event) override; | ||||||
|  |   QSystemTrayIcon *m_trayIcon; | ||||||
|  |   QMenu *m_trayIconMenu; | ||||||
|  |   QSettings *m_settings; | ||||||
|   bool m_wasMaximized; |   bool m_wasMaximized; | ||||||
|   static MainWindow *m_instance; |   static MainWindow *m_instance; | ||||||
|   bool m_useNotifySend; |   bool m_useNotifySend; | ||||||
| @@ -32,6 +42,9 @@ private: | |||||||
|   bool m_useKF5Notifications = false; |   bool m_useKF5Notifications = false; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | public Q_SLOTS: | ||||||
|  |   void setTrayIcon(bool enabled); | ||||||
|  |  | ||||||
| private Q_SLOTS: | private Q_SLOTS: | ||||||
|   void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); |   void fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -12,53 +12,77 @@ | |||||||
| StreamDialog::StreamDialog() : QWidget() { | StreamDialog::StreamDialog() : QWidget() { | ||||||
|   setAttribute(Qt::WA_QuitOnClose, false); |   setAttribute(Qt::WA_QuitOnClose, false); | ||||||
|  |  | ||||||
|  |   { | ||||||
|     auto layout = new QVBoxLayout(this); |     auto layout = new QVBoxLayout(this); | ||||||
|     layout->setSizeConstraint(QLayout::SetFixedSize); |     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); | ||||||
|  |  | ||||||
|  |       auto resolutionLabel = new QLabel(this); | ||||||
|  |       resolutionLabel->setText("Resolution"); | ||||||
|  |       videoLayout->addWidget(resolutionLabel); | ||||||
|  |  | ||||||
|  |       m_resolutionComboBox = new QComboBox(this); | ||||||
|  |       m_resolutionComboBox->addItem("2160p", "3840x2160"); | ||||||
|  |       m_resolutionComboBox->addItem("1440p", "2560x1440"); | ||||||
|  |       m_resolutionComboBox->addItem("1080p", "1920x1080"); | ||||||
|  |       m_resolutionComboBox->addItem("720p", "1280x720"); | ||||||
|  |       m_resolutionComboBox->addItem("480p", "854x480"); | ||||||
|  |       m_resolutionComboBox->addItem("360p", "640x360"); | ||||||
|  |       m_resolutionComboBox->addItem("240p", "426x240"); | ||||||
|  |       m_resolutionComboBox->setCurrentText("720p"); | ||||||
|  |       videoLayout->addWidget(m_resolutionComboBox); | ||||||
|  |  | ||||||
|  |       auto framerateLabel = new QLabel(this); | ||||||
|  |       framerateLabel->setText("Framerate"); | ||||||
|  |       videoLayout->addWidget(framerateLabel); | ||||||
|  |  | ||||||
|  |       m_framerateComboBox = new QComboBox(this); | ||||||
|  |       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_audioGroupBox = new QGroupBox(this); | ||||||
|  |     m_audioGroupBox->setCheckable(true); | ||||||
|  |     m_audioGroupBox->setTitle("Audio"); | ||||||
|  |     layout->addWidget(m_audioGroupBox); | ||||||
|  |  | ||||||
|  |     { | ||||||
|  |       auto audioLayout = new QVBoxLayout(this); | ||||||
|  |       m_audioGroupBox->setLayout(audioLayout); | ||||||
|  |  | ||||||
|  |       auto targetLabel = new QLabel(this); | ||||||
|  |       targetLabel->setText("Audio Source"); | ||||||
|  |       audioLayout->addWidget(targetLabel); | ||||||
|  |  | ||||||
|  |       { | ||||||
|  |         auto targetLayout = new QHBoxLayout(this); | ||||||
|  |         audioLayout->addLayout(targetLayout); | ||||||
|  |  | ||||||
|         m_targetComboBox = new QComboBox(this); |         m_targetComboBox = new QComboBox(this); | ||||||
|         updateTargets(); |         updateTargets(); | ||||||
|   targetHBox->addWidget(m_targetComboBox); |         targetLayout->addWidget(m_targetComboBox); | ||||||
|  |  | ||||||
|         auto refreshTargetsButton = new QPushButton(this); |         auto refreshTargetsButton = new QPushButton(this); | ||||||
|         refreshTargetsButton->setFixedSize(30, 30); |         refreshTargetsButton->setFixedSize(30, 30); | ||||||
|         refreshTargetsButton->setIcon(QIcon::fromTheme("view-refresh")); |         refreshTargetsButton->setIcon(QIcon::fromTheme("view-refresh")); | ||||||
|         connect(refreshTargetsButton, &QPushButton::clicked, this, |         connect(refreshTargetsButton, &QPushButton::clicked, this, | ||||||
|                 &StreamDialog::updateTargets); |                 &StreamDialog::updateTargets); | ||||||
|   targetHBox->addWidget(refreshTargetsButton); |         targetLayout->addWidget(refreshTargetsButton); | ||||||
|  |       } | ||||||
|   auto qualityLabel = new QLabel(this); |     } | ||||||
|   qualityLabel->setText("Stream Quality"); |  | ||||||
|   layout->addWidget(qualityLabel); |  | ||||||
|  |  | ||||||
|   auto qualityHBox = new QHBoxLayout(this); |  | ||||||
|   layout->addLayout(qualityHBox); |  | ||||||
|  |  | ||||||
|   m_qualityResolutionComboBox = new QComboBox(this); |  | ||||||
|   m_qualityResolutionComboBox->addItem("2160p", "3840x2160"); |  | ||||||
|   m_qualityResolutionComboBox->addItem("1440p", "2560x1440"); |  | ||||||
|   m_qualityResolutionComboBox->addItem("1080p", "1920x1080"); |  | ||||||
|   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); |  | ||||||
|   m_qualityFPSComboBox->addItem("60 FPS", 60); |  | ||||||
|   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 button = new QPushButton(this); | ||||||
|     button->setText("Start Stream"); |     button->setText("Start Stream"); | ||||||
| @@ -66,16 +90,18 @@ StreamDialog::StreamDialog() : QWidget() { | |||||||
|     layout->addWidget(button, Qt::AlignRight | Qt::AlignBottom); |     layout->addWidget(button, Qt::AlignRight | Qt::AlignBottom); | ||||||
|  |  | ||||||
|     setLayout(layout); |     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); | ||||||
|   | |||||||
| @@ -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(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user