diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 78a0c0b23..ba4361560 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 6d96dcfc6..6af544370 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 2ba8f94c0..5727258d1 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 85e804600..1325f3dde 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();