From 76b6266689fd88a2d085650b16e7baf72b8d2d5e Mon Sep 17 00:00:00 2001 From: cg2121 Date: Wed, 13 Sep 2017 21:10:45 -0700 Subject: [PATCH] UI: Allow hiding/unhiding sources in the mixer Allows the ability to hide/unhide sources in the mixer that the user doesn't care about or doesn't necessarily want to see (such as video sources that have audio but don't have any audio playing). If all sources are hidden, the user can right-click the mixer's empty area and choose "unhide all" via a context menu. Closes jp9000/obs-studio#1002 --- UI/data/locale/en-US.ini | 2 + UI/forms/OBSBasic.ui | 5 +- UI/window-basic-main.cpp | 116 +++++++++++++++++++++++++++++++++++++++ UI/window-basic-main.hpp | 6 ++ 4 files changed, 128 insertions(+), 1 deletion(-) diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 78a0c0b2..ba436156 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -43,6 +43,7 @@ Clear="Clear" Revert="Revert" Show="Show" Hide="Hide" +UnhideAll="Unhide All" Untitled="Untitled" New="New" Duplicate="Duplicate" @@ -72,6 +73,7 @@ RemuxRecordings="Remux Recordings" Next="Next" Back="Back" Defaults="Defaults" +HideMixer="Hide in Mixer" # warning if program already open AlreadyRunning.Title="OBS is already running" diff --git a/UI/forms/OBSBasic.ui b/UI/forms/OBSBasic.ui index 6d96dcfc..6af54437 100644 --- a/UI/forms/OBSBasic.ui +++ b/UI/forms/OBSBasic.ui @@ -602,13 +602,16 @@ 4 - + 220 0 + + Qt::CustomContextMenu + QFrame::StyledPanel diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 2ba8f94c..5727258d 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -2186,6 +2186,22 @@ void OBSBasic::SelectSceneItem(OBSScene scene, OBSSceneItem item, bool select) } } +static inline bool SourceMixerHidden(obs_source_t *source) +{ + obs_data_t *priv_settings = obs_source_get_private_settings(source); + bool hidden = obs_data_get_bool(priv_settings, "mixer_hidden"); + obs_data_release(priv_settings); + + return hidden; +} + +static inline void SetSourceMixerHidden(obs_source_t *source, bool hidden) +{ + obs_data_t *priv_settings = obs_source_get_private_settings(source); + obs_data_set_bool(priv_settings, "mixer_hidden", hidden); + obs_data_release(priv_settings); +} + void OBSBasic::GetAudioSourceFilters() { QAction *action = reinterpret_cast(sender()); @@ -2204,14 +2220,78 @@ void OBSBasic::GetAudioSourceProperties() CreatePropertiesWindow(source); } +void OBSBasic::HideAudioControl() +{ + QAction *action = reinterpret_cast(sender()); + VolControl *vol = action->property("volControl").value(); + obs_source_t *source = vol->GetSource(); + + if (!SourceMixerHidden(source)) { + SetSourceMixerHidden(source, true); + DeactivateAudioSource(source); + } +} + +void OBSBasic::UnhideAllAudioControls() +{ + auto UnhideAudioMixer = [this] (obs_source_t *source) /* -- */ + { + if (!obs_source_active(source)) + return true; + if (!SourceMixerHidden(source)) + return true; + + SetSourceMixerHidden(source, false); + ActivateAudioSource(source); + return true; + }; + + using UnhideAudioMixer_t = decltype(UnhideAudioMixer); + + auto PreEnum = [] (void *data, obs_source_t *source) -> bool /* -- */ + { + return (*reinterpret_cast(data))(source); + }; + + obs_enum_sources(PreEnum, &UnhideAudioMixer); +} + +void OBSBasic::ToggleHideMixer() +{ + OBSSceneItem item = GetCurrentSceneItem(); + OBSSource source = obs_sceneitem_get_source(item); + + if (!SourceMixerHidden(source)) { + SetSourceMixerHidden(source, true); + DeactivateAudioSource(source); + } else { + SetSourceMixerHidden(source, false); + ActivateAudioSource(source); + } +} + void OBSBasic::VolControlContextMenu() { VolControl *vol = reinterpret_cast(sender()); + /* ------------------- */ + + QAction hideAction(QTStr("Hide"), this); + QAction unhideAllAction(QTStr("UnhideAll"), this); + QAction filtersAction(QTStr("Filters"), this); QAction propertiesAction(QTStr("Properties"), this); QAction advPropAction(QTStr("Basic.MainMenu.Edit.AdvAudio"), this); + /* ------------------- */ + + connect(&hideAction, &QAction::triggered, + this, &OBSBasic::HideAudioControl, + Qt::DirectConnection); + connect(&unhideAllAction, &QAction::triggered, + this, &OBSBasic::UnhideAllAudioControls, + Qt::DirectConnection); + connect(&filtersAction, &QAction::triggered, this, &OBSBasic::GetAudioSourceFilters, Qt::DirectConnection); @@ -2222,20 +2302,45 @@ void OBSBasic::VolControlContextMenu() this, &OBSBasic::on_actionAdvAudioProperties_triggered, Qt::DirectConnection); + /* ------------------- */ + + hideAction.setProperty("volControl", + QVariant::fromValue(vol)); + filtersAction.setProperty("volControl", QVariant::fromValue(vol)); propertiesAction.setProperty("volControl", QVariant::fromValue(vol)); + /* ------------------- */ + QMenu popup(this); + popup.addAction(&unhideAllAction); + popup.addAction(&hideAction); + popup.addSeparator(); popup.addAction(&filtersAction); popup.addAction(&propertiesAction); popup.addAction(&advPropAction); popup.exec(QCursor::pos()); } +void OBSBasic::on_mixerScrollArea_customContextMenuRequested() +{ + QAction unhideAllAction(QTStr("UnhideAll"), this); + connect(&unhideAllAction, &QAction::triggered, + this, &OBSBasic::UnhideAllAudioControls, + Qt::DirectConnection); + + QMenu popup(this); + popup.addAction(&unhideAllAction); + popup.exec(QCursor::pos()); +} + void OBSBasic::ActivateAudioSource(OBSSource source) { + if (SourceMixerHidden(source)) + return; + VolControl *vol = new VolControl(source, true); vol->setContextMenuPolicy(Qt::CustomContextMenu); @@ -3519,6 +3624,8 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview) uint32_t flags = obs_source_get_output_flags(source); bool isAsyncVideo = (flags & OBS_SOURCE_ASYNC_VIDEO) == OBS_SOURCE_ASYNC_VIDEO; + bool hasAudio = (flags & OBS_SOURCE_AUDIO) == + OBS_SOURCE_AUDIO; QAction *action; popup.addAction(QTStr("Rename"), this, @@ -3541,6 +3648,15 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview) popup.addAction(sourceWindow); popup.addSeparator(); + + if (hasAudio) { + QAction *actionHideMixer = popup.addAction( + QTStr("HideMixer"), + this, SLOT(ToggleHideMixer())); + actionHideMixer->setCheckable(true); + actionHideMixer->setChecked(SourceMixerHidden(source)); + } + if (isAsyncVideo) { popup.addMenu(AddDeinterlacingMenu(source)); popup.addSeparator(); diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 85e80460..1325f3dd 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -429,6 +429,12 @@ private slots: void ToggleShowHide(); + void HideAudioControl(); + void UnhideAllAudioControls(); + void ToggleHideMixer(); + + void on_mixerScrollArea_customContextMenuRequested(); + void on_actionCopySource_triggered(); void on_actionPasteRef_triggered(); void on_actionPasteDup_triggered(); -- GitLab