Skip to content

Waveform mark fixes - #15968

Merged
acolombier merged 8 commits into
mixxxdj:2.6from
daschuer:gh15954
Feb 17, 2026
Merged

Waveform mark fixes #15968
acolombier merged 8 commits into
mixxxdj:2.6from
daschuer:gh15954

Conversation

@daschuer

@daschuer daschuer commented Feb 10, 2026

Copy link
Copy Markdown
Member

This fixed [Skin],show_intro_outro_cues for scrolling waveforms #15967
The issue was that init() was used for connecting controls before the waveform marks have been found.

This also removes a double marks updates. The "position" and "end_positions" were directly connected in case of WOverview and it is updated by Cue::updated(). In case of scrolling waveform this connection was broken anyway.

It is also involved in #15954 so the fix here might have an positive effecrt

These were the call stacks showing the redundant updates.:

WaveformMarkSet::update() at waveformmarkset.cpp:124 0x55555662f820	
WOverview::updateCues() at woverview.cpp:508 0x555556733997	
WOverview::onMarkChanged() at woverview.cpp:423 0x555556737262	
WOverview::receiveCuesUpdated() at woverview.cpp:514 0x555556737262	
QtPrivate::QSlotObjectBase::call() at qobjectdefs_impl.h:375 0x7ffff27ac023	
doActivate<false>() at qobject.cpp:3.912 0x7ffff27ac023	
QtPrivate::QSlotObjectBase::call() at qobjectdefs_impl.h:375 0x7ffff27ac023	
doActivate<false>() at qobject.cpp:3.912 0x7ffff27ac023	
QMetaObject::activate() at qobject.cpp:3.972 0x7ffff27a6ac7	
Cue::updated() at moc_cue.cpp:134 0x55555651e82a	
Cue::setStartPosition() at cue.cpp:166 0x55555651e82a	
CueControl::hotcuePositionChanged() at cuecontrol.cpp:1.407 0x555555edfec6	
WaveformMarkSet::update() at waveformmarkset.cpp:124 0x55555662f820	
WaveformRenderMarkBase::updateMarks() at waveformrendermarkbase.cpp:98 0x555556647ab2	
WaveformRenderMarkBase::updateMarksFromCues() at waveformrendermarkbase.cpp:93 0x555556649c38	
QtPrivate::QSlotObjectBase::call() at qobjectdefs_impl.h:375 0x7ffff27ac023	
doActivate<false>() at qobject.cpp:3.912 0x7ffff27ac023	
QtPrivate::QSlotObjectBase::call() at qobjectdefs_impl.h:375 0x7ffff27ac023	
doActivate<false>() at qobject.cpp:3.912 0x7ffff27ac023	
QMetaObject::activate() at qobject.cpp:3.972 0x7ffff27a6ac7	
Cue::updated() at moc_cue.cpp:134 0x55555651e82a	
Cue::setStartPosition() at cue.cpp:166 0x55555651e82a	
CueControl::hotcuePositionChanged() at cuecontrol.cpp:1.407 0x555555edfec6	
WaveformMarkSet::update() at waveformmarkset.cpp:124 0x55555662f820	
WOverview::updateCues() at woverview.cpp:508 0x555556733997	
WOverview::onMarkChanged() at woverview.cpp:423 0x555556736cd2	

@acolombier acolombier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for looking into this.
I haven't yet completely understood how removing the connectSample*Changed impact the waveform rendering. I need to dig deeper to understand how the scene invalidation would work, especially of the context of the rendergraph with the scenegraph (though not important for 2.6, but important to know if we pull this fix forward)

@daschuer

Copy link
Copy Markdown
Member Author

The waveform marks have the "....position" co. If you change position let's say for '[Channel1],hotcue_1_position' form the developers window, you see the three backtracks from above.

This PR remove the redundant last one, which is from the connection to WOverview::onMarkChanged().
Originally there was also the similar connection in WaveformRenderMarkBase(), but this does not connect because the connect is called before the marks are created. This wrong order cause also the missing connection to [Skin],show_intro_outro_cues.

This is all is unrelated to the rendering itself. It is just a question about the way position changes are causing a visual update.

@ywwg

ywwg commented Feb 11, 2026

Copy link
Copy Markdown
Member

Code looks great and uncontroversial, I'll do some quick hand QA to make sure there aren't any immediate issues

@ywwg ywwg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

looks great, good cleanup

@ywwg
ywwg requested a review from acolombier February 11, 2026 15:08
@ywwg

ywwg commented Feb 11, 2026

Copy link
Copy Markdown
Member

Let's just make sure Antoine is ok with the changse as well

@acolombier acolombier left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unfortunately, this appears to be breaking marker in QML entirely

Here is how it use to work before in 2.6

Image

Here is with this PR

Image

@daschuer

Copy link
Copy Markdown
Member Author

Did you merge this PR to main?

@acolombier

Copy link
Copy Markdown
Member

No, compared with 2.6

@daschuer

Copy link
Copy Markdown
Member Author

I cannot confirm. I have tested this branch with option --qml and I see:
image

Can you think of any reason it is broken for you?

@ywwg

ywwg commented Feb 12, 2026

Copy link
Copy Markdown
Member

I am seeing this too, if I open mixxx --qml and load a track with marks, the marks don't show up the first time. they do show up on subsequent track loads (including the same track). I suspect the connections are not being made in the right order

@daschuer

Copy link
Copy Markdown
Member Author

Ah I see, only the very first track is affected.

@github-actions github-actions Bot added the qml label Feb 13, 2026
@daschuer

Copy link
Copy Markdown
Member Author

I have found the issue. It was related to using an half baked track object in case of QML.

I think we have a conceptual issue here. In case of QML rendering is done by the QSGRenderThread concurrently accessing the main thread resources without synchronisation. Not sure if this is actually an issue, but we should consider a clear separation to not suffer random crashes with the QML GUI. Currently the variable "m_updateImagesImmediately" is used to control the differenc between QML Multithreading and Widgets single thread.

@ywwg

ywwg commented Feb 13, 2026

Copy link
Copy Markdown
Member

would it help to have a short meeting to discuss the issue? it sounds like we have uncovered a design flaw that we will need to reconcile to prevent issues like this in the future.

@ywwg

ywwg commented Feb 13, 2026

Copy link
Copy Markdown
Member

we can still merge this cleanup once I confirm the cue issue has been fixed

@ywwg

ywwg commented Feb 13, 2026

Copy link
Copy Markdown
Member

can confirm, marks appear on first load now

@ywwg
ywwg requested a review from acolombier February 13, 2026 16:07
@acolombier

acolombier commented Feb 13, 2026

Copy link
Copy Markdown
Member

Note that QML should manage this synchronisation implicitly AFAIU, the only case we need to manage it explicitelt is for multi threaded rendering engine.

I will have a look at this PR, but remove the change request in case I take too long.

@acolombier
acolombier dismissed their stale review February 13, 2026 16:50

Removing as Owen as confirmed the issue is fixed!

Q_UNUSED(pOldTrack); // only used in DEBUG_ASSERT
DEBUG_ASSERT(getTrackInfo() == pOldTrack);
setCurrentTrack(pNewTrack);
setCurrentTrack({});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you clarify why this is needed? As I understand, setCurrentTrack will still be called in QmlWaveformDisplay::slotTrackLoaded, which was previously discarded as the current track would already be set. Was that causing trouble? Might be good to capture the explanation in a comment so we don't accidentally add this back in the future.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

During loading a new Track all data is populated one by one. We want to remove the old track during that time and pass the new one once it is finished and ready for use in slotTrackLoaded() above.
Maybe this helps also to fix @ywwg race condition.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the explanation.
From my discovery, this won't help with the race condition.

@acolombier

Copy link
Copy Markdown
Member

Just to confirm my message above, I can confirm that Qt guaranties synchronisation between the GUI thread and QSGRenderThread

In this implementation, the render thread is never blocked and the GUI thread will initiate a polishAndSync which will block and wait for the render thread to pick it up and release the block only after the render thread is done syncing.

@ronso0 ronso0 added this to the 2.6.0 milestone Feb 15, 2026
@acolombier

Copy link
Copy Markdown
Member

I can confirm the issue with marker not displaying is fixed. Thank you.

@acolombier
acolombier merged commit 5e9cffa into mixxxdj:2.6 Feb 17, 2026
14 checks passed
@ronso0

ronso0 commented Mar 1, 2026

Copy link
Copy Markdown
Member

Unfortunately this introduces some update regressions in the overview.
Hotcues:

  • set hotcue1 -> no update in overview
  • set hotcue2 -> hotcue1 pops up in overview

Loop cues:

  • updated/shown after seek in the overview (repaint?)

Same delay after clearing hotcues: they're removed only after forced repaint (hover overview)

mixxx-overview-hotcues-delayed-update.webm

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