Skip to content

CMRT 29: Threshold pref, cache-hit grouping fix, reanalyze fingerprint reset, lookup timestamp fix, redundant quality score fixes - #39

Open
Swarnadip-Kar wants to merge 7 commits into
cmrt-canonical-reelectionfrom
cmrt-fixup-threshold-reanalyze-timestamp
Open

CMRT 29: Threshold pref, cache-hit grouping fix, reanalyze fingerprint reset, lookup timestamp fix, redundant quality score fixes#39
Swarnadip-Kar wants to merge 7 commits into
cmrt-canonical-reelectionfrom
cmrt-fixup-threshold-reanalyze-timestamp

Conversation

@Swarnadip-Kar

@Swarnadip-Kar Swarnadip-Kar commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Five small, independent fixes bundled into one PR

A — Match threshold preference

FingerprintMatcher's 90% match cutoff was a compile-time constant. It's now
read from a new Preferences > Fingerprint Analysis spin box
(kCmrtMatchThresholdConfigKey, default 90%, stored as a 0.0-1.0 fraction).
FingerprintMatcher::compare() takes the threshold as a parameter; it has no
UserSettings dependency of its own. CmrtGroupingService re-reads the pref on
every processTrack() call so a change takes effect without restarting Mixxx.

B — Cache hits never triggered grouping

processJob()'s cache-hit branch wrote the MBID to the library table but
skipped CmrtGroupingService::processTrack() entirely -- only fresh network
lookups triggered grouping. Exact-duplicate files whose second copy resolved
via acoustid_cache would get tagged but never grouped. Fixed by calling
processTrack() in both branches.

C — Reanalyze silently skipped fingerprint data

AnalyzerChromaprint::initialize() skips any track with a still-valid
fingerprint_metadata row -- by design, so normal analysis doesn't redo
fingerprinting. But Reanalyze (all three variants) never cleared that row, so
reanalyzing a track whose audio had actually changed left the stale
fingerprint, .chroma file, and CMRT group membership untouched. Extracted the
existing fingerprint-clear loop into clearFingerprintDataForSelection() and
call it from all three Reanalyze slots (and reused it in slotClearFingerprint
and slotClearAllMetadata, removing the prior duplication).

D — acoustid_lookup_at never written

Column has existed in the schema since revision 41; TrackDAO::updateAcoustIdResult()
never included it in the UPDATE. Now stamped with the current Unix timestamp
inside the DAO, matching how TrackFingerprintDao already handles
computed_at/queued_at -- no new parameter, no call-site changes.

E — Add TrackFingerprintDao::getMemberQualityScore()

cmrt_members.quality_score is written once per track, when it joins a group
as a member or canonical (addCmrtMember(), called from createNewGroup(),
assignToExistingGroup(), and replaceCanonical()).

Add getMemberQualityScore(trackId), a structural twin of
updateMemberOffset(): same guard clause, same WHERE track_id=:track_id,
SELECT instead of UPDATE. Returns the same -1.0 "not yet scored" sentinel
CmrtMember::qualityScore and addCmrtMember() already use.

F — replaceCanonical() re-scoring a track it was already given the score for

handleMatchedCandidate() scores the new track once to decide whether it should
replace the existing canonical. When it does, replaceCanonical() was re-reading
TrackQualityInfo and re-running QualityScorer on that same track to fill in its
CmrtMember row -- same input, same output, computed twice for no reason.
replaceCanonical() now takes newCanonicalQualityScore as a parameter and the
caller passes through the value it already has, matching the pattern
assignToExistingGroup() already used.

G — handleMatchedCandidate() re-scoring the canonical on every match into its group

handleMatchedCandidate() re-derived the existing
canonical's score from TrackQualityInfo on every new track that matched into
that group, instead of reusing the score already stored in
cmrt_members.quality_score from when that track became canonical. Added
TrackFingerprintDao::getMemberQualityScore() (DAO commit) and switched
handleMatchedCandidate() to use it, falling back to the old recompute path
only if the canonical somehow has no stored score (call-site commit).

Depends on: cmrt-canonical-reelection (#37)

@coveralls

coveralls commented Jun 26, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 28433425207

Coverage decreased (-4.2%) to 30.301%

Details

  • Coverage decreased (-4.2%) from the base build.
  • Patch coverage: 56 uncovered changes across 7 files (0 of 56 lines covered, 0.0%).
  • 5 coverage regressions across 5 files.

Uncovered Changes

File Changed Covered %
src/library/dao/trackfingerprintdao.cpp 25 0 0.0%
src/musicbrainz/cmrtgroupingservice.cpp 12 0 0.0%
src/widget/wtrackmenu.cpp 7 0 0.0%
src/preferences/dialog/dlgpreffingerprint.cpp 5 0 0.0%
src/musicbrainz/acoustidworker.cpp 3 0 0.0%
src/musicbrainz/fingerprintmatcher.cpp 3 0 0.0%
src/library/dao/trackdao.cpp 1 0 0.0%

Coverage Regressions

5 previously-covered lines in 5 files lost coverage.

File Lines Losing Coverage Coverage
src/library/dao/trackfingerprintdao.cpp 1 0.78%
src/musicbrainz/cmrtgroupingservice.cpp 1 0.0%
src/preferences/dialog/dlgpreffingerprint.cpp 1 0.0%
src/track/track.cpp 1 61.82%
src/widget/wtrackmenu.cpp 1 0.0%

Coverage Stats

Coverage Status
Relevant Lines: 116752
Covered Lines: 35377
Line Coverage: 30.3%
Coverage Strength: 59013.22 hits per line

💛 - Coveralls

@Swarnadip-Kar Swarnadip-Kar changed the title CMRT 29: Threshold pref, cache-hit grouping fix, reanalyze fingerprint reset, lookup timestamp fix CMRT 29: Threshold pref, cache-hit grouping fix, reanalyze fingerprint reset, lookup timestamp fix, redundant quality score fixes Jun 30, 2026
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.

2 participants