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

Pref > Mixer: apply & save settings only in slotApply(), fix bugs, improve UX #11527

Merged
merged 53 commits into from Oct 16, 2023

Conversation

ronso0
Copy link
Member

@ronso0 ronso0 commented May 1, 2023

This is like #4667 but for the entire new Mixer page.

  • update (read from config) only in slotUpdate()
  • apply settings only in slotApply()
  • add checkboxes to apply EQ shelves and Main EQ instantly (default: off) to allow the previous (unexpected) behaviour applied instantly but saved to config in slotApply() so that Cancel (> slotUpdate() resets to saved values

This makes quick fix #11271 obsolete but I'll leave that open for now.
The last commits adds debug output that allows easy tracing. To be removed after review.

There's still a round-trip issue with the EQ shelves' getEqFreq() and getSliderPosition(). This is noticable when resetting to defaults (250, 2500), the resulting values are 246 and 2484 🤷‍♂️ Maybe someone has an idea...

@ronso0
Copy link
Member Author

ronso0 commented May 2, 2023

There's still a round-trip issue with the EQ shelves' getEqFreq() and getSliderPosition(). This is noticable when resetting to defaults (250, 2500), the resulting values are 246 and 2484 man_shrugging Maybe someone has an idea...

Fixed with much larger slider ranges and std::round instead of casting to int.

edit I also set the steps for Left/Right/PageUp/PageDown keys relative to the slider range. This should make it easier to make precise adjustments with the keyboard when the slieris focused.

@ronso0 ronso0 added this to the 2.4.0 milestone May 8, 2023
@ronso0 ronso0 changed the title Pref EQ: apply & save settings only in slotApply(), fix bugs, improve UX Pref > Mixer: apply & save settings only in slotApply(), fix bugs, improve UX Jun 13, 2023
@ronso0 ronso0 force-pushed the pref-mixer-apply branch 4 times, most recently from de7810d to 5ccbfc0 Compare June 28, 2023 11:47
@ronso0 ronso0 marked this pull request as draft June 29, 2023 13:09
@ronso0
Copy link
Member Author

ronso0 commented Jun 29, 2023

Back to draft to avoid early reviews. I did some polishing and rebased. Also, merging #11663 will create some annoying conflicts, so I prefer rebasing when that is merged.

Note that I very much still consider this an relevant bugfix and usability improvement for 2.4!

@ronso0 ronso0 marked this pull request as ready for review June 30, 2023 13:05
@ronso0
Copy link
Member Author

ronso0 commented Jun 30, 2023

Ready to roll this is, woohoo!

I did extensive testing and eliminated all UX hickups, mostly around the infamous 'Single EQ effect for all decks' checkbox, so WYSIWYG. All deck EQ & QuickEffect selectors are now always visible, only deactivated in the 'Single EQ ..' is checked. Consider this a temporary state, we may as well hide those if desired.

All settings are applied only in slotApply(), and read from config/effect engine in update slots.

Both EQ shelves and main EQ sliders now have a 'Apply instantly' checkbox for quick testing.
reverted, still applied instantly but Cancel would revert to the previous state.

Please test!

ronso0 added 14 commits July 1, 2023 00:54
…ip errors

Increase slider range (int, linear) for more precision when calculating the corresponding EQ frequency
(double, exponential) and vice versa.
Previously there was a round-trip rounding issue that would decrease certain high EQ frequencies on each update
until they'd settle at certain values that are appearantly not affected. This was also noticeable when recalling
the defaults (250 Hz, 2500 Hz), which resulted in 2484 Hz and 246 Hz.
src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
@ronso0
Copy link
Member Author

ronso0 commented Sep 15, 2023

The xfader graph looks like this now:
Screenshot_2023-09-15_16-26-30

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.

minor comments, still didn't get through everything, but I feel like thats just the nature of QWidgets...

src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved

QLabel* label = new QLabel(QObject::tr("Deck %1").arg(deckNo), this);

// Create the drop down list for deck EQs
// Create the EQ selector //////////////////////////////////////////////
QComboBox* pEqComboBox = new QComboBox(this);
Copy link
Member

Choose a reason for hiding this comment

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

can you go the extra mile and make this a parented_ptr as well? if the same is done for the members of m_deckQuickEffectSelectors we can remove the destructor entirely.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍
though I run into this now with the lambda in slotNumDecksChanged() here

src/preferences/dialog/dlgprefmixer.cpp: In member function ‘void DlgPrefMixer::slotNumDecksChanged(double)’:
src/preferences/dialog/dlgprefmixer.cpp:230:17: error: use of deleted function ‘parented_ptr<T>::parented_ptr(const parented_ptr<T>&) [with T = QComboBox]’
  230 |                 [this, pQuickEffectComboBox](const QString& name) {
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  231 |                     m_ignoreEqQuickEffectBoxSignals = true;
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  232 |                     pQuickEffectComboBox->setCurrentIndex(pQuickEffectComboBox->findText(name));
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  233 |                     m_ignoreEqQuickEffectBoxSignals = false;
      |                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  234 |                 });
      |                 ~
In file included from src/preferences/dialog/dlgprefmixer.h:9,
                 from src/preferences/dialog/dlgprefmixer.cpp:1:
src/util/parented_ptr.h:35:5: note: declared here
   35 |     parented_ptr(const parented_ptr<T>&) = delete;
      |     ^~~~~~~~~~~~

and I have no clue what this is about 🤷‍♂️

Copy link
Member

@Swiftb0y Swiftb0y Sep 19, 2023

Choose a reason for hiding this comment

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

The lambda is capturing pQuickEffectComboBox by value (which is fine for a raw pointer, but not fine for a smart-ish-pointer such as parented_ptr). Thus the compiler wants to create a copy which it can't because the copy-ctor is deleted (intentional and correct for now).
This is solved most easily by capturing by reference: [this, &pQuickEffectComboBox]

@daschuer do we want to rethink the parented_ptr semantics? Eg enabling moves and and copies, giving the parented_ptr reference semantics essentially. it's not really owning anyways.

src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
src/preferences/dialog/dlgprefmixer.cpp Show resolved Hide resolved
Comment on lines 1012 to 1018
QLabel* pCenterFreqLabel = new QLabel(this);
QString labelText = param->name();
pCenterFreqLabel->setText(labelText);
m_mainEQLabels.append(pCenterFreqLabel);
slidersGridLayout->addWidget(pCenterFreqLabel, 0, i + 1, Qt::AlignCenter);

QSlider* pSlider = new QSlider(this);
Copy link
Member

Choose a reason for hiding this comment

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

these are being leaked right now from what I can tell. seems like a not-insignificant memory leak to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

👍 using parented_ptr for all spontaneously created widgets now, and for the numDecks ControlProxy.
no new anymore in this file.

Copy link
Member

Choose a reason for hiding this comment

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

Thank you 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

but I messed it up when using it for the Main EQ widgets,crashes with qDeleteAll and/or QList in slotMainEqEffectChanged(int) here 5f43d7e#diff-c4e587c957428bd6afd10136eb4dad00d554179984d800b2252947ef2c27e666L984

I'll take a look at this later on.
Or we stick to new and re-add the destructor to delete those widgets.

Copy link
Member

Choose a reason for hiding this comment

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

I'll try to look into it later as well. You can probably just get rid of the qDeleteAll call.

Copy link
Member

Choose a reason for hiding this comment

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

Okay, I double checked, simply removing the qDeleteAlls is the correct choice. The compiler should've warned you if you were to call qDeleteAll on a QList<parented_ptr<T>>, but it apparently didn't. The resulting code still won't be leaky since all objects in the QList will have a parent (as DEBUG_ASSERTed when calling .clear() on the container).

The thing I'm rather confused by is that apparently QList::appending a parented_ptr<T> works, even though it shouldn't because copy and move have been deleted...

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 commented the entire function and I'm sure the crash happens in of the Quick Effect slots. I'll check this soonish

Copy link
Member

Choose a reason for hiding this comment

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

Then its probably from this lambda. It's probably that the lambda (the connection its bound to) outlives the pQuickEffectComboBox reference, which lives shorter because of some m_deckQuickEffectSelectors.clear() call. But I wonder why that bug wasn't there previously.

Copy link
Member Author

@ronso0 ronso0 Sep 19, 2023

Choose a reason for hiding this comment

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

It's not the Main EQ (and therefore: false alarm, qDeleteAll doesn't cause any issues), and there is no m_deckQuickEffectSelectors.clear().

But it's indeed that lambda and that pQuickEffectComboBox reference, though the crash happens during startup and the presetChanged() signal was not emitted.

I worked around it by capturing just the deck group string and the preset name and update the index in a separate slot (just to have a compact lambda body).

Copy link
Member Author

Choose a reason for hiding this comment

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

...and I added a note about the crash and the workaround.

src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
src/preferences/dialog/dlgprefmixer.cpp Outdated Show resolved Hide resolved
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.

LGTM and works. Thank you.

@daschuer daschuer merged commit b695252 into mixxxdj:2.4 Oct 16, 2023
13 checks passed
@ronso0
Copy link
Member Author

ronso0 commented Oct 16, 2023

Finally off my table.. Thanks for your reviews!

@ronso0 ronso0 deleted the pref-mixer-apply branch October 16, 2023 21:04
@ronso0
Copy link
Member Author

ronso0 commented Oct 19, 2023

Whoops, had to fix the 'Bypass EQ procesing' default, it didn't consider empty string (no cfg value).
e39db38

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.

None yet

3 participants