mirror of
https://github.com/obsproject/obs-studio.git
synced 2025-12-30 18:08:08 -05:00
318 lines
10 KiB
C++
318 lines
10 KiB
C++
/******************************************************************************
|
|
Copyright (C) 2023 by Lain Bailey <lain@obsproject.com>
|
|
Zachary Lund <admin@computerquip.com>
|
|
Philippe Groarke <philippe.groarke@gmail.com>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
******************************************************************************/
|
|
|
|
#include "OBSBasic.hpp"
|
|
|
|
#include <widgets/VolControl.hpp>
|
|
|
|
using namespace std;
|
|
|
|
void OBSBasic::UpdateVolumeControlsDecayRate()
|
|
{
|
|
double meterDecayRate = config_get_double(activeConfiguration, "Audio", "MeterDecayRate");
|
|
|
|
for (size_t i = 0; i < volumes.size(); i++) {
|
|
volumes[i]->SetMeterDecayRate(meterDecayRate);
|
|
}
|
|
}
|
|
|
|
void OBSBasic::UpdateVolumeControlsPeakMeterType()
|
|
{
|
|
uint32_t peakMeterTypeIdx = config_get_uint(activeConfiguration, "Audio", "PeakMeterType");
|
|
|
|
enum obs_peak_meter_type peakMeterType;
|
|
switch (peakMeterTypeIdx) {
|
|
case 0:
|
|
peakMeterType = SAMPLE_PEAK_METER;
|
|
break;
|
|
case 1:
|
|
peakMeterType = TRUE_PEAK_METER;
|
|
break;
|
|
default:
|
|
peakMeterType = SAMPLE_PEAK_METER;
|
|
break;
|
|
}
|
|
|
|
for (size_t i = 0; i < volumes.size(); i++) {
|
|
volumes[i]->setPeakMeterType(peakMeterType);
|
|
}
|
|
}
|
|
|
|
void OBSBasic::ClearVolumeControls()
|
|
{
|
|
for (VolControl *vol : volumes)
|
|
delete vol;
|
|
|
|
volumes.clear();
|
|
}
|
|
|
|
void OBSBasic::RefreshVolumeColors()
|
|
{
|
|
for (VolControl *vol : volumes) {
|
|
vol->refreshColors();
|
|
}
|
|
}
|
|
|
|
void OBSBasic::HideAudioControl()
|
|
{
|
|
QAction *action = reinterpret_cast<QAction *>(sender());
|
|
VolControl *vol = action->property("volControl").value<VolControl *>();
|
|
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<UnhideAudioMixer_t *>(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::LockVolumeControl(bool lock)
|
|
{
|
|
QAction *action = reinterpret_cast<QAction *>(sender());
|
|
VolControl *vol = action->property("volControl").value<VolControl *>();
|
|
obs_source_t *source = vol->GetSource();
|
|
|
|
OBSDataAutoRelease priv_settings = obs_source_get_private_settings(source);
|
|
obs_data_set_bool(priv_settings, "volume_locked", lock);
|
|
|
|
vol->EnableSlider(!lock);
|
|
}
|
|
|
|
void OBSBasic::VolControlContextMenu()
|
|
{
|
|
VolControl *vol = reinterpret_cast<VolControl *>(sender());
|
|
|
|
/* ------------------- */
|
|
|
|
QAction lockAction(QTStr("LockVolume"), this);
|
|
lockAction.setCheckable(true);
|
|
lockAction.setChecked(SourceVolumeLocked(vol->GetSource()));
|
|
|
|
QAction hideAction(QTStr("Hide"), this);
|
|
QAction unhideAllAction(QTStr("UnhideAll"), this);
|
|
QAction mixerRenameAction(QTStr("Rename"), this);
|
|
|
|
QAction copyFiltersAction(QTStr("Copy.Filters"), this);
|
|
QAction pasteFiltersAction(QTStr("Paste.Filters"), this);
|
|
|
|
QAction filtersAction(QTStr("Filters"), this);
|
|
QAction propertiesAction(QTStr("Properties"), this);
|
|
QAction advPropAction(QTStr("Basic.MainMenu.Edit.AdvAudio"), this);
|
|
|
|
QAction toggleControlLayoutAction(QTStr("VerticalLayout"), this);
|
|
toggleControlLayoutAction.setCheckable(true);
|
|
toggleControlLayoutAction.setChecked(
|
|
config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl"));
|
|
|
|
/* ------------------- */
|
|
|
|
connect(&hideAction, &QAction::triggered, this, &OBSBasic::HideAudioControl, Qt::DirectConnection);
|
|
connect(&unhideAllAction, &QAction::triggered, this, &OBSBasic::UnhideAllAudioControls, Qt::DirectConnection);
|
|
connect(&lockAction, &QAction::toggled, this, &OBSBasic::LockVolumeControl, Qt::DirectConnection);
|
|
connect(&mixerRenameAction, &QAction::triggered, this, &OBSBasic::MixerRenameSource, Qt::DirectConnection);
|
|
|
|
connect(©FiltersAction, &QAction::triggered, this, &OBSBasic::AudioMixerCopyFilters, Qt::DirectConnection);
|
|
connect(&pasteFiltersAction, &QAction::triggered, this, &OBSBasic::AudioMixerPasteFilters,
|
|
Qt::DirectConnection);
|
|
|
|
connect(&filtersAction, &QAction::triggered, this, &OBSBasic::GetAudioSourceFilters, Qt::DirectConnection);
|
|
connect(&propertiesAction, &QAction::triggered, this, &OBSBasic::GetAudioSourceProperties,
|
|
Qt::DirectConnection);
|
|
connect(&advPropAction, &QAction::triggered, this, &OBSBasic::on_actionAdvAudioProperties_triggered,
|
|
Qt::DirectConnection);
|
|
|
|
/* ------------------- */
|
|
|
|
connect(&toggleControlLayoutAction, &QAction::changed, this, &OBSBasic::ToggleVolControlLayout,
|
|
Qt::DirectConnection);
|
|
|
|
/* ------------------- */
|
|
|
|
hideAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
|
|
lockAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
|
|
mixerRenameAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
|
|
|
|
copyFiltersAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
|
|
pasteFiltersAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
|
|
|
|
filtersAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
|
|
propertiesAction.setProperty("volControl", QVariant::fromValue<VolControl *>(vol));
|
|
|
|
/* ------------------- */
|
|
|
|
copyFiltersAction.setEnabled(obs_source_filter_count(vol->GetSource()) > 0);
|
|
pasteFiltersAction.setEnabled(!obs_weak_source_expired(copyFiltersSource));
|
|
|
|
QMenu popup;
|
|
vol->SetContextMenu(&popup);
|
|
popup.addAction(&lockAction);
|
|
popup.addSeparator();
|
|
popup.addAction(&unhideAllAction);
|
|
popup.addAction(&hideAction);
|
|
popup.addAction(&mixerRenameAction);
|
|
popup.addSeparator();
|
|
popup.addAction(©FiltersAction);
|
|
popup.addAction(&pasteFiltersAction);
|
|
popup.addSeparator();
|
|
popup.addAction(&toggleControlLayoutAction);
|
|
popup.addSeparator();
|
|
popup.addAction(&filtersAction);
|
|
popup.addAction(&propertiesAction);
|
|
popup.addAction(&advPropAction);
|
|
|
|
// toggleControlLayoutAction deletes and re-creates the volume controls
|
|
// meaning that "vol" would be pointing to freed memory.
|
|
if (popup.exec(QCursor::pos()) != &toggleControlLayoutAction)
|
|
vol->SetContextMenu(nullptr);
|
|
}
|
|
|
|
void OBSBasic::on_hMixerScrollArea_customContextMenuRequested()
|
|
{
|
|
StackedMixerAreaContextMenuRequested();
|
|
}
|
|
|
|
void OBSBasic::on_vMixerScrollArea_customContextMenuRequested()
|
|
{
|
|
StackedMixerAreaContextMenuRequested();
|
|
}
|
|
|
|
void OBSBasic::StackedMixerAreaContextMenuRequested()
|
|
{
|
|
QAction unhideAllAction(QTStr("UnhideAll"), this);
|
|
|
|
QAction advPropAction(QTStr("Basic.MainMenu.Edit.AdvAudio"), this);
|
|
|
|
QAction toggleControlLayoutAction(QTStr("VerticalLayout"), this);
|
|
toggleControlLayoutAction.setCheckable(true);
|
|
toggleControlLayoutAction.setChecked(
|
|
config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl"));
|
|
|
|
/* ------------------- */
|
|
|
|
connect(&unhideAllAction, &QAction::triggered, this, &OBSBasic::UnhideAllAudioControls, Qt::DirectConnection);
|
|
|
|
connect(&advPropAction, &QAction::triggered, this, &OBSBasic::on_actionAdvAudioProperties_triggered,
|
|
Qt::DirectConnection);
|
|
|
|
/* ------------------- */
|
|
|
|
connect(&toggleControlLayoutAction, &QAction::changed, this, &OBSBasic::ToggleVolControlLayout,
|
|
Qt::DirectConnection);
|
|
|
|
/* ------------------- */
|
|
|
|
QMenu popup;
|
|
popup.addAction(&unhideAllAction);
|
|
popup.addSeparator();
|
|
popup.addAction(&toggleControlLayoutAction);
|
|
popup.addSeparator();
|
|
popup.addAction(&advPropAction);
|
|
popup.exec(QCursor::pos());
|
|
}
|
|
|
|
void OBSBasic::ToggleMixerLayout(bool vertical)
|
|
{
|
|
if (vertical) {
|
|
ui->stackedMixerArea->setMinimumSize(180, 220);
|
|
ui->stackedMixerArea->setCurrentIndex(1);
|
|
} else {
|
|
ui->stackedMixerArea->setMinimumSize(220, 0);
|
|
ui->stackedMixerArea->setCurrentIndex(0);
|
|
}
|
|
}
|
|
|
|
void OBSBasic::ToggleVolControlLayout()
|
|
{
|
|
bool vertical = !config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl");
|
|
config_set_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl", vertical);
|
|
ToggleMixerLayout(vertical);
|
|
|
|
// We need to store it so we can delete current and then add
|
|
// at the right order
|
|
vector<OBSSource> sources;
|
|
for (size_t i = 0; i != volumes.size(); i++)
|
|
sources.emplace_back(volumes[i]->GetSource());
|
|
|
|
ClearVolumeControls();
|
|
|
|
for (const auto &source : sources)
|
|
ActivateAudioSource(source);
|
|
}
|
|
|
|
void OBSBasic::on_actionMixerToolbarAdvAudio_triggered()
|
|
{
|
|
on_actionAdvAudioProperties_triggered();
|
|
}
|
|
|
|
void OBSBasic::on_actionMixerToolbarMenu_triggered()
|
|
{
|
|
QAction unhideAllAction(QTStr("UnhideAll"), this);
|
|
connect(&unhideAllAction, &QAction::triggered, this, &OBSBasic::UnhideAllAudioControls, Qt::DirectConnection);
|
|
|
|
QAction toggleControlLayoutAction(QTStr("VerticalLayout"), this);
|
|
toggleControlLayoutAction.setCheckable(true);
|
|
toggleControlLayoutAction.setChecked(
|
|
config_get_bool(App()->GetUserConfig(), "BasicWindow", "VerticalVolControl"));
|
|
connect(&toggleControlLayoutAction, &QAction::changed, this, &OBSBasic::ToggleVolControlLayout,
|
|
Qt::DirectConnection);
|
|
|
|
QMenu popup;
|
|
popup.addAction(&unhideAllAction);
|
|
popup.addSeparator();
|
|
popup.addAction(&toggleControlLayoutAction);
|
|
popup.exec(QCursor::pos());
|
|
}
|