frontend: Fix volume control state desync

This commit is contained in:
Warchamp7
2026-04-30 10:48:34 -04:00
committed by Ryan Foster
parent 556d5fdbda
commit 6ff9db6f13
4 changed files with 50 additions and 31 deletions
+42 -27
View File
@@ -95,10 +95,11 @@ VolumeControl::VolumeControl(obs_source_t *source, QWidget *parent, bool vertica
volumeMeter = new VolumeMeter(this, source);
bool muted = obs_source_muted(source);
obsMuted = obs_source_muted(source);
bool unassigned = isSourceUnassigned(source);
obsMonitoringType = obs_source_get_monitoring_type(source);
volumeMeter->setMuted(muted || unassigned);
volumeMeter->setMuted(obsMuted || unassigned);
setLayoutVertical(vertical);
setName(sourceName);
@@ -107,10 +108,8 @@ VolumeControl::VolumeControl(obs_source_t *source, QWidget *parent, bool vertica
obsSignals.reserve(9);
obsSignals.emplace_back(obs_source_get_signal_handler(source), "mute", obsVolumeMuted, this);
obsSignals.emplace_back(obs_source_get_signal_handler(source), "audio_mixers", obsMixersOrMonitoringChanged,
this);
obsSignals.emplace_back(obs_source_get_signal_handler(source), "audio_monitoring", obsMixersOrMonitoringChanged,
this);
obsSignals.emplace_back(obs_source_get_signal_handler(source), "audio_mixers", obsMixersChanged, this);
obsSignals.emplace_back(obs_source_get_signal_handler(source), "audio_monitoring", obsMonitoringChanged, this);
obsSignals.emplace_back(obs_source_get_signal_handler(source), "activate", VolumeControl::obsSourceActivated,
this);
obsSignals.emplace_back(obs_source_get_signal_handler(source), "deactivate",
@@ -151,7 +150,7 @@ VolumeControl::VolumeControl(obs_source_t *source, QWidget *parent, bool vertica
// Call volume changed once to init the slider position and label
changeVolume();
updateMixerState();
processMixerState();
}
VolumeControl::~VolumeControl()
@@ -202,17 +201,26 @@ void VolumeControl::obsVolumeChanged(void *data, float)
QMetaObject::invokeMethod(volControl, "changeVolume", Qt::QueuedConnection);
}
void VolumeControl::obsVolumeMuted(void *data, calldata_t *)
void VolumeControl::obsVolumeMuted(void *data, calldata_t *params)
{
VolumeControl *volControl = static_cast<VolumeControl *>(data);
bool muted = calldata_bool(params, "muted");
QMetaObject::invokeMethod(volControl, "updateMixerState", Qt::QueuedConnection);
QMetaObject::invokeMethod(volControl, "onMuteChanged", Qt::QueuedConnection, Q_ARG(bool, muted));
}
void VolumeControl::obsMixersOrMonitoringChanged(void *data, calldata_t *)
void VolumeControl::obsMixersChanged(void *data, calldata_t *)
{
VolumeControl *volControl = static_cast<VolumeControl *>(data);
QMetaObject::invokeMethod(volControl, "updateMixerState", Qt::QueuedConnection);
QMetaObject::invokeMethod(volControl, "processMixerState", Qt::QueuedConnection);
}
void VolumeControl::obsMonitoringChanged(void *data, calldata_t *params)
{
VolumeControl *volControl = static_cast<VolumeControl *>(data);
auto type = static_cast<int>(calldata_int(params, "type"));
QMetaObject::invokeMethod(volControl, "onMonitoringChanged", Qt::QueuedConnection, Q_ARG(int, type));
}
void VolumeControl::obsSourceActivated(void *data, calldata_t *)
@@ -594,6 +602,18 @@ void VolumeControl::setLocked(bool locked)
emit main->mixerStatusChanged(uuid);
}
void VolumeControl::onMuteChanged(bool muted)
{
obsMuted = muted;
processMixerState();
}
void VolumeControl::onMonitoringChanged(int type)
{
obsMonitoringType = static_cast<obs_monitoring_type>(type);
processMixerState();
}
void VolumeControl::updateCategoryLabel()
{
QString labelText = QTStr("Basic.AudioMixer.Category.Active");
@@ -724,14 +744,15 @@ void VolumeControl::setMonitoring(obs_monitoring_type type)
void VolumeControl::sourceActiveChanged(bool active)
{
setUseDisabledColors(!active);
processMixerState();
mixerStatus().set(VolumeControl::MixerStatus::Active, active);
OBSBasic *main = OBSBasic::Get();
emit main->mixerStatusChanged(uuid);
}
void VolumeControl::updateMixerState()
void VolumeControl::processMixerState()
{
OBSSource source = OBSGetStrongRef(weakSource());
if (!source) {
@@ -739,9 +760,7 @@ void VolumeControl::updateMixerState()
return;
}
bool muted = obs_source_muted(source);
bool unassigned = isSourceUnassigned(source);
obs_monitoring_type monitoringType = obs_source_get_monitoring_type(source);
bool isActive = obs_source_active(source) && obs_source_audio_active(source);
@@ -751,9 +770,9 @@ void VolumeControl::updateMixerState()
QSignalBlocker blockMute(muteButton);
QSignalBlocker blockMonitor(monitorButton);
bool showAsMuted = muted || monitoringType == OBS_MONITORING_TYPE_MONITOR_ONLY;
bool showAsMonitored = !muted && monitoringType != OBS_MONITORING_TYPE_NONE;
bool showAsUnassigned = !muted && unassigned;
bool showAsMuted = obsMuted || obsMonitoringType == OBS_MONITORING_TYPE_MONITOR_ONLY;
bool showAsMonitored = obsMonitoringType != OBS_MONITORING_TYPE_NONE;
bool showAsUnassigned = !obsMuted && unassigned;
volumeMeter->setMuted((showAsMuted || showAsUnassigned) && !showAsMonitored);
setUseDisabledColors(showAsMuted || !isActive);
@@ -805,11 +824,10 @@ void VolumeControl::handleMuteButton(bool mute)
// The Mute and Monitor buttons in the volume mixer work as a pseudo quad-state toggle.
// Both buttons must be in their "off" state in order to actually process it as a mute.
// Otherwise, clicking "Mute" with monitoring enabled will toggle the monitoring type.
obs_monitoring_type monitoringType = obs_source_get_monitoring_type(source);
if (mute && monitoringType == OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT) {
if (mute && obsMonitoringType == OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT) {
setMonitoring(OBS_MONITORING_TYPE_MONITOR_ONLY);
} else if (!mute && monitoringType == OBS_MONITORING_TYPE_MONITOR_ONLY) {
} else if (!mute && obsMonitoringType == OBS_MONITORING_TYPE_MONITOR_ONLY) {
setMonitoring(OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT);
} else {
setMuted(mute);
@@ -825,19 +843,16 @@ void VolumeControl::handleMonitorButton(bool enableMonitoring)
// The Mute and Monitor buttons in the volume mixer work as a pseudo quad-state toggle.
// The source is only ever actually "Muted" if Monitoring is set to None.
obs_monitoring_type monitoringType = obs_source_get_monitoring_type(source);
bool muted = obs_source_muted(source);
if (!enableMonitoring) {
setMonitoring(OBS_MONITORING_TYPE_NONE);
if (monitoringType == OBS_MONITORING_TYPE_MONITOR_ONLY) {
if (obsMonitoringType == OBS_MONITORING_TYPE_MONITOR_ONLY) {
setMuted(true);
}
} else if (enableMonitoring && muted) {
} else if (enableMonitoring && obsMuted) {
setMonitoring(OBS_MONITORING_TYPE_MONITOR_ONLY);
setMuted(false);
} else if (enableMonitoring && !muted) {
} else if (enableMonitoring && !obsMuted) {
setMonitoring(OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT);
}
}
+7 -2
View File
@@ -71,6 +71,8 @@ private:
OBSWeakSource weakSource_;
const char *uuid;
std::vector<OBSSignal> obsSignals;
obs_monitoring_type obsMonitoringType;
bool obsMuted;
QBoxLayout *mainLayout;
QLabel *categoryLabel;
@@ -98,7 +100,8 @@ private:
static void obsVolumeChanged(void *param, float db);
static void obsVolumeMuted(void *data, calldata_t *calldata);
static void obsMixersOrMonitoringChanged(void *data, calldata_t *);
static void obsMixersChanged(void *data, calldata_t *);
static void obsMonitoringChanged(void *data, calldata_t *);
static void obsSourceActivated(void *data, calldata_t *params);
static void obsSourceDeactivated(void *data, calldata_t *params);
static void obsSourceDestroy(void *data, calldata_t *params);
@@ -115,7 +118,7 @@ public slots:
void sourceActiveChanged(bool active);
void setUseDisabledColors(bool greyscale);
void setLocked(bool locked);
void updateMixerState();
void processMixerState();
private slots:
void renameSource();
@@ -128,6 +131,8 @@ private slots:
void setName(QString name);
void handleSourceDestroyed() { deleteLater(); }
void onMuteChanged(bool muted);
void onMonitoringChanged(int type);
signals:
void unhideAll();
+1 -1
View File
@@ -364,7 +364,7 @@ VolumeMeter::~VolumeMeter()
void VolumeMeter::obsSourceDestroyed(void *data, calldata_t *)
{
VolumeMeter *self = static_cast<VolumeMeter *>(data);
QMetaObject::invokeMethod(self, "handleSourceDestroyed", Qt::QueuedConnection);
QMetaObject::invokeMethod(self, "onSourceDestroyed", Qt::QueuedConnection);
}
void VolumeMeter::setLevels(const float magnitude[MAX_AUDIO_CHANNELS], const float peak[MAX_AUDIO_CHANNELS],
-1
View File
@@ -371,7 +371,6 @@ void AudioMixer::updateControlVisibility(QString uuid)
bool show = getMixerVisibilityForControl(control);
if (show) {
control->updateMixerState();
control->show();
} else {
control->hide();