Preferences: show 'real' xfader configuration#14124
Conversation
| const ConfigKey kXfaderModeKey = ConfigKey(EngineXfader::kXfaderGroup, | ||
| EngineXfader::kXfaderModeKey); | ||
| const ConfigKey kXfaderCurveKey = ConfigKey(EngineXfader::kXfaderGroup, | ||
| EngineXfader::kXfaderCurveKey); | ||
| const ConfigKey kXfaderCalibrationKey = ConfigKey(EngineXfader::kXfaderGroup, | ||
| EngineXfader::kXfaderCalibrationKey); | ||
| const ConfigKey kXfaderReverseKey = ConfigKey(EngineXfader::kXfaderGroup, | ||
| EngineXfader::kXfaderReverseKey); |
There was a problem hiding this comment.
This is UB and will very likely cause crashes on startup. https://en.cppreference.com/w/cpp/language/siof
There was a problem hiding this comment.
Hmm, so IIUC this is not specific to the diff here but also applies to the state before?
Like EngineXfader::kXfaderConfigKey being defined and initialized in the namespace here?
And making those members of DlgPrefMixer and move them to the initializer list would avoid it, right?
There was a problem hiding this comment.
Or create a few getXYZCfgKey() helpers in dlgprefmixer.h?
There was a problem hiding this comment.
Or simply define them in enginexfader.h like this:
static const QString kXfaderGroup = QStringLiteral("[Mixer Profile]");
?
meeh..
error: in-class initialization of static data member ‘const QString EngineXfader::kXfaderGroup’ of non-literal type
There was a problem hiding this comment.
okay, I use
const ConfigKey xfaderModeKey() {
return ConfigKey(EngineXfader::kXfaderGroup, EngineXfader::kXfaderModeKey);
}
and alike in this namespace.
Should be fine since they're not called before DlgPrefMixer is constructed?
Please check my fixups.
(sorry I force-pushed earlier, some debug stuff slipped in which I had to remove)
There was a problem hiding this comment.
The problem is not that its defined in the namespace (please do and keep that), the problem is that you expose the symbol via the header and then other translation units initialize their static data based on the static data of another translation unit. The solution in both cases is either some "construct on first use" idiom (there are multiple ways to achieve that in C++) or just don't depend on static data from other translation units. So duplicate the QString across both translation units. Its ugly but thats what we get for using QStrings for everything...
6025dbe to
f00cfec
Compare
| static const QString kXfaderGroup; | ||
| static const QString kXfaderModeKey; | ||
| static const QString kXfaderCurveKey; | ||
| static const QString kXfaderCalibrationKey; | ||
| static const QString kXfaderReverseKey; |
There was a problem hiding this comment.
These are the offenders. If you can come up with a solution that removes this static data declarations from the header, you should be good. Again, I recommend you simply duplicate the required QStrings/ConfigKeys across both files. The same technically applies to the other more trivial members (double and const char*) too, it just likely doesn't crash in the unitialized state because the code is able to handle the "unitialized" values. Its still UB though. Best would be to make them static constexpr and initialize right there in the header, but thats not an option for the QStrings.
There was a problem hiding this comment.
Thanks for the explanation, though I'm at a loss: I read about Construct on first Use but explanations and tutorials only refer to obejcts/pointers and classes with a constructor, which is not the case for EngineXfader.
I'll revert the commit and stick with the duplicate QStrings.
f00cfec to
b8d477a
Compare
| m_xFaderMode(MIXXX_XFADER_ADDITIVE), | ||
| m_transform(EngineXfader::kTransformDefault), | ||
| m_cal(0.0), | ||
| m_mode(kXfaderModeKey), | ||
| m_curve(kXfaderCurveKey), | ||
| m_calibration(kXfaderCalibrationKey), | ||
| m_reverse(kXfaderReverseKey), | ||
| m_crossfader("[Master]", "crossfader"), | ||
| m_xFaderTransform(EngineXfader::kTransformDefault), | ||
| m_xFaderCal(0.0), |
There was a problem hiding this comment.
proposal: Create a struct CrossfaderParameter in the class to bundle the calibration, transform, reverse and mode together instead of prefixing all of those with xFader?
There was a problem hiding this comment.
You mean just for holding the parameters in the preferences?
Sure, we can do that. But tbh I'd like to get the mechanics right first before we start optimizing it.
There was a problem hiding this comment.
You mean just for holding the parameters in the preferences?
Yes, and for comparing whether the settings have changed and the display would need to be rerendered. Putting that into a struct and relying on the default operator== is easier/nicer than writing that comparision manually. But sure, we can postpone if you think thats raising complexity.
There was a problem hiding this comment.
Yup, let's postpone it.
Wanna file a request for it?
There was a problem hiding this comment.
nah, its no need to file an issue over code improvement. someone else will clean it up when they look at it again.
0057d9b to
a7bd77b
Compare
|
Sorry what? Why is CI failing on that one now?
|
|
not your fault. ignore clazy for now. #1713 (comment) |
a7bd77b to
72deec0
Compare
|
Alright, all works as desired now! |
|
great. what next steps would you prefer? Remove the debugging statements, address my previous comments, etcc? |
|
Testing! 😄 |
|
then with 👍 remove the debug stuff |
|
all comments addressed, except the struct. Fun fact: if I connect all CO changes to one slot and read all COs there, all (2-3) changes made by the mapping script are already applied, regardless: the slot is called 2-3 times. |
whoops, not quite, widget update after controls change was missing. |
72deec0 to
4c46a32
Compare
|
This has proven to be very handy recently: edit popup is here #14361 |
|
I agree. Do you intend to finish this then? There are still open review comments and the code is also still full of debug printing. |
4c46a32 to
e0dec0d
Compare
|
I think I addressed all comments. I'll squash and remove the debug commit once this has received some testing. |
| m_xFaderMode = radioButtonConstantPower->isChecked() | ||
| ? MIXXX_XFADER_CONSTPWR | ||
| : MIXXX_XFADER_ADDITIVE; | ||
|
|
There was a problem hiding this comment.
does this need to be in the slider slot?
| // wiped on shutdown. | ||
| m_xFaderCal = EngineXfader::getPowerCalibration(m_xFaderCurve); | ||
| m_xFaderMode = m_pConfig->getValue<int>(kXfaderModeKey); | ||
| m_xFaderReverse = m_pConfig->getValue<int>(kXfaderReverseKey) == 1; |
There was a problem hiding this comment.
| m_xFaderReverse = m_pConfig->getValue<int>(kXfaderReverseKey) == 1; | |
| m_xFaderReverse = m_pConfig->getValue<bool>(kXfaderReverseKey); |
or is there a reason otherwise?
|
@Swiftb0y Are all review findings solved? |
|
If added the testing mapping I was using for#14361
|
Swiftb0y
left a comment
There was a problem hiding this comment.
please remove the qWarnings. I will test ASAP.
| SliderXFader->blockSignals(true); | ||
| buttonGroupCrossfaderModes->blockSignals(true); | ||
| checkBoxReverse->blockSignals(true); |
There was a problem hiding this comment.
lets use a QSignalBlocker instead. Otherwise an exception or an inconsiderate future early return could cause the widgets to stay blocked.
Tested. Builds and works well afaict. |
Thanks! I'll squash, remove the trace logging and force-push after LGTM. |
7dc4de0 to
b9b5854
Compare
23f7207 to
8e5bce5
Compare
…ve changed Initially check if the xfader controls have been touched already (at least one is not at default value anymore). If not, load all from config. Else load from controls. Later on, update the widgets and xfader graphic when any control is touched, eg. by controller mappings.
8e5bce5 to
8297186
Compare
|
Sorry for the noise, I messed up the intertwined fixups. |
Swiftb0y
left a comment
There was a problem hiding this comment.
LGTM. Thank you. Waiting for CI.
This makes the Mixer preferences load the xfader configuration
This means touching the usual 3-state switch or curve knob on a controller will update the xfader graphic immedtiately.
¹Since mappings are loaded before DlgPreferences is instantiated this is supposed to detect if mappings have already set the xfader config in their init(), either explicitly or received updates via inputReport request.
Will do another test soon with the S4 Mk3 mapping which requests a status report on startup to sync all controls.
If someone wants to test it without controller, here's a mapping for Vir-MIDI or MIDI Through
https://gist.github.com/ronso0/ae7a6f3fc2b28e43f16bf50bfb84e62e