Skip to content

Commit

Permalink
fixup! Pref Mixer: update xfader graphic and widgets when xfader cont…
Browse files Browse the repository at this point in the history
…rols have changed
  • Loading branch information
ronso0 committed Feb 6, 2025
1 parent b8d477a commit 1f1cbc8
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 60 deletions.
127 changes: 73 additions & 54 deletions src/preferences/dialog/dlgprefmixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include <QButtonGroup>
#include <QPainterPath>
#include <QStandardItemModel>
#include <QTimer>

#include "control/controlobject.h"
#include "control/controlproxy.h"
Expand Down Expand Up @@ -42,14 +41,12 @@ const ConfigKey kLowEqFreqKey = ConfigKey(kMixerProfile, kLowEqFrequency);
const ConfigKey kLowEqFreqPreciseKey =
ConfigKey(kMixerProfile, QStringLiteral("LoEQFrequencyPrecise"));

const QString kXfaderCalibration = QStringLiteral("xFaderCalibration");

const ConfigKey kXfaderModeKey = ConfigKey(EngineXfader::kXfaderConfigKey,
QStringLiteral("xFaderMode"));
const ConfigKey kXfaderCurveKey = ConfigKey(EngineXfader::kXfaderConfigKey,
QStringLiteral("xFaderCurve"));
const ConfigKey kXfaderCalibrationKey = ConfigKey(EngineXfader::kXfaderConfigKey,
kXfaderCalibration);
QStringLiteral("xFaderCalibration"));
const ConfigKey kXfaderReverseKey = ConfigKey(EngineXfader::kXfaderConfigKey,
QStringLiteral("xFaderReverse"));

Expand Down Expand Up @@ -80,8 +77,7 @@ DlgPrefMixer::DlgPrefMixer(
m_xfModeCO(make_parented<ControlProxy>(kXfaderModeKey, this)),
m_xfCurveCO(make_parented<ControlProxy>(kXfaderCurveKey, this)),
m_xfReverseCO(make_parented<ControlProxy>(kXfaderReverseKey, this)),
m_xfCalibrationCO(
ConfigKey(EngineXfader::kXfaderConfigKey, kXfaderCalibration)),
m_xfCalibrationCO(make_parented<ControlProxy>(kXfaderCalibrationKey, this)),
m_crossfader(QStringLiteral("[Master]"), QStringLiteral("crossfader")),
m_xFaderReverse(false),
m_COLoFreq(kLowEqFreqKey),
Expand All @@ -104,6 +100,7 @@ DlgPrefMixer::DlgPrefMixer(
#endif
m_eqBypass(false),
m_initializing(true),
m_inSlotApply(false),
m_updatingMainEQ(false),
m_applyingDeckEQs(false),
m_applyingQuickEffects(false) {
Expand All @@ -114,40 +111,24 @@ DlgPrefMixer::DlgPrefMixer(
connect(SliderXFader,
QOverload<int>::of(&QSlider::valueChanged),
this,
&DlgPrefMixer::slotXFaderWidgetsChanged);
connect(SliderXFader, &QSlider::sliderMoved, this, &DlgPrefMixer::slotXFaderWidgetsChanged);
connect(SliderXFader, &QSlider::sliderReleased, this, &DlgPrefMixer::slotXFaderWidgetsChanged);
connect(radioButtonAdditive,
&QRadioButton::clicked,
this,
&DlgPrefMixer::slotXFaderWidgetsChanged);
connect(radioButtonConstantPower,
&QRadioButton::clicked,
&DlgPrefMixer::slotXFaderSliderChanged);
connect(SliderXFader, &QSlider::sliderMoved, this, &DlgPrefMixer::slotXFaderSliderChanged);
connect(SliderXFader, &QSlider::sliderReleased, this, &DlgPrefMixer::slotXFaderSliderChanged);
connect(buttonGroupCrossfaderModes,
&QButtonGroup::buttonClicked,
this,
&DlgPrefMixer::slotXFaderWidgetsChanged);
&DlgPrefMixer::slotXFaderModeToggled);
connect(checkBoxReverse,
// TODO deprecated after Qt 6.9, replace with checkStateChanged(Qt::CheckState)
&QCheckBox::stateChanged,
this,
&DlgPrefMixer::slotXFaderReverseBoxToggled);

m_xfModeCO->connectValueChanged(this, &DlgPrefMixer::slotXFaderControlChanged);
m_xfCurveCO->connectValueChanged(this, &DlgPrefMixer::slotXFaderControlChanged);
m_xfReverseCO->connectValueChanged(this, &DlgPrefMixer::slotXFaderControlChanged);
// When e.g. controller mappings rapidly set multiple xfader controls we may
// get concurrent calls of slotUpdateXFaderFromConfigOrControls().
// In slotXFaderControlChanged() we start a timer to avoid that, only the last
// calls th update method.
connect(&m_xfaderControlUpdateTimer,
&QTimer::timeout,
this,
[this]() {
slotUpdateXFaderFromConfigOrControls();
// store new settings in config
applyXFader();
});
m_xfaderControlUpdateTimer.setSingleShot(true);
m_xfaderControlUpdateTimer.setInterval(200);
m_xfModeCO->connectValueChanged(this, &DlgPrefMixer::slotUpdateXFaderFromConfigOrControls);
m_xfCurveCO->connectValueChanged(this, &DlgPrefMixer::slotUpdateXFaderFromConfigOrControls);
m_xfCalibrationCO->connectValueChanged(
this, &DlgPrefMixer::slotUpdateXFaderFromConfigOrControls);
m_xfReverseCO->connectValueChanged(this, &DlgPrefMixer::slotUpdateXFaderFromConfigOrControls);

// Don't allow the xfader graph getting keyboard focus
graphicsViewXfader->setFocusPolicy(Qt::NoFocus);
Expand Down Expand Up @@ -717,6 +698,8 @@ int DlgPrefMixer::getSliderPosition(double eqFreq, int minValue, int maxValue) {
}

void DlgPrefMixer::slotApply() {
m_inSlotApply = true;

applyXFader();

// EQ & QuickEffect settings ///////////////////////////////////////////////
Expand All @@ -732,22 +715,24 @@ void DlgPrefMixer::slotApply() {
applyQuickEffects();

storeEqShelves();
m_inSlotApply = false;
}

void DlgPrefMixer::applyXFader() {
m_xfModeCO->set(m_xFaderMode);
m_xfCurveCO->set(m_xFaderTransform);
m_xfReverseCO->set(m_xFaderReverse ? 1.0 : 0.0);
m_xfCalibrationCO.set(m_xFaderCal);
m_xfCalibrationCO->set(m_xFaderCal);
// TODO check when/how position needs to be updated
if (m_xFaderReverse != (m_xfReverseCO->get() > 0)) {
double position = m_crossfader.get();
m_crossfader.set(0.0 - position);
}
m_xfReverseCO->set(m_xFaderReverse ? 1.0 : 0.0);

m_pConfig->set(kXfaderModeKey, ConfigValue(m_xFaderMode));
m_pConfig->set(kXfaderCurveKey, ConfigValue(QString::number(m_xFaderTransform)));
m_pConfig->set(kXfaderReverseKey, ConfigValue(m_xFaderReverse ? 1 : 0));
m_pConfig->setValue(kXfaderModeKey, m_xFaderMode);
m_pConfig->setValue(kXfaderCurveKey, m_xFaderTransform);
m_pConfig->setValue(kXfaderReverseKey, m_xFaderReverse);
}

void DlgPrefMixer::storeEqShelves() {
Expand Down Expand Up @@ -827,23 +812,33 @@ void DlgPrefMixer::slotUpdate() {
}

void DlgPrefMixer::slotUpdateXFaderFromConfigOrControls() {
if (m_inSlotApply) {
return;
}

// Read values from config only on first update if the xfader curve controls
// are still at their default values. This should detect if controller mappings
// (or skin attributes) have changed the xfader controls.
// Else and on later calls, always read the current state from controls.
if (m_initializing &&
bool readCfg = m_initializing &&
m_xfCurveCO->get() == m_xfCurveCO->getDefault() &&
m_xfCalibrationCO.get() == m_xfCalibrationCO.getDefault() &&
m_xfCalibrationCO->get() == m_xfCalibrationCO->getDefault() &&
m_xfModeCO->get() == m_xfModeCO->getDefault() &&
m_xfReverseCO->get() == m_xfReverseCO->getDefault()) {
m_xfReverseCO->get() == m_xfReverseCO->getDefault();
if (readCfg) {
m_xFaderTransform = m_pConfig->getValue(kXfaderCurveKey, EngineXfader::kTransformDefault);
m_xFaderMode = m_pConfig->getValueString(kXfaderModeKey).toInt();
m_xFaderReverse = m_pConfig->getValueString(kXfaderReverseKey).toInt() == 1;
// "xFaderCalibration" is not stored in the config and it's not expsoed
// with a slider here. Each time the slider is touched it's calculated
// to get us a smooth curve for ConstPower mode. And hos no effect for
// Additive mode.
// TODO This also means custom values set by controller mappings are
// wiped on shutdown.
m_xFaderCal = EngineXfader::getPowerCalibration(m_xFaderTransform);
m_xFaderMode = m_pConfig->getValue<int>(kXfaderModeKey);
m_xFaderReverse = m_pConfig->getValue<int>(kXfaderReverseKey) == 1;
} else {
// Update xfader from controls
m_xFaderTransform = m_xfCurveCO->get();
m_xFaderMode = static_cast<int>(m_xfModeCO->get());
m_xFaderReverse = static_cast<bool>(m_xfReverseCO->get());
slotXFaderControlChanged();
}

checkBoxReverse->setChecked(m_xFaderReverse);
Expand All @@ -854,16 +849,24 @@ void DlgPrefMixer::slotUpdateXFaderFromConfigOrControls() {
EngineXfader::kTransformMax - EngineXfader::kTransformMin + 1,
SliderXFader->minimum(),
SliderXFader->maximum());
// This triggers slotXFaderWidgetsChanged() which calculates
// m_xFaderCal and calls drawXfaderDisplay()
// This would trigger slotXFaderWidgetsChanged() which calculates
// m_xFaderCal and calls drawXfaderDisplay().
// This would overwrite the m_cal value we read from the calibration CO,
// so block it.
SliderXFader->blockSignals(readCfg);
SliderXFader->setValue(static_cast<int>(std::round(sliderVal)));
SliderXFader->blockSignals(false);

// These also trigger slotXFaderWidgetsChanged()
// Same here
buttonGroupCrossfaderModes->blockSignals(true);
if (m_xFaderMode == MIXXX_XFADER_CONSTPWR) {
radioButtonConstantPower->setChecked(true);
} else {
radioButtonAdditive->setChecked(true);
}
buttonGroupCrossfaderModes->blockSignals(false);

drawXfaderDisplay();
}

void DlgPrefMixer::drawXfaderDisplay() {
Expand Down Expand Up @@ -957,16 +960,11 @@ void DlgPrefMixer::drawXfaderDisplay() {
graphicsViewXfader->repaint();
}

void DlgPrefMixer::slotXFaderControlChanged() {
// calls slotUpdateXFaderFromConfigOrControls() on timeout
m_xfaderControlUpdateTimer.start();
}

void DlgPrefMixer::slotXFaderReverseBoxToggled() {
m_xFaderReverse = checkBoxReverse->isChecked();
}

void DlgPrefMixer::slotXFaderWidgetsChanged() {
void DlgPrefMixer::slotXFaderSliderChanged() {
// m_xFaderTransform is in the range of 1 to 1000 while 50 % slider results
// to ~2, which represents a medium rounded fader curve.
double transform = RescalerUtils::linearToOneByX(
Expand All @@ -977,11 +975,32 @@ void DlgPrefMixer::slotXFaderWidgetsChanged() {
1 + EngineXfader::kTransformMin;
// Round to 4 decimal places to avoid round-trip offsets with default 1.0
m_xFaderTransform = std::round(transform * 10000) / 10000;
// If the curve has been changed in the GUI we fetch the engine value for
// calibration which gives us a smooth curve.
// This wipes any previous value set by controller mappings for example.
m_xFaderCal = EngineXfader::getPowerCalibration(m_xFaderTransform);
m_xFaderMode = radioButtonConstantPower->isChecked()
? MIXXX_XFADER_CONSTPWR
: MIXXX_XFADER_ADDITIVE;

drawXfaderDisplay();
}

void DlgPrefMixer::slotXFaderModeToggled() {
m_xFaderMode = radioButtonConstantPower->isChecked()
? MIXXX_XFADER_CONSTPWR
: MIXXX_XFADER_ADDITIVE;

drawXfaderDisplay();
}

void DlgPrefMixer::slotXFaderControlChanged() {
m_xFaderTransform = m_xfCurveCO->get();
m_xFaderCal = m_xfCalibrationCO->get();
m_xFaderMode = static_cast<int>(m_xfModeCO->get());
m_xFaderReverse = static_cast<bool>(m_xfReverseCO->get());
}

void DlgPrefMixer::slotEqAutoResetToggled(bool checked) {
m_eqAutoReset = checked;
}
Expand Down
9 changes: 4 additions & 5 deletions src/preferences/dialog/dlgprefmixer.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
class QComboBox;
class QWidget;
class EffectsManager;
class QTimer;

class DlgPrefMixer : public DlgPreferencePage, public Ui::DlgPrefMixerDlg {
Q_OBJECT
Expand Down Expand Up @@ -51,8 +50,9 @@ class DlgPrefMixer : public DlgPreferencePage, public Ui::DlgPrefMixerDlg {

void slotUpdateXFaderFromConfigOrControls();
void slotXFaderReverseBoxToggled();
void slotXFaderModeToggled();
void slotXFaderSliderChanged();
void slotXFaderControlChanged();
void slotXFaderWidgetsChanged();

void slotHiEqSliderChanged();
void slotLoEqSliderChanged();
Expand Down Expand Up @@ -93,7 +93,7 @@ class DlgPrefMixer : public DlgPreferencePage, public Ui::DlgPrefMixerDlg {
parented_ptr<ControlProxy> m_xfModeCO;
parented_ptr<ControlProxy> m_xfCurveCO;
parented_ptr<ControlProxy> m_xfReverseCO;
PollingControlProxy m_xfCalibrationCO;
parented_ptr<ControlProxy> m_xfCalibrationCO;
PollingControlProxy m_crossfader;

bool m_xFaderReverse;
Expand Down Expand Up @@ -126,12 +126,11 @@ class DlgPrefMixer : public DlgPreferencePage, public Ui::DlgPrefMixerDlg {
bool m_eqBypass;

bool m_initializing;
bool m_inSlotApply;
bool m_updatingMainEQ;
bool m_applyingDeckEQs;
bool m_applyingQuickEffects;

QList<int> m_eqIndiciesOnUpdate;
QList<int> m_quickEffectIndiciesOnUpdate;

QTimer m_xfaderControlUpdateTimer;
};
2 changes: 1 addition & 1 deletion src/preferences/dialog/dlgprefmixerdlg.ui
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<layout class="QVBoxLayout" name="verticalLayout_2">

<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QGroupBox" name="groupBox_xfader">
<property name="title">
<string>Crossfader Curve</string>
</property>
Expand Down

0 comments on commit 1f1cbc8

Please sign in to comment.