Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Effects: store deck & main EQ in effects.xml #11695

Merged
merged 13 commits into from
Jan 12, 2024

Conversation

ronso0
Copy link
Member

@ronso0 ronso0 commented Jun 30, 2023

... to have all effects settings in one place.

The migration from mixxx.cfg is supposed to be done only once, hence the read lines are removed from mixxx.cfg. This means if someone decides to go back to 2.3, the deck EQs and the Main EQ will be reset to default. (IIRC downgrading has more implications and we don't guarantee that's trouble-free anyway)

Since cfg strings are removed during migration the only possibility to loose the main EQ config is if Mixxx crashes before/during shutdown (when the cleaned config is written but not the effects config).

Deck EQ effect uids:

 <EqualizerEffects>
  <Id group="[Channel3]">org.mixxx.effects.biquadfullkilleq Built-In</Id>
  <Id group="[Channel2]">---</Id> <!-- exactly as with QuickEffect chains --- clears the EQ slot -->
  <Id group="[Channel1]"></Id>    <!-- while this (or absent Id element) loads the default EQ -->
  <Id group="[Channel4]">org.mixxx.effects.bessel8lvmixeq Built-In</Id>
 </EqualizerEffects>

Main EQ effect uid + parameters (stored like the standard effect chains)

 <MainEQ>
  <EffectChain>
   <Name></Name> <!-- always empty since we just load an effect into the only slot #1 -->
   <MixMode>DRY/WET</MixMode>
   <SuperParameterValue>0</SuperParameterValue>
   <Effects>
    <Effect>
     <MetaParameterValue>0</MetaParameterValue>
     <Id>org.mixxx.effects.parametriceq</Id>
     <BackendType>Built-In</BackendType>
     <Parameters>
      ...
     </Parameters>
    </Effect>
   </Effects>
  </EffectChain>
 </MainEQ>

Preferences > Mixer is adjusted, though there's now one small step back in terms of UX IMO (compared to #11527, not 2.4):
main EQ changes can not be undone with Cancel -- updateMainEQ() always reads the state from EffectsManager. Though that's what the 'Reset Parameter' button is for.

@github-actions github-actions bot added the ui label Jun 30, 2023
@ronso0 ronso0 changed the base branch from main to 2.4 June 30, 2023 23:29
@ronso0 ronso0 added effects and removed ui labels Jun 30, 2023
@ronso0 ronso0 added this to the 2.4.0 milestone Jun 30, 2023
@ronso0
Copy link
Member Author

ronso0 commented Jun 30, 2023

If there are review ressources for #11527 for merging that into 2.4 it makes absolute sense to have this, too, to complement the effect system changes.

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from 80cb584 to c17af3d Compare July 1, 2023 11:37
@github-actions github-actions bot added the ui label Jul 1, 2023
@ronso0 ronso0 marked this pull request as draft July 2, 2023 15:38
@ronso0
Copy link
Member Author

ronso0 commented Jul 2, 2023

I have no clue why so many loop / cue / engine buffer tests fail with this branch, I didn't touch related files 🤷

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from c17af3d to 22d5dda Compare July 2, 2023 15:50
@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from 22d5dda to 786b9df Compare July 12, 2023 21:21
@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch 2 times, most recently from c0a46b8 to 20b68e6 Compare July 13, 2023 23:56
@ronso0
Copy link
Member Author

ronso0 commented Jul 14, 2023

I have no clue why so many loop / cue / engine buffer tests fail with this branch, I didn't touch related files shrug

I do now: apparently the output effect chain is not created for tests, thus with null check on the output effect chain pointer all tests pass.

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from 20b68e6 to c672756 Compare August 13, 2023 23:44
@ronso0
Copy link
Member Author

ronso0 commented Aug 14, 2023

Transition from mixxx.cfg works flawlessly.
Ready for review (last 4 commits), but still draft until #11527 has been merged.

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from c672756 to ad73a65 Compare October 16, 2023 22:34
@ronso0 ronso0 marked this pull request as ready for review October 16, 2023 22:35
@github-actions github-actions bot added the ui label Oct 16, 2023
@ronso0
Copy link
Member Author

ronso0 commented Oct 16, 2023

#11527 has been merged, rebased onto 2.4

@daschuer
Copy link
Member

Can you remove the unrelated logo update?

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from ad73a65 to 5c12ebd Compare October 17, 2023 08:08
@ronso0
Copy link
Member Author

ronso0 commented Oct 17, 2023

Whoops, cleaned it up locally already but push...
Done.

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from 7b23d47 to 3fffc29 Compare November 15, 2023 15:28
Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some low-level codestyle comments, didn't manage to analyze the highlevel changes yet.

Comment on lines +667 to +668
EffectManifestPointer pDefaultEqEffect = m_pBackendManager->getManifest(
BiquadFullKillEQEffect::getId(), EffectBackendType::BuiltIn);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't the default effect defined somewhere else?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was set in DlgPrefMixer

Comment on lines 669 to 670
VERIFY_OR_DEBUG_ASSERT(!pDefaultEqEffect.isNull()) {
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a branch without any statement, should this just be DEBUG_ASSERT or are you missing an early return?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh.. Yeah, just DEBUG_ASSERT will do

Comment on lines 722 to 723
mainEqPreset = EffectChainPresetPointer(
new EffectChainPreset(mainEqChainElement));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer over the same reason to prefer std::make_shared

Suggested change
mainEqPreset = EffectChainPresetPointer(
new EffectChainPreset(mainEqChainElement));
mainEqPreset = EffectChainPresetPointer::create(mainEqChainElement);

QDomElement mainEqElement = XmlParse::selectElement(root, EffectXml::kMainEq);
QDomNodeList mainEqs = mainEqElement.elementsByTagName(EffectXml::kChain);
QDomNode mainEqChainNode = mainEqs.at(0);
EffectChainPresetPointer mainEqPreset;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

functionally equivalent, but this makes it obvious that the pointer is initialized.

Suggested change
EffectChainPresetPointer mainEqPreset;
EffectChainPresetPointer mainEqPreset = nullptr;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, shouldn't this also probably be pDefaultEqEffect instead of nullptr?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default for Main is none

Comment on lines 177 to 179
for (auto it = m_equalizerEffectChains.begin();
it != m_equalizerEffectChains.end();
it++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotta love Qt's associative containers for the ease-of-use when wanting to iterate over them...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copied the style present in this file, could as well be a QHashIterator.

Copy link
Member

@Swiftb0y Swiftb0y Nov 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No its fine, I just wish we could use structured-bindings instead, but we can't...
https://stackoverflow.com/questions/13087028/can-i-easily-iterate-over-the-values-of-a-map-using-a-range-based-for-loop

I have an Idea on how to improve this though. Nevermind, not much of an improvement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.
I already switched to QHashIterator, even if it's just about making it a bit more compact.

@ronso0
Copy link
Member Author

ronso0 commented Nov 16, 2023

Thanks @Swiftb0y for taking a look. I'll consider your proposals and check each of the commits to make sure everything is still as intended.

@Swiftb0y
Copy link
Member

Thank you. I just picked this PR by chance during the little free time I had. So I don't know when I'll be able to finish this review.

@ronso0
Copy link
Member Author

ronso0 commented Nov 16, 2023

didn't manage to analyze the highlevel changes yet

I simply adopted the routines of the QuickEffect chains for the Equalizers, and those of the standard effect units for the Main effect unit, maybe that helps 🤷‍♂️ Nothing I'm particularly proud of, it just had to be done.

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from 1db748e to c5c8895 Compare November 17, 2023 13:39
@ronso0
Copy link
Member Author

ronso0 commented Dec 3, 2023

ping @Swiftb0y do you see a chance to continue with your review?
I'd love to get this into 2.4, IMO it's the final move to finsh the effects refactoring.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works already good. Thank you.
I have added some comment for code improvement

Comment on lines 189 to 191
QHashIterator<QString, QuickEffectChainPointer> qeIt(m_quickEffectChains);
while (qeIt.hasNext()) {
auto pChainSlot = qeIt.next().value();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QHashIterator<QString, QuickEffectChainPointer> qeIt(m_quickEffectChains);
while (qeIt.hasNext()) {
auto pChainSlot = qeIt.next().value();
for (auto pChainSlot : m_quickEffectChains) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could have sworn I tried that loop earlier...
Thanks!

Comment on lines 177 to 179
QHashIterator<QString, EqualizerEffectChainPointer> eqIt(m_equalizerEffectChains);
while (eqIt.hasNext()) {
auto pEqChainSlot = eqIt.next().value();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QHashIterator<QString, EqualizerEffectChainPointer> eqIt(m_equalizerEffectChains);
while (eqIt.hasNext()) {
auto pEqChainSlot = eqIt.next().value();
for (auto pEqChainSlot : m_equalizerEffectChains) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment on lines 218 to 221
QHashIterator<QString, QuickEffectChainPointer> qeIt(m_quickEffectChains);
while (qeIt.hasNext()) {
deckStrings << qeIt.next().key();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QHashIterator<QString, QuickEffectChainPointer> qeIt(m_quickEffectChains);
while (qeIt.hasNext()) {
deckStrings << qeIt.next().key();
}
deckStrings = m_quickEffectChains.keys();

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

QHashIterator<QString, EqualizerEffectChainPointer> eqIt(m_equalizerEffectChains);
while (eqIt.hasNext()) {
eqIt.next();
const auto pEffectSlot = eqIt.value().data()->getEffectSlot(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const auto pEffectSlot = eqIt.value().data()->getEffectSlot(0);
const auto pEffectSlot = eqIt.value()->getEffectSlot(0);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -241,10 +292,24 @@ void EffectsManager::saveEffectsXml() {
"schemaVersion", QString::number(EffectXml::kXmlSchemaVersion));
doc.appendChild(rootElement);

QHash<QString, EffectManifestPointer> eqEffectManifests;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QHash<QString, EffectManifestPointer> eqEffectManifests;
QHash<QString, EffectManifestPointer> eqEffectManifests;
eqEffectManifests.reserve(m_equalizerEffectChains.size());

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

auto pManifest = pEffectSlot->getManifest();
eqEffectManifests.insert(eqIt.key(), pManifest);
}

QHash<QString, EffectChainPresetPointer> quickEffectChainPresets;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QHash<QString, EffectChainPresetPointer> quickEffectChainPresets;
QHash<QString, EffectChainPresetPointer> quickEffectChainPresets;
quickEffectChainPresets.reserve(m_quickEffectChains.size());

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

QHashIterator<QString, QuickEffectChainPointer> qeIt(m_quickEffectChains);
while (qeIt.hasNext()) {
qeIt.next();
auto pPreset = EffectChainPresetPointer::create(qeIt.value().data());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I stumbled over this because the ownership was not instantly obvious. Maybe a comment helps or:

Suggested change
auto pPreset = EffectChainPresetPointer::create(qeIt.value().data());
auto* pQuickEffectChain = qeIt.value().data();
auto pPreset = EffectChainPresetPointer::create(pQuickEffectChain);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// Read id of last loaded EQ effect
QDomElement eqEffectsElement =
XmlParse::selectElement(root, EffectXml::kEqualizerEffects);
QDomNodeList eqEffectNodeList =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
QDomNodeList eqEffectNodeList =
const QDomNodeList eqEffectNodeList =

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@daschuer
Copy link
Member

Did did still consider this +350 -141 PR a 2.4 candidate? I think yes for sake of completeness

@ronso0
Copy link
Member Author

ronso0 commented Jan 12, 2024

Yes, this should be in 2.4 now that we polished it.

The tricky part is the migration in DlgPrefMixer:

The migration from mixxx.cfg is supposed to be done only once, hence the read lines are removed from mixxx.cfg. This means if someone decides to go back to 2.3, the deck EQs and the Main EQ will be reset to default. (IIRC downgrading has more implications and we don't guarantee that's trouble-free anyway)

Since cfg strings are removed during migration the only possibility to loose the main EQ config is if Mixxx crashes before/during shutdown (when the cleaned config is written but not the effects config).

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from 7134440 to dfb7c1c Compare January 12, 2024 14:02
@daschuer
Copy link
Member

clazy is complaining:

Error: /home/runner/work/mixxx/mixxx/src/effects/effectsmanager.cpp:177:10: error: Missing reference in range-for with non trivial type (QSharedPointer<EqualizerEffectChain>) [-Wclazy-range-loop-reference]
    for (auto pEqChainSlot : std::as_const(m_equalizerEffectChains)) {
         ^
         const  &
1 error generated.

The rest looks good. Thank you. Please confirm when it is ready for merge.

@ronso0 ronso0 force-pushed the effects-store-eq-in-effects.xml branch from dfb7c1c to 2e9aa1d Compare January 12, 2024 18:11
@ronso0
Copy link
Member Author

ronso0 commented Jan 12, 2024

Fixed.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All Green. Thank you. LGTM.

@daschuer daschuer merged commit a4ce3c9 into mixxxdj:2.4 Jan 12, 2024
11 checks passed
@ronso0 ronso0 deleted the effects-store-eq-in-effects.xml branch January 12, 2024 20:00
@ronso0
Copy link
Member Author

ronso0 commented Jan 12, 2024

Glad this got done, thanks for your reviews @Swiftb0y and @daschuer !!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants