From 2232c6d925d217d40bd077433566979131ab13e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82?= <44851575+zneix@users.noreply.github.com> Date: Sun, 11 Oct 2020 13:52:14 +0200 Subject: [PATCH] Changed Streamer Mode settings (#2001) There's now a new (yet another, sigh) section in Settings -> General, which lets you set streamer mode to 'enable/disable/detect obs' and there are also separate settings for each of the things that streamer mode covers. I just have to add ping sounds and PR is ready to be merged :) * Show "Streamer Mode" image as link thumbnails if applicable * Moved hideViewerCountAndDuration to streamerMode settings Set it to false by default (just how it used to be under /misc settings, also reworked live tooltip to be a bit prettier and say "" in gray instead of "Live with for viewers" --- CHANGELOG.md | 3 +- src/messages/SharedMessageBuilder.cpp | 7 +++ src/providers/LinkResolver.cpp | 5 +- src/singletons/Settings.hpp | 16 ++++- src/util/StreamerMode.cpp | 76 ++++++++++++---------- src/util/StreamerMode.hpp | 2 + src/widgets/dialogs/UserInfoPopup.cpp | 3 +- src/widgets/helper/ChannelView.cpp | 12 +++- src/widgets/settingspages/GeneralPage.cpp | 29 ++++++++- src/widgets/splits/SplitHeader.cpp | 77 ++++++++++++++++------- 10 files changed, 164 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e531d4b2..8bc772381 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ## Unversioned -- Minor: Made the current channels emotes appear at the top of the emote picker popup. +- Major: Added Streamer Mode configuration (under `Settings -> General`), where you can select which features of Chatterino should behave differently when you are in Streamer Mode. (#2001) +- Minor: Made the current channels emotes appear at the top of the emote picker popup. (#2057) - Minor: Added viewer list button to twitch channel header. (#1978) - Minor: Added followage and subage information to usercard. (#2023) - Minor: Added an option to only open channels specified in command line with `-c` parameter. You can also use `--help` to display short help message (#1940) diff --git a/src/messages/SharedMessageBuilder.cpp b/src/messages/SharedMessageBuilder.cpp index 26a2d85a5..73d435eb4 100644 --- a/src/messages/SharedMessageBuilder.cpp +++ b/src/messages/SharedMessageBuilder.cpp @@ -7,6 +7,7 @@ #include "providers/twitch/TwitchCommon.hpp" #include "singletons/Settings.hpp" #include "singletons/WindowManager.hpp" +#include "util/StreamerMode.hpp" namespace chatterino { @@ -365,6 +366,12 @@ void SharedMessageBuilder::triggerHighlights() { static QUrl currentPlayerUrl; + if (isInStreamerMode() && getSettings()->streamerModeMuteMentions) + { + // We are in streamer mode with muting mention sounds enabled. Do nothing. + return; + } + if (getCSettings().isMutedChannel(this->channel->getName())) { // Do nothing. Pings are muted in this channel. diff --git a/src/providers/LinkResolver.cpp b/src/providers/LinkResolver.cpp index 41f511eb5..144f2aa4f 100644 --- a/src/providers/LinkResolver.cpp +++ b/src/providers/LinkResolver.cpp @@ -32,12 +32,11 @@ void LinkResolver::getLinkInfo( auto statusCode = root.value("status").toInt(); QString response = QString(); QString linkString = url; - ImagePtr thumbnail = nullptr; + ImagePtr thumbnail = + Image::fromUrl({root.value("thumbnail").toString()}); if (statusCode == 200) { response = root.value("tooltip").toString(); - thumbnail = - Image::fromUrl({root.value("thumbnail").toString()}); if (getSettings()->unshortLinks) { linkString = root.value("link").toString(); diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index eca85d320..b3c1b5722 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -9,6 +9,7 @@ #include "controllers/highlights/HighlightPhrase.hpp" #include "controllers/moderationactions/ModerationAction.hpp" #include "singletons/Toasts.hpp" +#include "util/StreamerMode.hpp" #include "widgets/Notebook.hpp" using TimeoutButton = std::pair; @@ -177,7 +178,18 @@ public: BoolSetting unshortLinks = {"/links/unshortLinks", false}; BoolSetting lowercaseDomains = {"/links/linkLowercase", true}; - /// Ignored phrases + /// Streamer Mode + EnumSetting enableStreamerMode = { + "/streamerMode/enabled", StreamerModeSetting::DetectObs}; + BoolSetting streamerModeHideUsercardAvatars = { + "/streamerMode/hideUsercardAvatars", true}; + BoolSetting streamerModeHideLinkThumbnails = { + "/streamerMode/hideLinkThumbnails", true}; + BoolSetting streamerModeHideViewerCountAndDuration = { + "/streamerMode/hideViewerCountAndDuration", false}; + BoolSetting streamerModeMuteMentions = {"/streamerMode/muteMentions", true}; + + /// Ignored Phrases QStringSetting ignoredPhraseReplace = {"/ignore/ignoredPhraseReplace", "***"}; @@ -314,8 +326,6 @@ public: BoolSetting restartOnCrash = {"/misc/restartOnCrash", false}; BoolSetting attachExtensionToAnyProcess = { "/misc/attachExtensionToAnyProcess", false}; - BoolSetting hideViewerCountAndDuration = { - "/misc/hideViewerCountAndDuration", false}; BoolSetting askOnImageUpload = {"/misc/askOnImageUpload", true}; /// Debug diff --git a/src/util/StreamerMode.cpp b/src/util/StreamerMode.cpp index 001e8f36b..799ae8d41 100644 --- a/src/util/StreamerMode.cpp +++ b/src/util/StreamerMode.cpp @@ -1,5 +1,7 @@ #include "StreamerMode.hpp" +#include "singletons/Settings.hpp" + #ifdef USEWINSDK # include @@ -24,47 +26,57 @@ const QStringList &broadcastingBinaries() bool isInStreamerMode() { -#ifdef USEWINSDK - if (IsWindowsVistaOrGreater()) + switch (getSettings()->enableStreamerMode.getEnum()) { - static bool cache = false; - static QDateTime time = QDateTime(); + case StreamerModeSetting::Enabled: + return true; + case StreamerModeSetting::Disabled: + return false; + } - if (time.isValid() && - time.addSecs(cooldownInS) > QDateTime::currentDateTime()) +#ifdef USEWINSDK + if (!IsWindowsVistaOrGreater()) + { + return false; + } + static bool cache = false; + static QDateTime time = QDateTime(); + + if (time.isValid() && + time.addSecs(cooldownInS) > QDateTime::currentDateTime()) + { + return cache; + } + + time = QDateTime::currentDateTime(); + + WTS_PROCESS_INFO *pWPIs = nullptr; + DWORD dwProcCount = 0; + + if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, + &dwProcCount)) + { + //Go through all processes retrieved + for (DWORD i = 0; i < dwProcCount; i++) { - return cache; - } + QString processName = QString::fromUtf16( + reinterpret_cast(pWPIs[i].pProcessName)); - time = QDateTime::currentDateTime(); - - WTS_PROCESS_INFO *pWPIs = nullptr; - DWORD dwProcCount = 0; - - if (WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, - &dwProcCount)) - { - //Go through all processes retrieved - for (DWORD i = 0; i < dwProcCount; i++) + if (broadcastingBinaries().contains(processName)) { - QString processName = QString::fromUtf16( - reinterpret_cast(pWPIs[i].pProcessName)); - - if (broadcastingBinaries().contains(processName)) - { - cache = true; - return true; - } + cache = true; + return true; } } - - if (pWPIs) - WTSFreeMemory(pWPIs); - - cache = false; } -#endif + if (pWPIs) + { + WTSFreeMemory(pWPIs); + } + + cache = false; +#endif return false; } diff --git a/src/util/StreamerMode.hpp b/src/util/StreamerMode.hpp index 10a58295c..989b4802c 100644 --- a/src/util/StreamerMode.hpp +++ b/src/util/StreamerMode.hpp @@ -2,6 +2,8 @@ namespace chatterino { +enum StreamerModeSetting { Disabled = 0, Enabled = 1, DetectObs = 2 }; + const QStringList &broadcastingBinaries(); bool isInStreamerMode(); diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index 3b45891f5..0fa98a5fc 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -586,7 +586,8 @@ void UserInfoPopup::updateUserData() [] { // failure }); - if (isInStreamerMode()) + if (isInStreamerMode() && + getSettings()->streamerModeHideUsercardAvatars) { this->ui_.avatarButton->setPixmap(getResources().streamerMode); } diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 4a3ccf7da..889033269 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -1314,13 +1314,21 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) { auto element = &hoverLayoutElement->getCreator(); auto thumbnailSize = getSettings()->thumbnailSize; - if (thumbnailSize == 0 || isInStreamerMode()) + if (!thumbnailSize) { tooltipPreviewImage.setImage(nullptr); } else { - tooltipPreviewImage.setImage(element->getThumbnail()); + const auto isHideLink = + isInStreamerMode() && + getSettings()->streamerModeHideLinkThumbnails && + (!element->getThumbnail()->url().string.isEmpty()); + auto thumb = + isHideLink ? Image::fromPixmap(getResources().streamerMode) + : element->getThumbnail(); + tooltipPreviewImage.setImage(std::move(thumb)); + if (element->getThumbnailType() == MessageElement::ThumbnailType::Link_Thumbnail) { diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index 3a5a0ff9b..01701b97b 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -13,6 +13,7 @@ #include "util/FuzzyConvert.hpp" #include "util/Helpers.hpp" #include "util/IncognitoBrowser.hpp" +#include "util/StreamerMode.hpp" #include "widgets/BaseWindow.hpp" #include "widgets/dialogs/ColorPickerDialog.hpp" #include "widgets/helper/ColorButton.hpp" @@ -529,6 +530,31 @@ void GeneralPage::initLayout(SettingsLayout &layout) return fuzzyToInt(args.value, 0); }); + layout.addTitle("Streamer Mode"); + layout.addDescription( + "Chatterino can automatically change behavior if it " + "detects that \"OBS Studio\" is running.\nSelect which " + "things you want to change while streaming"); + + ComboBox *dankDropdown = + layout.addDropdown::type>( + "Enable Streamer Mode", {"No", "Yes", "Detect OBS (Windows only)"}, + s.enableStreamerMode, [](int value) { return value; }, + [](DropdownArgs args) { + return static_cast(args.index); + }, + false); + dankDropdown->setMinimumWidth(dankDropdown->minimumSizeHint().width() + 10); + + layout.addCheckbox("Hide usercard avatars", + s.streamerModeHideUsercardAvatars); + layout.addCheckbox("Hide link thumbnails", + s.streamerModeHideLinkThumbnails); + layout.addCheckbox( + "Hide viewer count and stream length while hovering over split header", + s.streamerModeHideViewerCountAndDuration); + layout.addCheckbox("Mute mention sounds", s.streamerModeMuteMentions); + layout.addTitle("Emotes"); layout.addCheckbox("Enable", s.enableEmoteImages); layout.addCheckbox("Animate", s.animateEmotes); @@ -732,9 +758,6 @@ void GeneralPage::initLayout(SettingsLayout &layout) s.enableExperimentalIrc); layout.addCheckbox("Show unhandled IRC messages", s.showUnhandledIrcMessages); - layout.addCheckbox( - "Hide viewercount and stream length while hovering the split", - s.hideViewerCountAndDuration); layout.addDropdown( "Stack timeouts", {"Stack", "Stack until timeout", "Don't stack"}, s.timeoutStackStyle, [](int index) { return index; }, diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index baf9b6e29..1348de2fa 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -12,6 +12,7 @@ #include "singletons/WindowManager.hpp" #include "util/LayoutCreator.hpp" #include "util/LayoutHelper.hpp" +#include "util/StreamerMode.hpp" #include "widgets/Label.hpp" #include "widgets/TooltipWidget.hpp" #include "widgets/dialogs/SettingsDialog.hpp" @@ -86,30 +87,64 @@ namespace { } auto formatTooltip(const TwitchChannel::StreamStatus &s, QString thumbnail) { - return QString(" \ -

%1%2%3%4%5%6 for %7 with %8 viewers

") - .arg(s.title.toHtmlEscaped()) - .arg(s.title.isEmpty() ? QString() : "

") - .arg(getSettings()->thumbnailSizeStream.getValue() > 0 - ? ((thumbnail.isEmpty() - ? "Couldn't fetch thumbnail" - : "") + - "
") - : QString()) - .arg(s.game.toHtmlEscaped()) - .arg(s.game.isEmpty() ? QString() : "
") - .arg(s.rerun ? "Vod-casting" : "Live") - .arg(getSettings()->hideViewerCountAndDuration ? "<Hidden>" - : s.uptime) - .arg(getSettings()->hideViewerCountAndDuration - ? "<Hidden>" - : QString::number(s.viewerCount)); + auto title = [&s]() -> QString { + if (s.title.isEmpty()) + { + return QStringLiteral(""); + } + + return s.title.toHtmlEscaped() + "

"; + }(); + + auto tooltip = [&thumbnail]() -> QString { + if (getSettings()->thumbnailSizeStream.getValue() == 0) + { + return QStringLiteral(""); + } + + if (thumbnail.isEmpty()) + { + return QStringLiteral("Couldn't fetch thumbnail
"); + } + + return "
"; + }(); + + auto game = [&s]() -> QString { + if (s.game.isEmpty()) + { + return QStringLiteral(""); + } + + return s.game.toHtmlEscaped() + "
"; + }(); + + auto extraStreamData = [&s]() -> QString { + if (isInStreamerMode() && + getSettings()->streamerModeHideViewerCountAndDuration) + { + return QStringLiteral( + "<Streamer " + "Mode>"); + } + + return QString("%1 for %2 with %3 viewers") + .arg(s.rerun ? "Vod-casting" : "Live") + .arg(s.uptime) + .arg(QString::number(s.viewerCount)); + }(); + + return QString("

" + // + title + // + tooltip + // + game + // + extraStreamData + // + "

" // + ); } auto formatOfflineTooltip(const TwitchChannel::StreamStatus &s) { - return QString(" \ -

Offline
%1

") + return QString("

Offline
%1

") .arg(s.title.toHtmlEscaped()); } auto formatTitle(const TwitchChannel::StreamStatus &s, Settings &settings)