Versioning: 0.XX = Prototype phase (XX = Prototype number).
From the official launch onwards, on 2.0 changed.
Versions 1.xx remain open for the old version.

0.106 — Central icons, colors from the theme (2026-06-18)
New Features / Improvements
- Uniform icon concept for all themes: All icons are now located centrally in a shared space.
images/Folders are not duplicated in each theme. Geometry and design are maintained centrally once; the Color comes exclusively from the theme values.. - New theme color key
icon_color(in addition to the existingtitle_iconIcon colors can thus be set purely via [method/method - context needed].skin.jsonControl it — entirely without your own image files. This makes creating your own themes significantly easier. - All themes use the same icon set (modern, outline style); previously differing designs (win11, elegant) have been standardized.
- Semantic accent colors remain fixed (highlight yellow, text color red).
Bug fixes (theme polishing)
- Spinbox/Combobox arrows Previously, in light themes (light/win11), buttons were dark on a blue background (difficult to read) — they are now being replaced.
icon_colorand they are white there. - Splitter dividing line (e.g., Planner between Pool and Playlist) was unstyled and appeared almost white — it now uses the theme separator color like the Dock separators.
- „…“ buttons for file dialogs The three dots were not displayed (button padding cut off the text at a fixed narrow width) — custom narrow button variant, dots visible again.
- Notes widget: Zoom icons are displayed again (now using the central icon cache).
Technology
SkinManagerQSS colors the central template SVGs with the theme colors when the theme is loaded (temp cache); QSS references icons via{{icon_path}}, code aboutskin_mgr.icon_dir. Documentation:1_Source/docs/17_theming_icons.mdand `1_So
0.105 — Japanese as a third language (2026-06-18)
New features
- Japanese programming language (日本語): Callers Caddy can now be switched to Japanese. The entire interface (menus, dialogs, tooltips, messages, tutorials, migration and class designer — approximately 1,460 texts) has been translated.
- Selection on first launch (third button „日本語で開始“) and at any time via Settings → Language or the language menu.
- Square dance terminology is deliberately kept in English. (e.g., Pattern, Singing Call, Tip, Loop, BPM, Pitch, Beat Snap) — as is common internationally and also by Japanese callers.
- German and English remain unchanged: The Japanese translation was added purely additively; existing languages were not touched at any point.
Improvements
- Lyrics toolbar wraps when dock is narrow: The buttons at the top of the lyrics window (Auto-Scroll, Auto-Size, Auto-Width, Zoom, Edit) derive their width from their content and wrap to the next line when the widget becomes narrower than the button row can accommodate—instead of being cut off or forcing a minimum width. This wrapping behavior is the same as with the song list and playlist.
Technology
- Log files remain readable regardless of language: Diagnostic/support logs (crash logs, rules.log, perf_log.txt, system report) were and remain independent of the UI language (technical/English). Migration details log From now on, all text will be deliberately written in English (including live display during migration) so that it remains readable for support regardless of the chosen language — the rest of the migration tool interface will remain in the user's language.
0.104 — Mass deletion of large amounts of songs (2026-06-17)
New features
- New tab „Mass Deletion“ in the Potential window (BL-148): Removes a large number of songs from the database in one go — intended for cases where too many songs have been accidentally loaded (e.g., an incorrect folder during import).
- Multi-sortable list with the columns Type (P/S/PS), Added (Date), Title, Label, Genre, ERR and Quality — each column can be sorted by clicking on the header to quickly isolate the wrong batch.
- Convenient multiple selection: Shift+Click selects a contiguous area, Ctrl+Click selects individual lines, Ctrl+A selects everything in the view.
- A single security check for the entire process (no prompt per song), after which it will be deleted without further interruption.
- Historical data: If playback histories exist for the selected songs, you will be asked whether these should also be deleted (default: No — the history can be cleaned up later via "Orphaned History").
- The music files on the hard drive will not be touched.
Technology / Performance
- The rider's song list will be only when opening The data is loaded (no start overhead) and the deletion process runs in the background thread, ensuring that a playing song is never interrupted. With the performance log enabled, metrics (database query, genre assignment, table structure, deletion process) are recorded.
0.103 — Lyrics: View Word (DOCX) and PDF files (2026-06-16)
New features
- View lyrics as a Word document (.docx): Lyrics and cue sheets in Word format can now be directly linked to a song and displayed in the lyrics window – including font sizes, a large centered title, indentation, bold/italic/underlined text, and colored text and background markers (e.g., the typical yellow/colored tag markers). No additional software (no Word) is required.
- View lyrics as PDF: PDF files can also be linked and displayed as lyrics – providing a quick text-reading view of the call text. Note: PDFs are intentionally displayed as plain text only; colored highlights and the exact layout from the PDF are not retained. For full formatting with highlights, use Word, RTF, or HTML.
- Editing Word/PDF lyrics: Word and PDF are purely display formats. For those who wish to edit such a lyric, Callers Caddy offers the option of creating an editable HTML copy (just as with RTF and text files). The original file remains unchanged.
Improvements
- File selection, automatic lyrics import when adding songs, and migration from the old version are now also recognized.
.docx- and.pdf-files.
0.102 — Startup issues resolved: "already running", audio on ARM Windows, theme switching (2026-06-16)
Bug fixes
- „"Callers Caddy is already running" despite closed program – fixed: When installing in protected folders (e.g.
C:\Program Files\…Callers Caddy wouldn't start – it displayed a message that the program was already running, even though it was closed. The only workaround was to run it as administrator. The cause was an internal lock file located in the program folder, where normal users are not allowed to write. This file is now located in a user-specific temporary folder that is always writable – the administrator workaround is no longer necessary. Multiple separate installations will not block each other. - Crash on startup on Windows-on-ARM (e.g., Apple Mac with Parallels) – fixed: If Callers Caddy ran under an ARM-based Windows system (such as Windows 11 in Parallels on a MacBook), it crashed immediately upon startup.
error 0x7eThe problem occurred because the audio system was incorrectly searching for an ARM version of the audio library, which is not included. Callers Caddy now correctly uses the included 64-bit library (via Windows emulation) and also starts in this environment. Additionally, a failed audio system no longer aborts the startup process at this point, but is now properly handled.
Improvements
- Theme/Skin will now change immediately: A change to "Skin / Theme" in the settings is applied immediately – a restart is no longer required.
0.101 — Understandable message instead of crash when the audio system is blocked (2026-06-15)
Bug fixes
- No more raw crashes on startup if the audio component cannot be loaded: On some computers, Callers Caddy crashed immediately upon startup with an incomprehensible Python error window (
PortAudio library not found,error 0x7eThe cause is almost always the computer, not the program — usually a virus scanner that has scanned the audio file.libportaudio64bit.dllThe error occurred when a file is blocked or quarantined, or when a downloaded ZIP file was not "allowed" before extraction (Windows block). Previously, this error occurred so early that no warning window appeared. - Plain text hint with solution: If the audio system fails to load, an easy-to-understand window will now appear, stating the likely cause and explaining step by step how to fix it (virus scanner exception or allowing ZIP before unpacking).
Improvements (diagnosis)
- Crash logging now starts from the very first second: The crash logger is now activated very early on — even before the audio components are loaded. This means that crashes will now also be logged. at program start written to a log file (
logs\crashes), which have so far remained without a trace. - Targeted audio diagnostics: If the audio system fails to load, Callers Caddy automatically writes a diagnostic file. This file checks, among other things, whether the audio file is still present and readable—this helps determine whether the virus scanner has detected it. deleted/in quarantine has postponed or whether it present, but blocked This is (which the Windows error code alone does not reveal). The dialog box provides the file location for further inquiry with support.
- Recognition of special characters in the installation path: The diagnostic tool now also checks whether the program path contains special characters (e.g., umlauts or diacritics in the username).
C:\Users\Tomáš\…Such paths are a known, region-dependent cause for the audio library failing to load under Windows — the diagnostic tool will then point directly to this (solution: install to a path without special characters, e.g.C:\Callers_Caddy).
0.100 — Relative music paths: scattered libraries across multiple folders (2026-06-15)
New features
- Songs can now be located in subfolders of any depth: Previously, Callers Caddy only remembered the filename of each song and searched for it directly in the (up to four) music folders. Users who organized their music into many subfolders ran into limitations with this method. Now, for each song, the relative path within his music path stored (e.g.
Singing Calls/Country/song.mp3). Thus, the four music paths are still sufficient as roots — the subfolder structure below them can be of any size. - Up to four root paths, even on different drives: The four music paths are considered independent roots and can reside on different drives (e.g., C:, D:, E:, F:). A song is stored relative to its music path; during playback, the paths are tried sequentially.
- New tool „Re-index Music Library“ (Paths menu): Recursively searches all configured music paths and automatically moves existing songs whose files are located in subfolders to the correct relative path—thus making previously unfindable songs playable again. It runs in the background without interrupting any playing music. A report is displayed at the end (updated / ambiguous / still missing). Files with the same name in multiple folders are intentionally not guessed but reported for manual assignment.
- Import retains the folder structure: When importing using the "leave in place" option, the selected root folder is entered as the music path and each song is saved relative to it — including subfolders.
Improvements
- Unified, portable path storage: Relative paths are consistently represented with a forward slash everywhere.
/saved (instead of mixed slashes). A one-time database migration automatically cleans up older entries. This makes the database more robust when moving it to other computers or USB drives. - File selection has been standardized across all locations: The file button in the song record, the variant management, and the lyrics selection now determine the relative path uniformly against all music paths.
Migration tool
- Copy or link selectable: As with a normal import, the migration now asks whether the music files should be copied to the destination or left in their current location and only linked. Linking saves storage space and is ideal for large, scattered libraries—the source folders are automatically entered as music paths in the destination configuration.
- Root directory of the music library: The migration queries the root directory and saves each song relative to it — the subfolder structure is preserved.
- Subfolders are fully searched (CC1): The Callers Caddy 1.0 migration now recursively searches the music folders including all subfolders (previously only the top level).
- No more lost files with the same name (SqView): Previously, files with the same name in different folders were lost. Now, both are retained; if multiple files match, the correct one is selected based on its original path.
0.99 — Migration detail log and more robust SqView takeover (2026-06-14)
Bug fixes
- The app restarts reliably after a crash: If Callers Caddy crashed, an internal lock file remained, blocking any subsequent launch with the message "Callers Caddy is already running"—even a computer restart didn't help, as the file remained on the hard drive. The app now checks at startup whether the program instance registered as the lock owner is still running and automatically removes orphaned locks. If an instance is indeed still running, the warning message appears as before.
Migration tool
- Detailed migration log: A log file is now stored in the target folder during every migration (both SqView and Callers Caddy 1.0).
migration_log_ _ .txtIt logs step-by-step what was done for each song—data set imported, jump markers transferred, lyrics found and entered, MP3 found and linked—and remains accessible at any time, even after migration. The file is continuously updated, so even if the process is interrupted, everything up to that point is preserved. - Three notification levels: Each step is considered
DONE,WARNINGorERRORclassified. At the end of the log is a summary, summed by category — at a glance it's clear what was successful and what wasn't. - Searchable dual key (severity + theme): Each log line begins with a language-independent key consisting of severity and topic, e.g.
ERROR MUSIC,DONE LYRIC,WARNING LYRIC,DONE LOOP. This allows individual topics in the log to be found specifically via full-text search, regardless of the language of the description. - Clean live display: During migration, the window only displays the phase progress, all warnings/errors, and the final summary. The complete step-by-step list is saved in the detailed log. A new "Open Detailed Log" button opens the log file directly—even after an error.
- Missing files are detected as errors: If a file exists according to the source system but is not found during import (MP3 or lyrics), this now appears as
ERRORinstead of going unnoticed. The deliberate blind import without a music folder remains a warning. - Lyrics mappings from SqView are preferred: Explicit song-to-lyrics links from SqView (marry table) are now evaluated first before using name-based search. This preserves manually maintained associations.
- Log language follows the selected language: The detailed log is written in German or English — depending on the selected language. The level identifiers
DONE/WARNING/ERRORThey remain language-independent so that the log remains searchable.
SqView import: more complete and correct transfer
- The entire song library will be transferred: Previously, only songs from current playlists and playback history (~1000) were imported. Now, the entire song library from the source is retrieved—including all songs with set loop markers that were no longer in any current playlist. Songs whose audio files are missing are logged as dummy entries with an error message and can be activated later via file import.
- Correct pattern/singing classification: Previously, the classification as a pattern, singing, or both depended solely on the folder name—resulting in entire folders (e.g., "Singing Calls") being incorrectly identified as patterns. The new rule is: If loop markers are present, it's a pattern; if a lyric is present, the singing marker is set; the folder path now only serves as an indicator. Songs that meet both criteria are automatically classified as both pattern and singing. Without any signal, a song is classified as singing.
- Apostrophes in titles are being removed: Song titles containing apostrophes (e.g., "Ain't Misbehaving") were imported from the source using a placeholder character. These are now automatically converted back to a regular apostrophe upon import. Locating the corresponding audio and lyrics files works regardless of the spelling.
- Lyrics attribution from the source preferred: Explicit song-to-lyrics links from the source are used first; only if none exist is the name-based search used.
0.98 — Edit lyrics directly in the app (2026-06-08)
New features
- Lyrics editor in the lyrics dock: Lyrics can now be edited directly in Callers Caddy — no external Word or editor session is needed. A new pencil icon (✎) on the right side of the lyrics toolbar toggles between view and edit modes. Alternatively, double-clicking the lyrics activates edit mode.
- Full rich text editing: In edit mode, a second toolbar appears with all the important formatting options—paragraph format (normal / heading 1–3), font size (6–96 pt), bold, italic, underline, font color, and background color (highlight). This allows you to highlight tag, break, and closer lines as you would want them to appear in live operation.
- HTML as a unified target format: When saving, the file is always saved as HTML. HTML covers all requirements (headings, markup, font sizes, colors, background colors) without loss and can be further edited by any browser or editor.
- Original files remain untouched: RTF and TXT lyrics are NEVER overwritten during editing. Instead, Callers Caddy creates a new one.
.html-file next to the original and drags thelyrics_fileThe song entry will be updated to the new file. The original will remain in the lyrics folder as a backup. A brief information message will appear after the first save. - HTML originals will be overwritten with the backup: The first time you save an HTML lyrics file, a
.bakA backup of the original file was created alongside it — in case the old version is needed later. - Keyboard shortcuts:
Ctrl+Ssaves and exits edit mode,Escrejects the changes (with a confirmation message if anything has been changed). - Safety when changing songs: If you change the song while the lyrics are still being edited without being saved, you will receive a confirmation message asking "Discard changes?" — thus preventing accidental data loss.
- Font size has an immediately noticeable effect: When changing the font size in edit mode using the spinbox field (arrow keys or Enter), the change is displayed live in the text. Without selection, the new size applies to the entire document; with selection, it applies only to the selected area.
- Per-word font sizes are retained in the display: A word deliberately set in a larger font (e.g., a particularly emphasized passage in the lyrics) will remain visibly larger in the lyrics display after saving. Previously, font sizes were standardized when displayed—this is no longer the case.
- Zoom and Auto-Width scale the entire document proportionally: Even if individual words have different font sizes, zoom buttons and auto-width scale the entire document proportionally — the size difference between highlighted and normal areas is maintained at every display size.
- Auto modes are useful in edit mode: Auto-scroll and auto-size are disabled during editing (they would move the cursor and cause the text to jump around when typing). Auto-width and manual zoom remain available—they only change the display, not the saved sizes. All modes are reactivated after saving.
- Icons in all skins: The new toolbar buttons (pen, save, B/I/U, font/background color, discard) are included as SVG icons in each of the four included skins (Default, Elegant, Light, Win11). The icons follow the established skin pattern and adapt to the selected theme.
0.97 — Pitch changes without warbling, custom timer sound and label in the player (2026-06-03)
New features
- Custom sound when using timer cover (BL-137): Instead of the system beep, an MP3 or WAV file can now be played when the pattern/singing time is exceeded—for example, the famous donkey noise of a fellow caller. The sound is mixed into the ongoing audio stream (same output, same device, no second stream) and does not interfere with the music. Configure via Settings → Audio: "Notification Sound (Timer Overlay)" with a file picker and its own volume slider. If no path is set, the existing double beep remains active. Alternatively, the sound can also be assigned individually to each rule (parameter).
soundin thesystem_ping-Action) — this allows patterns and singing with different tones to be distinguished. - New Rule action „Play sound“: In the Rule Editor, the new action appears directly above "System Ping (Beep)" in the "Info & Warnings" group. An audio file is selected via a file picker; the volume is adjustable for each rule. The file is mixed into the current stream—no second channel, no dropout in the main song.
- Record label in player (BL-138): The record label of the currently playing song (e.g., "DGR 014") is now displayed in the top right corner of the player, directly above the status – same font, no extra space. It is hidden if no label is entered.
- Rules is paused in Loop Finder preview: During previewing in the Loop Finder (Audition), all rules are completely deactivated. This prevents Auto-Advance or other song_stopped rules from activating at the end of the audition. After the audition ends, the rules function normally again. This is technically achieved via a central suspend/resume mechanism in the rule engine—reusable for future preview functions.
Improvements for live operation
- Pitch slider now reacts instantly: Previously, anyone who moved the pitch slider during playback only heard the new pitch after several seconds—and during the transition phase, the tempo audibly "wobbled" (approximately 20 % fluctuations over 4 seconds). The audio engine now places the resampling after the WSOLA stretcher (SoundTouch architecture for rates > 1), meaning pitch changes are audible at the speaker within milliseconds, and the tempo is virtually unaffected by the change. Tempo slider (
set_today_tempo,set_tempo) remains unchanged according to the AR-021 pattern. Measurement-wise: Carrier settling time from >3000 ms to 6 ms, RMS deviation from 188 Hz to 0.77 Hz.
Under the hood
- Pitchshifter completely redesigned: Instead of block-wise FFT resampling, a stateful Cubic Hermite interpolator (Catmull ROM, 4-point kernel) with fractional read position and a 3-sample tail across calls is now used. Pitch changes at runtime occur without reset/flush; only the ratio parameter is changed—analogous to SoundTouch's RateTransposer.
- Pipeline sequence: Stretcher now receives original audio (previously: pre-resampled audio in a 5-second buffer, which conflicted with the new tempo parameter during pitch changes). Resampling runs in the audio callback.
stretcher.retrieve, with carry buffer for variable output lengths. - Diagnostic Capture: New engine methods
start_output_capture/stop_output_capturefor diagnostic tools. In normal operation, a single one.is None-Check per callback, no performance impact. Test tools in1_Source/src/tools/pitch_transition_test.pyandpitch_transition_analyze.pyfor AM-modulated sine wave measurements (carrier shows pitch, envelope shows tempo via zero-crossing analysis). - Rule Engine Suspend/Resume: New API
rule_engine.suspend(reason)/rule_engine.resume(reason)and context managerwith rule_engine.suspended("xy"):. Counter-based, nestable — multiple simultaneous suspend calls are only canceled out once all resume() calls have been made. During suspend, all triggers (except the `resume()` method) are disabled.play_timer) in rules.log asSUSPENDEDlogged. - Settings dialog (BL-129): new fields appear automatically. The dialog now enumerates not only existing INI keys, but also all keys from
SETTINGS_META— even if they have never been written. New widget typefilefor file pickers (with configurable audio filter).
0.96 — Manage sequences and unified import (2026-06-01)
New features
- Universal Sequence Import (BL-098): A new menu item, "Sequences → Import Sequences…", replaces the four previous import methods (MDB, JSON, CSDS, free text). Simply select the file; the dialog automatically detects the format (file extension + content sample), displays a live preview of the first three sequences, and reports how many sentences were recognized. The format can be manually overridden if needed. Multi-file selection works for JSON, CSDS, and free text—all files are processed in one go. The old individual entries have been removed from the menu; the underlying routines will be retained as a safety net until August 1, 2026 (BL-135).
- Free text format with three writing styles: The free-text parser now understands (1) one sequence per line with comma-separated calls, (2) one call per line with a blank line as a separator between sequences, (3) like 2 but with
,or;at the end of the line. Additionally, Ceder website headers (... ID= Print) recognized as sequence separators — so you can directly copy and paste and import the choreo database collections. - Bulk values or from the file (type + difficulty): For JSON and CSDS imports that include type and difficulty per sequence, you can choose for each field: either the bulk value set in the dialog for all sequences, or the values from the file (with bulk as a fallback if the file doesn't provide anything for a single sequence).
- Duplicate detection during import: Before writing, the importer performs a 15-field comparison to check whether the sequence already exists in the database or appears twice in the selected files. This is enabled by default; the status line reports "X detected — Y new, Z duplicates". This eliminates the need for subsequent cleanup via the deduplicate dialog.
- Delete sequences (BL-136): Right-click on a sequence in the sequence list → "Delete". You can also select multiple sequences (Ctrl/Shift-click) and delete them all at once—either via the right-click menu or using the new "Delete" button below the table. In the details window (SequenceView), there is also a Delete button in the navigation bar; after deletion, the next sequence from the filtered list automatically moves into position. Each deletion is preceded by a confirmation message, displaying singular or plural text depending on the selection.
Improvements for live operation
- Lyrics automatically adjust after a song change: Previously, users with "Auto Size" or "Auto Width" enabled in the lyrics window would only see the new file in its basic font size when switching songs—the refit simply didn't occur. Both modes are now persistent, mutually exclusive switches and are triggered again with each new song. The refit point is now tied to the actual layout end of the text browser (instead of a fixed 50ms delay), ensuring that even slow-loading HTML or RTF files are scaled correctly.
- Shift/Ctrl-click no longer opens the SequenceView: Previously, users who built a selection in the sequence list using multiple clicks would have the detail view opened with each click—a nuisance when selecting items. Now, only a single click (without modifiers) switches the detail window.
0.95 — Improved diagnosis of audio problems (2026-06-01)
Improvements
- Songs loaded in the performance log: With every song change, a diagnostic line is now written containing the filename, full path, sample rate, channels, and duration. This allows you to immediately trace which file was playing at that moment in case of a problem (dropouts, audio glitches, stream restarts) – previously, this had to be painstakingly reconstructed from the playback history. Completely invisible during live performance; only noticeable during later troubleshooting.
0.94 — Smooth tempo and pitch changes (2026-05-31)
Improvements for live operation
- Tempo changes now sound clean (AR-021). When adjusting the tempo or pitch control, there's no longer a noticeable dropout; the song remains exactly where it was. This is especially relevant for "hot hash" situations where the tempo is gradually increased—each click now results in a seamless transition instead of an audible jump. This applies to all three input methods: song tempo (stored in the database), current tempo (session factor), and pitch.
- There is some reaction latency when changing speed: Until the new tempo becomes audible, the audio continues at the old tempo for up to a second. This is the audio buffer, which has been responsible for ensuring smooth playback since version 0.93—we deliberately leave it alone because any intervention would create precisely the stutters we want to avoid. In practice, this means: leave a slight pause between two tempo clicks; then you'll hear each step clearly.
0.93 — WSOLA stretcher decoupled: Crackling at low latency fixed (2026-05-31)
Performance / Bug fixes
- WSOLA passthrough at Tempo 1.0 (AR-020 Fix A): Until now, the expensive coarse-to-fine cross-correlation was performed in
time_stretcher.pyalso when the tempo control was set to 1.0. With COLA-compliant Hann windows with 50 % overlap and ana_hop == syn_hop, the nominal position is already mathematically exact—the correlation only returns the nominal result anyway. On a Celeron N3450, this unnecessary search cost up to 15 ms of lock-hold per hop and was audible as crackling under WDM-KS with 11 ms hardware latency. Now: with tempo == 1.0, the correlation is skipped completely. - PREPROCESS_OUTPUT_SECONDS 0.25 → 1.0 (AR-020 Fix B): The stretcher output buffer is now maintained at a target value of 1 s instead of 250 ms. This absorbs even maximum hop calculation peaks (e.g., during tempo drag) before they can reach the hardware buffer. Previously: Buffer oscillated between 232 and 325 ms with a periodic dip to 209 ms → 23 ms reserve under WDM-KS. Afterward: Buffer oscillates between 998 and 1091 ms → ~1 s reserve across all host APIs.
- Stretcher with two locks (AR-020 Fix C):
time_stretcher.pyhad a single lock, whichpreprocess()throughout the entire expensive hop calculation. The audio callback waited in theretrieve()on the same lock — even if he only wanted to read output frames. Now a second, narrower one protects it._out_lockexclusively the output buffer;retrieve()It waits at most for the short append of a completed hop, not for the WSOLA calculation itself.
diagnosis
- Stretcher stats line every 5 seconds: New
[Diag] Stretcher Stats-Line directly below each[AudioBuf]-Entry in the performance log. Format:hops=N passthrough=N (X%) correlation=N lock_hold_ms avg=X.XX max=X.XX. This shows at a glance: whether Fix A is working (passthrough rate), how expensive the hop calculation actually is (lock-hold times), and when the user was at the optimal speed (correlation > 0). - Lock-hold measurement: Each hop is in
time_stretcher.preprocess()viatime.monotonic_ns()framed — the statistics provide Avg + Max per 5-s window.
background
- Thorsten's v0.92 trace from May 31, 2026 (perf_24–27) showed: WDM-KS measured perfectly (0 XRuns, hw_default=44100 Hz, distinct=1 in the frame histogram), but audible crackling like a broken cable. AR-020 mechanism (a) and (c) are thus definitively refuted. Code review in the Stretcher:
min10s=209 msA precisely constant callback time corresponds to approximately 2 callback blocks below the 250 ms target → the feeder couldn't deliver individual ticks in time because the only lock was being held by the expensive hop calculation. The three fixes address precisely this bottleneck.
0.92 — Audio diagnostics: Sample rate mismatch and callback frame histogram (2026-05-30)
Logs & Diagnostics
- Hardware sample rate in the stream diag log (AR-020 T1): As well as
[Diag] Stream-Init Attemptas well as[Diag] Stream startednow also showhw_default=XHz— the native sample rate of the audio device. If this doesn't match our requested rate (44100 Hz), the driver performs resampling — on some host API/codec combinations (WDM-KS + Realtek HD is a known issue) the quality is poor and audible as "strange sound"/"speed fluctuations," without any buffer underruns occurring.hw_default ≠ requested SR, a clearer⚠ SR-MISMATCH (we demand NHz)-Marker directly in the experiment line. - Callback frame count histogram (AR-020 T1): For each stream, the first 200 calls to the PortAudio callback are counted and logged once as a compact histogram:
[Diag] Callback frames histogram (first 200): min=1024 max=1024 distinct=1 | top: 1024×200 (100%). If the driver delivers constant block sizes, then...distinct=1— if it fluctuates (suspected WDM-KS), the distribution is immediately visible. Sampling is a cheap method.list.appendPer callback, no lock, no I/O. - Background: Thorsten's test 2026-05-30 (perf_log_22, T-Lap, WDM-KS) showed 4 min
xRuns=0Despite a perfect buffer, audible pitch fluctuations and vinyl-like noise were still present. The immediately following MME test (perf_log_23) sounded clean. The two new diagnostic lines clarify in a single trace whether sample rate mismatch (mechanism a) or frame count fluctuation (mechanism c) is the cause.
0.91 — Fade-out stuttering fixed, new logs folder (2026-05-30)
Performance / Bug fixes
- Fade-Out vectorized (AR-018): The fade-out block in the PortAudio callback (
audio_engine.py) contained a Pythonfor-Loop over 1024 samples per audio block. On weak hardware (Thorsten's Celeron N3450), this caused audible stuttering during fade-out because ~4–10 % of the block time was spent solely on the fade logic, and the GIL was held for the entire loop. Replaced by NumPy array multiplication (1 call instead of 1024 iterations). Speedup factor 100–500x; fade-out now runs smoothly even on weak CPUs.
Logs & Diagnostics
- Diagnostic Center (Help → Diagnostic Center…): A new window with built-in tests provides developers with the necessary data to troubleshoot dropouts—without requiring you to install external tools. Each test clearly explains what it measures and what you should do. Available tests:
- A — System snapshot: Key data: Windows/CPU/RAM/Audio devices/Backends, Callers Caddy version, INI content.
- D — QTimer inventory: Lists all active timers in the program — helps in detecting periodic dropouts.
- F — External Load Sampling (60 s): It checks which other programs are using CPU during playback (antivirus, cloud sync, driver services).
- G — Stall-Sentinel: Shows the status of continuous background monitoring for main thread blockages during playback.
- H — Bundle „Send to Developer“: Packs the latest logs into a ZIP file for emailing.
- B/C/E — Audio tests (in preparation): Silent playback, Hostapi comparison, and fade-out stress are included in v0.92.
- Central logs folder: All logs now end up in
/logs/. This keeps the main directory tidy, and diagnostic data is stored in the correct location. one Position: logs/perf/perf_YYYY-MM-DD_HH-MM-SS.txt— Perflog with timestamp per session (previously fixed name)perf_log.txt, (Each start overwrote the last one). Automatic rotation: only the most recent 20 sessions are retained.logs/crashes/crash_*.log— Crash logs (previously in root)logs/rules.log— Rules Engine Log (previously underrules/, (only the user rules JSONs are located there now)logs/system_report.txt— System report (previously in root)- Automatic migration on first start v0.91: Existing
perf_log.txt,crash_*.log,rules/rules.logandsystem_report.txtThey will be moved to the new structure on a one-off basis.
0.90 — Sequence Editor & Sequence Limit per Dance Program (2026-05-27)
New features
- Sequence Editor (BL-015): A new window, "Sequences → Sequence Editor…", allows you to create and edit sequences. The header displays the type (required field) and difficulty (pre-filled, editable dropdown menus), below which is an input field with… one call per line. Buttons: "+ New", "Save", "Check for Duplicates" (warns if the entry already exists) and "Close". A limit of 15 calls is displayed live and enforced when saving. Known calls are green marked (mapped or exact match); a Double-click Clicking on a non-green line opens a streamlined matching dialog with a searchable call selection (matcher suggestion pre-selected). Exact matches are automatically mapped upon saving so that the level can be calculated. From the sequence view, a ✎ button leads directly to editing the displayed sequence. After saving, the new sequence is guaranteed to be visible (filter reset + selection).
- Sequence limit per dance program (BL-132): In the dance program manager, a "sequence limit" can be set for each program—any call from the teaching order (including program separators like "– Mainstream –"). When switching programs (loading a location or manually in the player), the sequence filter automatically sets this call. Each caller defines the limit once—those switching to MS will only see MS sequences, those switching to A2 will only see A2 sequences. Opt-out is available in Settings → Sequences → "Automatically set filter to dance program".
0.89 — Mouse wheel protection, feedback suppression, call mapping bulk confirmation, quality/ERR via context menu (2026-05-27)
New features
- Context menu Quality/ERR ±1 (BL-127): The song list, playlist, and statistics dock (TOP/FLOP/Never) now display four new entries in the right-click menu: Quality +1/−1 and ERR +1/−1. Each entry shows the old and new values in the form
[5>6]. At the edge of the value range (Quality 0/10, ERR 0/4), the respective action is deactivated. Changes are immediately written to the database; the song data dock synchronizes live when displaying the same song. - Feedback dialog: Session suppression: A new checkbox, "Don't ask again this session," has been added between the notes field and the buttons. When checked, this suppresses the auto-feedback window for the remainder of the session—regardless of whether "Apply" or "Cancel" is clicked. This applies to both manual feedback requests and automatic pop-ups after a song ends. The default INI settings remain unchanged and will be applied again the next time the app is launched.
- Call Mapping: Bulk Confirmation: In the call mapping dialog, multiple lines can now be selected (Ctrl/Shift+Click, Ctrl+A) and written to the database together using the "Confirm Selection" button. The source is displayed on
manualOnce set, the table will be automatically reloaded from the database.
Improvements
- Mouse wheel protection covering all curses: In the Song Data Dock, Player (including volume and position sliders), and in the Settings dialog, SpinBoxes, ComboBoxes, DateEdits, and Sliders ignore mouse wheel events. Accidental scrolling over fields no longer changes values. In the Settings dialog, the protection applies window-wide—fields added in the future are also automatically protected.
- Menu „General Settings“: The settings dialog is now located in the "Settings" menu (previously under "App") and is called "General Settings…". Shortcut
Ctrl+,It remains. The app menu now only contains "Exit".
Bug fixes / diagnostics
- Stall detector remains silent at idle: The Main Thread Stall Detector (AR-F) now only reports stalls while a song is playing. Previously, dragging the title bar or resizing the window caused apparent "stalls" due to Windows' modal move loop, which were unrelated to audio dropouts—these false positives no longer appear in the performance log.
Tidy up
- Dead Translation Key
menu_settingsremoved (bymenu_general_settings(replaced) - Three NoScroll subclasses removed from the Settings dialog (replaced by a window-wide event filter)
0.88 — Audition channel + settings window + anti-stuttering (2026-05-26)
New feature: Audition channel (BL-074)
- Audition button In the player: narrow button to the right of Play, visually positioned above Fade Out
- The song starts from the beginning when the Audition button is pressed. secondary output (exclusive — no second stream)
- No history entry at audition; rules are not broken.
- Stop / Play / End of Song: End audition and automatically restore the primary channel
- Primary / Secondary Output now separate INI keys (
audio/primary_device,audio/secondary_device) with its own volume (audio/secondary_volume, Default 80 %) - Both device dropdown menus appear in the settings dialog (audio section).
- Migration:
audio/output_device→audio/primary_deviceruns automatically once - Bugfix: WASAPI fallback cache in
AudioEngine— If a device reverts to system default at startup, the cache entry is used instead of retrying WASAPI on every channel change (Audition → Primary).
New feature: Settings window (BL-129)
- New window „Settings…“ in the app menu (shortcut)
Ctrl+,) - Genericly reads all relevant INI sections and displays them in tabs.
- Automatic widget selection based on value type: Checkbox, SpinBox, DoubleSpinBox, Path Button, ComboBox, DateEdit, LineEdit
SETTINGS_META-Registration table for known keys with labels, tooltips, value ranges and ComboBox options (skin list, languages)- Tabs: Display, Paths, Audio, Loop, Player, Playlist, Feedback, Sequences, Notes, Lyrics, Debug, Rules (System)
- Buttons: OK / Cancel / Apply
- Warning dialog if keys requiring a restart have been changed (skin, language, debug, audio flags)
- Live Apply where possible: Zoom (sequences/lyrics/notes), minimum volume, loop crossfade, status bar player, music paths
- Excluded:
[General],[Tutorials],[custom-filter], all*_dock-Sections - New
settings_dialog.py— standalone, no bloating of main.py
Anti-stuttering: Host API heuristic + header latency + playlist refresh storm (AR-015 / AR-002)
- L1 — WDM-KS-first heuristic: On first launch (no saved device), the app automatically selects the best available audio backend: WDM-KS > WASAPI Shared > MME — DirectSound is never the default. Background: Thorsten's HostAPI matrix test from May 26, 2026 (10 sessions on a Celeron N3450) shows WDM-KS = 0 stutters, MME = 7–10, DirectSound = 15–25 per 30-second session. Heuristic running in
_setup_audio_device_combo(), immediately saves the selected device to INI and logs[Diag] Auto-Device Heuristics (AR-015 L1). - L2 — Perf header both latencies:
[Sys]-Header now showsAudio output (system default)ANDAudio output (configured)(if different).generate_compact_header(configured_device_index=...)It receives the stored device index from the INI file. This prevents confusion: MME default latency 90 ms vs. actual active WDM KS latency 11 ms (finding 5 from the HostAPI matrix). - G — Playlist Refresh Storm fixed (AR-002): New method
PlaylistWidget.add_entries_bulk(entries)It internally appends all entries and callsrefresh_display()+_notify_changed()Exactly once — no matter how many songs. Auto-fill now uses bulk add instead of N×.add_entry(). Previously: 24×refresh_display+ 24×_refresh_playlist_mirror; afterwards: 1x each.
0.87 — Dock Open Instrumentation + Stall Detector 100 ms + Audio Device Routing Diagnostics (2026-05-25)
This version expands the diagnostic tools from version 0.86 by adding two targeted measurement points for audio dropout causes that we observed in Thorsten's logs (desktop + laptop) but couldn't pinpoint. Background information and suspected cases are documented in [documentation missing in original text]. 1_Source/docs/anti_ruckler_backlog.md (Tasks J, N).
Performance log: Dock toggle steps individually stamped
_toggle_dock(...)(central handler for all Dock buttons in the status bar, including Planner, Lyrics, SongData) now stamps each Qt step individually:setFloating(True),show(),move(),raise_(),setFocus(),hide(). Plus oneTOTAL-Line.- The label contains the dock name so that Planner/Lyrics/etc. are distinguishable.
_on_manager_button_clicked(Planner button) also receives additional stamps to mark thesetCurrentIndex(sort)-Trigger (triggers_apply_filterout of).- This observation focuses on Thorsten's laptop (Celeron N3450): an underflow burst immediately after clicking Planner, with a main thread stall of approximately 950 ms — so far without a visible cause in the log. The well-known Qt trap.
setFloating(True) ~90 ms(see CLAUDE.md) scales well on weak CPUs.
Stall detector threshold lowered: 150 ms → 100 ms
- In Thorsten's logs from the morning, underflows occurred in some cases without the stall detector (from 0.86) reporting anything — presumably because blocks were between 100–150 ms below the old cutoff.
- The new threshold of 100 ms is certainly above the normal scheduling jitter (~80–100 ms), but reliably catches the blocks that prevent the Python PortAudio callback from grabbing the GIL.
Diagnostic consequence for AR-014
- The underflows in Thorsten's latest logs (Desktop perf_log_8, Laptop perf_log_14) show all
BUFFER FILLED(255–325 ms buffer). The feeder isn't the problem—the Python callback is, because it needs the GIL on every call. This version makes the evidence more precise by also making smaller stalls and dock step costs measurable.
Audio Device Routing — Attempt / Fallback / Final Result (Update in the Evening)
Background: an afternoon test showed [Diag] Stream started still hostapi=MME, although according to the video, Thorsten had undoubtedly selected a WASAPI entry in the combo. Suspected: silent fallback in _ensure_stream, because the try/except-chain has so far swallowed the cause there.
Three new [Diag]-Lines surrounding the stream start make the path from combo to active stream traceable:
- Attempt (UI-side) —
_on_audio_device_changedlogs every combo change:[Diag] Audio device change requested: idx=…, combo_label='…'' - Attempt (engine-side) —
_ensure_streamlogs before the first stream opens:[Diag] Stream-Init attempt: device=…, name='…', hostapi=…, exclusive=… - Fallback paths — if the Open operation fails with the user device:
[Diag] Stream-Init failed with device=… (…) — Fallback 1 to the same device without extra_settings[Diag] Stream-Init Fallback 1 also failed (…) — Fallback 2 to system default (…). User selection device=… is IGNORED!
The existing [Diag] Stream started-Event continues to show the actually Active device + host API (i.e., after fallback). Purely diagnostic; no change to audio behavior.
0.86 — Anti-jerk diagnosis + MMCSS priority for audio feeder (2026-05-24)
Expands the troubleshooting capabilities for audio dropouts (TIC-0025 complex) with two new diagnostic tools in the perf_log.txt and an initial attempt at a solution at the system level. Background and suspected cases documented in 1_Source/docs/anti_ruckler_backlog.md, User manual in 1_Source/docs/diagnose_ruckler_user.md.
Audio feeder is running with MMCSS "Pro Audio" priority (attempted solution)
- The dedicated
Audio feederThe -Thread (since version 0.80) previously ran with normal Windows thread priority. PortAudio already assigns MMCSS to its own callback thread, but our Python feeder didn't—this allowed the Windows scheduler to push it behind UI threads, even if the GIL was free. - New: The very first action in the feeder run loop will be
AvSetMmThreadCharacteristicsW("Pro Audio")It is called via ctypes. This places the feeder above all UI applications in the scheduler. - Disableable via INI:
audio/mmcss_priority=falsein case problems occur.
Performance log: Wall clock timestamps on all lines
- Each line in
perf_log.txt(except[Sys]-Header) now gets aHH:MM:SS.mmmA prefix is added. This allows observations of jerking or stuttering to be precisely correlated with log events, either with the time or a video recording.
Performance log: System header at startup
- The first time the Perf log is opened, a
[Sys]-Block written with: Callers-Caddy-Version, Python/PySide6/Qt-Versions, OS, CPU, RAM, PortAudio-Version, Default-Audio-Output, active host API (MME/DirectSound/WASAPI/WDM-KS), available hostapis, audio engine constants (FEED_AHEAD,PREPROCESS,BLOCKMakes logs from different sessions and users comparable. - Cost: ~90 ms at startup (only if
debug/performance_logging=true); without subprocess calls.
Perf-Log: PortAudio underflow events with buffer snapshot
- Previously, underflows were only recorded as a counter (
xRuns=N). Now each underflow is writing its own.[Diag]-Line with timestamp, buffer level and diagnostic information: BUFFER EMPTY → Feeder/GIL suspicion(Our code could not refill)BUFFER FULL → Suspected driver/host API/DPC issue(PortAudio reports an error despite full data — e.g., WASAPI shared glitch or driver DPC stall)- Events are pushed into a deque in the callback (no I/O in the callback itself) and written to the log by the feeder loop.
- Additionally, at the start of the stream
[Diag] Stream started: ' ' hostapi=<...> sr=... blocksize=... latency=.... - Disableable via INI:
audio/log_underflows=false.
New user documentation
1_Source/docs/diagnose_ruckler_user.mdThis guide describes in three steps how affected users can collect logs (activate Perflog, LatencyMon, optionally video sync). It can be forwarded directly to users reporting stuttering issues.
WASAPI Exclusive Mode as Opt-in (AR-008)
- The research A documented glitch in Windows WASAPI Shared Mode (PortAudio Issue #303) was identified as the most likely cause of seemingly random mini-dropouts. This version allows users to use WASAPI in Exclusive Mode, completely bypassing the bug.
- The audio device selector now displays the Host API per device displayed (
""Speakers (WASAPI)"",""UR22 mkII (ASIO)""This allows the user to see directly which backend Windows uses. - New „Exclusive“ checkbox“ In the status bar next to the device combo. Enables WASAPI Exclusive Mode for the selected device; automatically falls back to Shared mode in case of an init error. Only works for WASAPI devices — other host APIs (MME, DirectSound, ASIO) ignore the flag.
- Tooltip warns: Exclusive Mode blocks other audio programs system-wide (no YouTube/Spotify alongside it).
- INI key:
audio/wasapi_exclusive=true/false(Default off). - For those who own an ASIO interface (e.g., Steinberg UR22 mkII): simply select the ASIO device from the list — PortAudio routes automatically via the ASIO host API, without any additional switches.
Main thread stall detector in the performance log
- The existing 50 ms
_update_allThe timer now measures the gap between its ticks. If the gap is greater than 150 ms, the UI thread was blocked—for example, by a heavy Python operation that occupied the GIL. - Logged in as
[Diag] Main thread blocked: NNNms (expected 50ms) (last [Perf] event before XXXms: ...). Directly correlated with underflow events via the wall clock stamp: was shortly before a[Diag] PortAudio output_underflowIf a main-thread stall occurs, GIL-Contention is the likely cause. - The attached "last [Perf] event" note names the last instrumented operation that ran in front of the stable — immediately identifies the suspect without having to scroll through the log.
- Pure logging, no change in behavior.
Improved AudioBuf classification
- The first live test showed that the previous system
⚠ CRITICALfrequently false alarms:min10s=0This occurs with every tempo/pitch change because the stretcher is briefly flushed — but the 5 s pre-roll catches this, so PortAudio does not report an underflow and nothing is audible. - New label levels in the
[AudioBuf]-Line: ⚠ XRUN (+N real dropouts)— the PortAudio xRun counter has increased since the last sample; this is an audible dropout at the driver level.△ Buffer dip (probably a stretcher flush, harmless)—min10sIt briefly dropped to 0, but no new xRun (typical during tempo/pitch changes)△ low—min10s50–120 ms (early warning)- When reviewing a log, a search for
⚠ XRUNand[Diag] output_underflow— the rest is noise.
Notice
This version contains only diagnostic improvements plus the MMCSS fix attempt. The other levers identified during research (WASAPI Exclusive/ASIO choice, stall detector, Numba/CFFI) are in the anti-stuttering backlog and will be prioritized based on the results of the first test round.
0.85 — Filter header + Critical bug fix Loop data loss (2026-05-23)
Bugfix: Loop values were being overwritten when clicking on the song list.
- symptom33 songs had identical
loop_in=0.34Values with differentloop_out(clustered by source song). Original loops were lost. - Caused:
_save_current_songran in_on_file_loadedwith the new_current_song, but the engine loop snapshot of the old Songs. When clicking through the song list, each new song inherits the loop values of the previous one. - Fix (Variant C+ — Direct persistence + Dirty flags):
- Each loop change (Set Loop In/Out, Beat Snap, Clear Loop) writes immediately into the DB — no more group save when changing songs.
- Tempo and pitch use a dirty flag and are persisted when leaving the field (Enter/focus change) or before the next song change. During a slider drag no DB-Write — protects the audio buffer.
- Snapshot mechanism (
_snapshot_loop_values,_saved_loop_in/out,on_before_load) completely removed. - New Helper Method
_flush_player_values()is called up at all song change points (song list, playlist, preview, drag & drop, close event). - DB cleanup33 affected songs on
loop_in=0, loop_out=0reset (loops need to be set up again). - Backups: DB under
2_Test/callers_caddy.db.backup_20260522_225318, Source under1_Source/src/_fallback/*.bak_loop_fix_20260522_231059. - Test plan:
5_Tickets/loop_data_loss_testplan.md - Follow-up ticket: TIC-0027 — Audio buffer underrun during tempo drag (standalone performance theme)
Feature: SongFilterBar — unified filter/sort area (BL-101 + BL-121)
- New common component
SongFilterBarreplaces the previous separate filter areas in Song List and Planner. - Songlist has now achieved full parity with the Planner:
- Type filter: RadioButtons All / Patter / Singing
- Genre filterComboBox with all available genres
- SortingAlphabetical / Quality / Last played / Recommendation (new)
- Custom filter: Button to load saved playlists as presets (BL-097)
- Search fieldLive filter via title, label, filename
- Planner remains unchanged — now also uses
SongFilterBarintern. - No more duplicate code: Filter logic, custom filter dialog, persistence and sorting all live in one place.
Feature: Random tiebreaker in case of a tie (BL-113)
- At Sorted by quality and Sorted by recommendation Songs with identical scores will no longer always be displayed in DB order, but will be randomly ordered within the tie group.
- New „"Random" checkbox next to the sort dropdown for turning it on/off — automatically greyed out for Alphabetical and Last Played.
- The order is stable within a session — no remixing with every keystroke or filter change.
- Alphabetical sorting and last-played sorting remain unchanged and deterministic.
- It works everywhere
SongFilterBarThe following are used: Song list, Planner pool, Auto-Fill.
Feature: Status bar — Thumbnail playback progress (BL-128)
- New widget
_StatusBarPlayerBarThe status bar permanently displays the playback progress: - Progress fill (semi-transparent, accent color from skin)
- Loop-in / loop-out as vertical lines (as in the main player slider)
- 7 equally wide section stripes (Singing-Call colours O/1/2/M/3/4/C) at the bottom edge
- The widget is skin-conscious — Colors change automatically when switching skins.
- Can be switched on/off via INI:
display/statusbar_player = true(Standard) /false - No performance overhead: Updates only occur when values actually change (
update_state(with dirty check).
Refactoring: Development guideline documented
- New Refactoring completeness rule in
1_Source/docs/12_erfahrungen.md: - Two-phase approach: first setup (creating something new), then, after testing, dismantling (removing the old one).
- Mandatory checklist: Setup list + teardown list before coding
CLAUDE.mdNow refers to all subdocuments via a table (when to read which one)
0.84 — Evening Planner transfer dialog + audio device selector + crash fix (2026-05-22)
Feature: Evening Planner — Transfer dialog with confirmation (BL-124)
- „"Go to playlist" and "Go to notes"“ They now always show a confirmation dialog — even if no songs are confirmed.
- The dialog provides information about the number of confirmed and unconfirmed songs and offers three options: All transferred / Confirmed only / Cancel.
- If all songs have already been confirmed, the selection option is no longer available and the transfer proceeds directly.
- After the transfer, a message appears indicating the number of songs transferred.
- Bugfix: If nothing was confirmed, clicking the transfer buttons simply did nothing—no dialog, no message. Fixed.
Bugfix: Evening Planner — incorrect order when exporting notes
- Songs appeared in reverse order after being exported to the notes.
- Cause: the Notes widget always adds new entries to the top (
index=0), which meant that when inserting the song sequentially, the last song ended up at the top. - Fix: The exported list is now reversed before pasting, so the order from the Evening Planner is preserved.
Feature: P/S marking in notes shortcodes
- When exporting to notes, songs are now marked as P (Pattern) or S (Singing Call) marked:
[load_song title="..." mode="P"]. - Prevents confusion with songs that are registered for both types.
- Backwards compatible: Songs without a type assignment will continue to use the old format.
[load_song "..."].
Feature: Select audio output device (BL-126)
- New ComboBox permanently displayed in the right status bar for selecting the audio output device.
- Displays all available output devices of the system (filtered to output-capable devices).
- First entry: System Standard (previous behavior).
- Switching devices also works during playback — the stream is immediately switched to the new device.
- The selection is saved in the INI file and automatically restored on the next startup.
- Fallback: If the saved device is unavailable (e.g., USB sound card not connected), the app automatically starts with the system default.
Bugfix: Crash after audio device disconnect (TIC-0026)
- Crash „Cannot operate on a closed database“ This occurred when an audio device was disconnected: The feeder stopped playback, and an already queued timer callback then attempted to access the already closed database.
- Fix:
timer.stop()will now be the very first action incloseEventexecuted. Additionalis_open()-Guards in_do_auto_advanceand_get_current_target_durationprevent access to a closed database. - Audio recovery: If a device is disconnected during playback (USB, HDMI), playback will automatically resume on the next available device (usually the internal speaker) after a brief interruption. The stream is checked for activity every 2 seconds and restarted if necessary.
0.83 — Feedback notes + location tips + AI metadata for Quality/ERR (2026-05-21)
Feature: Note field in the feedback dialog
- New text field „Notes for the future“ in the feedback dialog (after the Quality and ERR buttons), 3 lines.
- If a location is selected: The entry is created directly as a new note when OK is given. to the end of the notes list attached to the current location — ideal as a memory aid for the next evening.
- If no location is selected: Field deactivated with explanatory text in the placeholder ("First select a location").
- Storage directly in the DB (robust against lazy-init of the Notes dock) + subsequent refresh of the NotesWidget.
Feature: Planned number of tips per location
- New settings field In the location settings dialog (under the tempo spinner): Number of planned tips per evening.
- SpinBox 0–40, 0 = no default (displayed as „– (no default)“).
- When changing locations, the value is automatically applied to two places:
- Autofill dialog (Magic wand in the planner):
spin_tipsstarts with the location value instead of the hard-wired default value of 8. - Evening Planner:
_spin_tipsThe location value is set. - DB migration: new column
planned_tips INTEGERin thelocations-Tabel.
Feature: AI metadata export for Quality and ERR (Potential Widget)
- Quality and ERR These are now selectable fields in the "Export Gaps" dialog.
- „Missing“ means:
quality = 0or.err = 0. - AI prompt Quality and ERR explained with full instructions:
- Quality: Caller's self-assessment (AI cannot judge this) → AI always sets 6, caller corrects themselves.
- ERR: Dancer Response (1 = peak to 4 = calming down) → AI estimates based on familiarity, sing-along factor, and emotional impact. This field is mandatory and should never be skipped.
- import processed quality and ERR as integer fields (
update_song_simple_fieldA value of 0 is skipped during import. - Buttons in the FlowWidgetAll buttons are now side by side and automatically wrap to the next line if there isn't enough space — reusable
_FlowWidget-Class for the entire app.
0.82 — Feedback dialog + music and lyric variations + pattern→pattern (2026-05-20)
Feature: Song feedback after playback (BL-119 + BL-035)
- New modal feedback dialog appears after every song ending (natural ending, fadeout, manual stop), if
feedback/enabled = trueis set in the INI (default: off). - Quality buttons 0–10 with a color gradient from white (0 = not rated) through light green to forest green (10 = excellent). The currently set value is highlighted.
- ERR buttons 0/4/3/2/1 The dancer's reaction is listed in order from weakest to strongest, colored with the Evening Planner colors (gray/blue/green/amber/red). Tooltips explain the meaning when hovering.
- Adaptive text color: Dark text on light buttons, white text on dark buttons — automatically via luminance formula.
- Pressing Esc or "Cancel" closes the program without saving. Only changed fields are written to the database.
- Auto-Advanced is waiting automatically until the dialog is closed (modal dialog blocks the main thread).
- Manual call at any time via the new "Feedback" button in the song data dock (next to "Advanced Data" and "Delete Song").
Feature: Multiple music and lyric files per song (BL-XXX)
- Variant management in the dialog „Extended Song Data“ (new tab „Variants“).
- Over + Music version or. + Lyric variant Any number of alternative files can be entered per song — with a descriptive name (e.g. „Live Version“) and a file selection dialog.
- Variants are available in the
song_properties-table saved (music_2_name,music_2_file, etc.), no schema change is necessary. - Delete a variant using the ✕ button; remaining variants will be automatically renumbered.
- If variants exist, they will appear in the Song Data Dock directly below the file name or lyrics line Selection buttons"Default" / "Standard" is always the first and pre-selected option.
- Clicking on a music variant loads it immediately in the player (PathManager searches all configured music slots, just like with main files).
- Clicking on a lyric variant immediately displays it in the lyrics widget.
- The active lyric variant is retained when editing song fields (autosave) and switching skins. Switching to a different song always resets it to "Default".
- File dialogs start by default in the respective Music or Lyrics folder; portable filenames are stored relatively.
- Bugfix: Variant buttons reverted to "default" after each player response. The active variant is now remembered in the widget and correctly restored during button rebuild.
Renaming: „Pattern“ → „Patter“
- On the recommendation of an American caller: The entire UI now uses the correct term "Patter" instead of "Pattern" — in all German and English texts (Checkbox, RadioButton, Import dialog, Evening Planner, Statistics, Column headings, Tooltips, Tutorial texts).
- Internal code variables and DB fields (
is_patternetc.) remain unchanged.
0.81 — Bugfix: Slider display during tempo changes and loop audition (2026-05-18)
Bug fix: Time display inconsistent when speed changes
label_time_currentshowed original seconds,label_time_totalHowever, real-time duration uses different units. For example, with a 3-minute song at 1.5x tempo, after 1 minute: the labels showed "1:30 / 2:00" (implying 75 %), the slider was correctly set to 50 %. Now the running time also shows real-time:pos × major / original major. Labels and sliders are now in sync again.
Bugfix: Slider freezes during loop audition
- Slider remained during the 5-second preview phase (before the first loop jump) on the
loop_in-position. Cause:_estimate_playback_pos()clamped the position onmax(loop_in, ...), as soon as the feed pointer is already behind the feed-ahead wraploop_inwas — even though the audio callback was still operating in the pre-loop segment. Fix: Atpos < loop_inwill now_playback_sampleused as an approximation (exact at speed 1.0; slight deviation at other speeds).
0.80 — Audio Architecture: Dedicated Feeder Thread (2026-05-15)
Audio dropouts finally fixed (TIC-0025)
- Dedicated audio feeder thread in the
AudioEngine. Previously, the WSOLA stretcher was populated from the UI main thread (every 50 ms via QTimer).PlayerWidget.update_displayThis meant that the audio feeding was completely dependent on the UI thread: any GIL blockage > 500 ms (loop finder completion, DB operations, restoreState) resulted in audible dropouts. There is now a separate daemon thread running (Audio feeder), which refills the stretcher every 20 ms independently of the main thread. FEED_AHEAD_SECONDS: 0.5 s → 5.0 s. The stretcher now pre-buffers 5 seconds of audio. Even if the main thread blocks for several seconds, the audio callback has enough data to play it back.- Thread-safe state updates via
threading.Lock:load(),seek(),play()and_flush_and_refeed()hold the lock while they_feed_pos,audio_dataor thestretcherChange. Race conditions between feeder thread and main thread are no longer possible. - Result: An active audio stream now has absolute priority — it will no longer be starved by UI operations.
Further rule actions are decoupled.
dual_view_toggledeferred viaQTimer.singleShot(0, ...)— same pattern aslayout_loadin v0.79. The toggle paths withrestoreState/restoreGeometryblocked for up to 105 ms.system_pingasynchronous in the Daemon thread —winsound.BeepBlocked the main thread synchronously for the full duration of the tone (~300 ms). The trigger now completes instantly, and the beep plays in parallel.
0.79 — Performance: layout_load deferred (2026-05-15)
Bugfix: Audio dropouts when changing layouts via rules (TIC-0025)
layout_load-Action deferred —restoreState/restoreGeometryblocked ~75 ms synchronously on the main thread (GIL), exactly atsong_started-Trigger. WithQTimer.singleShot(0, ...)The layout change is deferred to the next event loop tick, so the audio callback runs first. Identical pattern to the already deferred one.play-Action.
0.78 — Performance: Audio dropouts (2026-05-15)
Bugfix: Song dropouts during live performance (TIC-0025)
- Song list:
set_last_played_mapoptimized — Previously, all 2401 table rows were rewritten at song start (a 144 ms GIL block on the UI thread). Now, only the actually changed rows are updated (typically 1 row, ~0 ms). This fixes the main cause of audio dropouts on less powerful machines. _apply_filterbuilds_row_by_id-Dict on (song_id → line index) for direct access without linear search.
Rule Engine: Action Timing in the Log
- Each rule action now logs its execution time in
rules/rules.log(e.g.song_list_refresh({}) [2.1ms]It facilitates the diagnosis of performance problems during live operation.
0.77 — Permanent Custom Filter (2026-05-14)
Planner — Permanent custom filter slots
- „"Permanent" toggle button in each of the 4 custom filter slot rows (behind the remove button)
- When the button is pressed, the file path of the loaded playlist is entered in the INI file (section).
custom filter) saved - Removing a slot automatically resets the permanent status.
- When the Planner is first opened in a session, permanent entries are read from the INI file and the playlists are automatically loaded as custom filters.
0.76 — Planner Custom Filter (BL-097) (2026-05-12)
Planner — Custom playlist filter
- „"Custom" button In the filter row (after All/Pattern/Singing, before Genre): opens the new custom filter dialog.
- Custom filter dialogUp to 4 fixed slots, each with [Load] and [Remove] buttons; loads saved playlist TXT files (current and old formats)
- Preview table The dialog displays the intersection of all loaded slots in real time.
- Display name Can be changed by double-clicking the slot name (playlist data remains unchanged)
- Extra line in the planner Appears after acceptance with checkboxes for each loaded slot — only visible if at least one playlist is loaded.
- Checkboxes on/off immediately filters the song pool to the intersection of the active playlists.
- All other filters (search, sort, type, genre) remain effective.
- The filter is session-only (no persistence after app closure).
0.75 — Quality + ERR Fill, Evening Planner Fixes (2026-05-11)
New tab in the Potential widget: Quality + ERR Fill
- Single record passSongs with missing quality or ERR ratings are displayed individually — no more skipping lists.
- Double-clicking the Loops column opens the Loop Count dialog (Playlist + Planner): Title (bold), below it Type (Pattern / Singing / Pattern + Singing), Label, current Quality and ERR value
- Quality buttons (1–10): only visible if Quality is not set; current value highlighted
- ERR buttons (1–4): in ERR colors (red / orange / green / blue); only visible if ERR is not set
- Auto-AdvanceOnce both values are set, the display automatically jumps to the next song.
- „▶ Preview“ / „⏹ Stop“ Button next to the title: loads the song into the player and starts playback; second click stops it.
- Navigation with „◀ Back“ / „Next ▶“ (easily readable) + counter „Song X by Y“
- Badge count in tab title
Evening Planner Fixes
- ERR bars never appeared: Songs with
err=0(not rated) deliveredpattern_err=0→_draw_bardrew nothing. Fix: Songs witherr=0but get an existing slot grey bars at target ERR level (consistent with table behavior) - Dock not dockableEvening Planner Dock is now only lockable (no longer movable/floating) — this will remain the case even after
restoreState()firmly
Further fixes
- AI prompt The metadata tab is now always in English.
- Statistical texts Fully translated after export/import/CSV comparison (no more hardcoded German strings)
0.74 — Metadata tools: Song properties, CSV matching, metadata export/import (2026-05-11)
New feature: Extended song data (BL-094)
- Generic
song_properties-TabelStores any number of key-value pairs per song (initial:original_artist,release_year) - "Advanced Data" button„ In the song data record, a generic editor with an editable key-value table opens.
- Label field Renamed to "Label + No." with example placeholder "e.g. SQR 123"
New widget layout in the Potential widget
- Conversion to QTabWidgetEach of the 10 exams gets its own tab (badge count in the tab title)
- The first tab loads automatically when opened.
- Tab scroll buttons widened (minimum width 24 px)
- New tab „Fill in metadata“ (BL-114) with three tools:
Metadata tools (BL-114)
Match with Music CSV
- CSV comparison button (Firstly): Automatically compares missing song metadata with a supplied CSV database.
- Three-stage matching: 1) exact title, 2) label code + number, 3) fuzzy (difflib, threshold 0.80)
- Preview table with checkbox for each song, "All / None" selection
- Green cells = definite match, yellow cells = ambiguous → Double-click opens selection list
- Supported fields: Artist, Label/No., Genre, Original Artist, Year of Release
music-extended-data/music_extended_data.csvis automatically included with every release
Export gaps (JSON)
- Field selection dialog (which empty fields to export?)
- Exports songs with missing data as JSON with
genres_available-List - Statistics after export (number of songs, missing fields)
Display AI prompt
- Ready-to-copy instructions for AI assistants, always in English
- Includes all genres available in the system as allowed values
Import data (JSON)
- Loads back enriched JSON, displays a preview table with checkbox selection.
- Unknown genres are marked and skipped.
- All statistics texts are fully translated (no more hardcoded German strings)
Playlist compatibility
- V1 playlists (Titles only, old format) will load correctly again.
- New playlists are saved with a title instead of a filename (Format V3: Type + Loop Count + Title)
- The loader automatically recognizes all three formats (V1/V2/V3)
0.73 — Evening Planning: Evening Planner Widget (2026-05-10)
Potential Widget: New Examiners
- Without ERR (BL-115): Lists songs for which the ERR value has not yet been set (
err = 0Double-clicking navigates directly to the song. - Genreless (BL-116): Lists songs without genre assignment. Double-clicking navigates directly to the song.
- Incompatible format (BL-117): Checks if audio files can be read by the internal decoder (soundfile/libsndfile). Detects MP3s with non-standard frames that can only be read by ffmpeg-based players. Works like the BPM and loop check with time estimation (5 sample files → extrapolation → confirmation → full check in the background thread). Double-clicking navigates to the affected song; an ignore function is available.
Bugfix
- Import of new songs fails (
You did not supply a value for binding parameters :err):errmissing ininsert()-Dict — the column was added when BL-111 was added to the SQL, but not to the Python dictionary. New songs are always started witherr = 0(not set) imported.insert()andupdate()use nowdataclasses.asdict()Instead of manual dictions — new fields in the song model will be automatically taken into account in the future. - Fixed crash during song import (
TypeError: '>' not supported between instances of 'str' and 'int''):qualityValues stored as text or decimal numbers in the database (e.g., from older migrations) could completely block the app at startup._row_to_songconvertedqualitynow robustint; an automatic database migration cleans up existing legacy data on the first start of the new version.
New feature: Evening Planner
- New dock „Evening Planning“ parallel to the existing Planner (View menu)
- Emotional arc: Bezier curve with Catmull-Rom interpolation as a visual target
- Sawtooth blocksCurveEngine automatically segments N tips into blocks (configurable min/max, default 3–5 tips), each block with an ERR pattern of 3→4→2→1
- ERR bars: Patter (rich color) and Singer (light color) as separate bars per tip; height = emotional intensity
- Drag handlesMove ERR targets with the mouse; configurable grip distance (per tap / 30 / 45 / 60 / 90 min)
- Break supportBreaks are represented as grey blocks on the timeline, proportional to their duration; hard block boundaries.
- Song suggestionsSongScorer rates according to
quality × days_since_last_played × err_match; best suggestion automatically grayed out - Compensation ruleSinger-ERR is complementary to Patter-ERR (sum ≈ 5)
- 4 strategies: Pattern + Singing alternating, Singings only beginning/end, Pattern only, Singings only
- Detailed list (PlannerTable)Tabular view of all tips with time, song title, label, ERR; pauses can be moved via drag & drop.
- Zoom & PanZoom-in/out/fit buttons, QScrollArea for horizontal panning
- Location integration: Automatic update of suggestions when changing locations
song_db.pyNew methodget_planner_candidates()for ERR-filtered candidate query- Candidate dialogueDouble-clicking a guess slot opens a dialog with all matching candidates (score, ERR, label, filename); for the pattern slot, optional bonus columns for genre and label matching are available; double-clicking or OK confirms the song for that slot.
- Genre filterCheckbox + Button restricts song candidates to selected genres (applies to auto-fill and candidate dialog); Button displays a compact summary of the selected genres.
- Planning rules dialogueConfigurable rules for proposal calculation
- balance: Patter-ERR complementary to Singing-ERR (sum ≈ 5)
- Same-Genre Boost / Same-Label Boost: Multiplicative score bonus (factor configurable) if pattern and singer are from the same genre/label
- First-Tip-SoftFirst tip: prefer baseline/calming
- Last-Tip-StrongLast tip: prefer climax or preparation
- Export button (green checkmark): Transfers all confirmed slots as a new playlist (only confirmed ones, no grey suggestions)
- Two fill algorithms:
_fill_optimal(global optimization, minimizes repetitions) and_fill_greedy(faster, greedier per slot)
0.72 — Potential: Without MP3 / Without quality, Crash handler Qt extension (2026-05-07)
Potential Widget: Two new data quality checks (BL-027)
- Without MP3: Shows songs whose MP3 file is not found in any configured music folder.
- Lazy Load: File check only starts when the button is clicked, not when the app starts.
- Progress dialog during the check ("Checking MP3 files... x/n")
- Runs in the background thread (QThread), UI remains usable, can be canceled.
- Double-clicking navigates to the song in the song list; ignore function available.
- Without qualityShows songs with
quality = 0(Default value = never rated) - Double-click to navigate to the song; ignore function available.
Crash handler: Qt message handler (BL-103)
qInstallMessageHandlerRegistered: Qt's own critical and fatal alerts are now being intercepted.- At
QtCriticalMsgandQtFatalMsg: immediate writing of a crash log file (including ring buffer) - Protects against a class of Qt-internal errors that
sys.excepthookcannot reach
0.71 — ERR field, Planner search, Auto-Fill, Button wrap (2026-05-07)
ERR field: Emotional Response Rate (BL-111)
- New field
errin the song database (INTEGER, 0–4): evaluates the emotional impact of a song during a dance evening - Values: 0 = not rated, 1 = peak, 2 = preparation, 3 = baseline, 4 = calming down
- ComboBox in the song data widget; only the number is saved, no lyrics.
- DB migration: new field is automatically added to existing databases
Auto-Fill in Planner (BL-112)
- New magic wand button (3rd position in the middle bar) automatically populates the playlist.
- Dialog: Selectable number of pattern and singing tips + one of 4 strategies:
- Random — Songs are randomly selected
- Rarely played — songs played infrequently preferred
- Quality — Songs sorted by quality rating
- ERR sequence — songs according to emotional curve (preparation→climax→baseline→calming)
- Dual-type songs (pattern + singing) correctly retain the selected mode.
- Total playlist duration taken into account when looping.∞ the preset pattern duration of the program/Clubs
Planner search (BL-106)
- Search field at the top of the pool (left column of the planner): filters simultaneously by title, label, and filename.
- Use the X button to clear; the search works in conjunction with the other filters (genre, type, etc.).
Button bar with line breaks
- New support class
_WrapButtonBarButtons are arranged side by side, but automatically wrap to a second line if the dock window is too narrow. - Song list and playlist now use this bar — no more cut-off labels.
- All buttons in a row are adjusted to the same height (row maximum).
- Button text made more compact: „→ Note“ → „+ Note“, „→ Playlist“ → „+ Playlist“
Other
- Standard dance program at startup: Button displays „MS“ (Mainstream) instead of „—“
0.70 — Potential Widget: Bulk actions; UI bug fixes (2026-05-05)
Potential Widget: Bulk Actions (Extension BL-027)
- Auto-loop for everyoneNew button in the "No Loop" check — automatically sets a loop for all affected patterns using the loop finder. For more than 5 songs, a time estimate is calculated based on 5 samples and displayed to the user before confirmation.
- Beat-Snap for everyoneNew button in the "Without BeatSnap" check — snaps the loop-in and loop-out of all affected songs to the nearest beat. Same timing principle: for more than 5 songs, a preliminary estimate is given; otherwise, it starts immediately.
- Delete empty locations: New button in the „Empty Locations“ check — removes all locations without playback history after confirmation.
- All bulk operations run in the background thread (no UI freeze), with a cancelable progress dialog ("Cancel" button).
- SQLite Thread Safety: Workers open their own database connection via
db_path, instead of sharing the connection of the main thread.
Bug fixes
- Loop Finder Widget: Segment bar (7 Singing Call sections) was cut off at the bottom after the player redesign — height corrected from 14 px to 28 px.
- Loop Widget ButtonsDescenders (p, g) in two-line buttons („Loop\nFinder“, „Beat\nSnap“ etc.) have been cut off — QPushButton padding in all themes reduced from 10 px to 5 px vertically.
0.69 — Rules: BPM conditions + Auto-Detect action; central path resolution (2026-05-03)
Rules — new conditions
- BPM Set: checks if the current song has a BPM value set (
base_bpm > 0) - BPM Not Set: Counterpart — Song does not yet have a BPM value
Rules — new campaign
- Auto-Detect BPM (Group „Audio“): Starts automatic BPM detection for the currently loaded song in the background — identical to the „Auto BPM“ button in the song data widget, but can be triggered as a rule action (e.g. via the „Song Changed“ trigger with the „BPM Not Set“ condition).
- The result is stored in the database and the BPM field in the song data widget is updated immediately.
- Runs idempotently: second call during ongoing detection is ignored.
- „BPM is determined…„"Overlay during recognition (analogous to the auto-loop overlay)"
Central path resolution (BL-104)
PathManager.find_lyric_file(filename)new — searches for lyrics file in the configured lyrics folder (equivalent tofind_song_file())SongDataWidget._on_auto_bpm(): now usesfind_song_file()instead of directmusic_dir-Join — finds songs in all 4 music slotsLyricsWidget._load_lyrics_file(): now usesfind_lyric_file()instead of directlyrics_dir-Join
Bug fixes
- TIC-0016The Auto-BPM button did not respond to clicks — the cause was
music_dir-Join that only searched slot 1; fixed byfind_song_file()(Part of central path resolution) - TIC-0023: Features ignored alternative music/lyric paths (slots 2–4) — fixed by central path resolution (BL-104)
- TIC-0007 / TIC-0022Crashes without details can no longer be analyzed — structurally fixed by crash handler (BL-103): automatic log file for every unhandled crash
0.68 — Player widget redesign (2026-05-02)
Player widget: New layout
- Information strip (Top row): 4 equally wide columns with a label at the top and a value below — Duration / BPM / Loops / Program
- BPM displayThe column header now only shows the numerical value; "BPM" appears above it.
- Loop Count: now only shows "3/8" or "∞", column title is "Loops"„
- Song title + status On a single line: Title left-aligned, status right-aligned
- Song titles dynamically scale: utilizes all free vertical space of the player card, font size increases from the theme's base size to +13 px — with line wrapping when space is limited
- Status text Remains permanently in a small, fixed font size (font_size − 2), does not scale with the title
new section bar
- 7 QPushButton segments instead of custom paintEvent
- Gestalt-based color scheme: O/M/C (structural markers) in red, 1/3 in light gray, 2/4 in dark gray — the singing call pattern is immediately visually recognizable.
- Colors via new skin keys
sec_o,sec_1,sec_2,sec_m,sec_3,sec_4,sec_c— included in all 4 skins (default, light, win11, elegant)
Transport buttons: SVG icons
- Play, Pause, Stop and Fade-Out are represented by SVG vector icons.
- The icon color dynamically follows the theme setting.
button_text— No separate SVG files are needed per theme - Fade-out arrow points to the right (→)
- Play button: full width, minimum height 44 px, accent color from the theme
Theme-relative font sizes in the info strip
- All font sizes relative to the
font_size-Skin settings - Labeling labels:
font_size − 2px - Value labels (BPM, Loops):
font_size + 1px - Continuous timer:
font_size + 2px, monospace bold
Space-saving adjustments (laptop optimization)
- Loop widgetButton height reduced from 52px to 38px, NEW button reduced from 38px to 32px, spacing reduced from 6px to 4px.,
addStretch()Removed from the bottom edge, bottom margin reduced to 4 px — saves ~100–120 px total height - Program button In the info strip: height limited to a maximum of 24 px, internal padding reduced.
- Song title area: Maximum height capped at 52px (prevents excessive white space between title and playtime)
- Minimum height player widget: 380 px (previously 420 px)
0.67 — Crash handler, media keys, bug fixes (2026-05-01)
New: Crash Handler (BL-103)
- New module
crash_handler.py: automatically catches unhandled Python exceptions - With every crash
crash_YYYYMMDD_HHMMSS.logstored in the app directory - The log contains: timestamp, song, location, full stack trace, and the last 25 user actions (ring buffer).
- The next time the app is started, a notification dialog will appear with a "View log" button (opens text editor).
- Logged actions: Song loaded from list, song loaded from playlist, playback started, location changed, Planner Confirm
Media and Fn keys as rule triggers
- Volume+, Volume−, Mute, Media Play/Pause, Media Stop, Media Next, Media Previous, Brightness+, Brightness− are now available as triggers in the Rule Engine.
- Interception via app-wide event filter (analogous to F13–F24) — works if the OS does not ignore the keystrokes system-wide.
- New diagnostic script
2_Test/key_monitor.py(+.bat): displays the key code, trigger name, and whether Caller's Caddy would process each pressed key — helpful when setting up Stream Deck / wireless remote controls
Statistics Dock: Context Menu (BL-102)
- Right-clicking on a song in the TOP / FLOP / Never Played lists opens a context menu.
- „Add to playlist“ → Song goes directly into the current playlist
- „"Add to notes"“ → adds a
[load_song "Title"]-Save shortcode as a new note
Bug fixes
- TIC-0019 Planner: Loop data was not updated after rule execution — Loop count dialog now reads data fresh from the database
- TIC-0020 Managing dance programs: Column header „Target duration (min)“ was cut off — the column now automatically adjusts to the header text
- TIC-0021 Statistics Dock: Alternating row colors had too little contrast —
alternate-background-colornow defined for all 4 skins - Statistics dock → „Add to Notes“ crashed if the Notes dock had never been opened before (
notes_widget(Not yet lazy-initialized) — Fix: synchronous initialization before access (found by the crash handler in the same session)
0.66 — Bug fixes (TIC-0015, TIC-0017, TIC-0018) (2026-04-30)
Bug fixes
- TIC-0015 Lyrics zoom level is now correctly restored on app startup — zoom value and auto-size state are stored in the INI file and applied immediately on the next startup.
- TIC-0017 The Loop Count dialog in Planner now also finds songs in music folders, slots 2–4 — Function
show_loop_count_dialognow usesfind_song_file()instead of just slot 1 - TIC-0018 Rule action „Load Layout“: The dropdown now shows all saved layouts from the
skins/-Folder -layout_names_providerconnected, TODO-Stub replaced
0.65 — Stats Dock (BL-019) (2026-04-29)
New Dock: Statistics
- New dockable, lazy-loaded "Statistics" window in the View menu (tabbed with Reports)
- filter (above): Location (All or individual), Type (Both / Pattern / Singing), Time period (All time / 5 years / 1 year / 3 months / 1 month)
- Three columns (scrollable, all songs without limit):
- TOP — all played songs, most played first, with number of plays
- FLOP — all songs played, least played first, with number of plays
- Never played — all songs without play in the current filters, alphabetically
- Double-click Clicking on a song jumps directly to the song list.
- histogram (Full width): Distribution of all songs by number of plays
- Bin 0 is always fixed for "never played", followed by 9 logarithmically distributed bins.
- Color gradient from blue (cold = rarely played) to orange-red (hot = often played), regardless of the skin
- A tooltip on each bar shows the bin area, number of songs, and up to 5 sample tracks.
- Full translations available in German and English.
0.64 — First Steps package, tutorial overhaul, playlist improvements (2026-04-28)
Example project for beginners (first-steps/)
- first-steps/folder is included in every new installation
- Includes „YRR 049 – Electro Blues.mp3„ by Jon Hansell Nilsson (kindly provided) and the matching lyrics sheet “YRR 049 – Electro Blues.htm”. Yellow Rock Records Offers free pattern music. Definitely worth checking out.
- The lyrics sheet humorously addresses the functions of Caller's Caddy.
build.pyStep 3 copied1_Source/first-steps/automatically into the app folder
Tutorial: New Songs Tour (completely revised)
- Renamed from „Loop Tour“ to „New Songs Tour“
- Menu order: New Songs Tour now directly after Player Tour (Priority 97), Loop Finder directly below (Priority 96), Beat Snap after that
- Step 1 (Import button): Explicit call to action with step-by-step instructions through the three import dialogs — Song type „Both“, Copy, Individual files from first-steps/
- Step 2 (Auto-Loop): Loop Finder as a second step instead of manual In/Out setting — manual buttons and Beat Snap removed from the tutorial
- Song Data Tutorial Step 4 has been added: "Link lyric sheet" with a reference to first-steps-HTM
Song list: Add song to playlist
- → Playlist button below the song list (next to "Update list" and "→ Note")
- Right-click context menu Song list: new entry „Add to playlist“
- „The "→ Note" button has been moved from the search bar down into the button bar.
Playlist: Remove songs
- ✕-Button The arrow keys ▲ ▼ immediately remove the selected song.
- Right-click context menu: „Remove from playlist“ at the very top (before separator)
- Delete key: QShortcut with
WidgetWithChildrenShortcut-Context — works regardless of which child widget has focus
0.63 — LoopFinder Lazy Init, Mapping Export/Import, Sequences Export (2026-04-27)
LoopFinder: Lazy Initialization
LoopFinderWidgetIt is no longer created at startup, but only when the window is first opened.- Saves ~100ms startup time on weak hardware (Notebook: addDockWidget was 106ms)
- Waveform and jump areas are displayed immediately upon opening (no manual "analyze" required for the preview)
- Song information will be provided later if a song is already loaded when opening the app.
setFloatingandrestoreGeometryof the Dock window also viaQTimer.singleShotaftershow()delay
Mapping Export/Import (Sequence Menu)
- Export mapping…Saves all
call_text_mappingsas a JSON file (call_text,entity_id,mapped_by) - Import mapping…: Reads JSON, inserts new entries (
INSERT OR IGNOREskips existing - Feedback: "X new mappings imported, Y already exists (skipped)"„
- Remapping is automatically triggered for new entries.
Export sequences (JSON)
- New menu item Export sequences (JSON)... after the three import points
- Exports all sequences in the exact same format as the JSON import expects (
id,calls,level,seq_type,difficulty) - The exported file can be directly imported again via "Import sequences (JSON)".
UI detail
- Arrow buttons (◀ ▶) and the note button in the Sequence Details window now have a uniform height (40px) — improved accuracy on laptops
Project documentation
CLAUDE.md:setFloating(True)On Windows, it costs ~90ms (once per floating dock context) — it only moves between buckets when you defer it, it doesn't save any overall time.
0.62 — CallMatcher & Sequence UI Improvements (2026-04-27)
Call Mapping: Intelligent Auto-Suggestion (CallMatcher)
- Three-stage matching fully integrated
sequence_mapper.pyOutsourced — no API costs, runs locally in milliseconds - Level 1: Exact comparison after normalization (prefixes/suffixes removed) → Score 1.0
- Level 2Bidirectional token overlap (geometric mean of precision × recall) → score up to 0.92
- Level 3:
difflib.SequenceMatcheras a fallback (only if token score ≥ 0.30) → score up to 0.85 - Color coding the call text lines in the mapping dialog:
- 🟢 Green (Score ≥ 0.85): safe proposal
- 🟡 Yellow (Score 0.50–0.84): uncertain proposal, manual review recommended
- 🔴 Red (Score < 0.50): no usable suggestion
- Green also applies to already mapped entries
- Old
_normalize_call_text/_norm_index-System inmain.pythroughCallMatcher-Import replaces
Sequence table: UX improvements
- Level, Type and Difficulty columns hidden (
setColumnHidden) — Sequence fills the full table width - Type filter dropdown starts with „Singer (Corner progression)“ as the default value (most common type)
- Bugfix:
ResizeToContentIn the Type column, the Sequence column shrank if many rows had the same long type.
Performance logging
- New measuring points:
SequencesWidgetandSequenceViewWidgetseparately measured - New measuring point:
_build_menu(was previously insong_list.refreshhidden) - New measuring point:
_init_sequencesinternally divided (load_sequences+sequence_view prefill) - Bugfix: LoopFinder split incorrectly displayed notes time as well (
_td10→_td10b)
0.61 — Sequence Import & Call Mapping (2026-04-26)
Sequence table extended
- New columns
typeanddifficultyin thesequences-Table (migration idempotent) insert_sequence()nowseq_typeanddifficultyin contrast to- New database methods:
get_sequence_type_values(),get_sequence_difficulty_values()
Sequence UI extended
- Table: from 3 to 4 columns — sequence (Stretch, instantly visible), Level, Type, Difficult
- Second filter row with type- and difficulty-Dropdown
- All filters (Contains, Limit, Type, Difficulty) are consistently applied across tables, navigation, and shortcodes.
New import formats in the "Sequences" menu„
- JSON import (
import_from_json): loads one or more JSON files, appends sequences to - CSDS Import (
import_from_csdsVic Ceder's invites you to visit.in/.csds-Export format; parse#EASY#/#REC=/#SEQTYPE=-Metadata and cleanedtext-Markup automatically - Deduplication via Ceder record ID during multiple imports
- The last import directory is saved in the settings.
Call mapping dialog
- New menu item „Call mapping…“ in the sequence menu
- Table of all unmapped call texts, sorted by frequency (Most frequent first — one entry can heal many sequences at once)
- Right column: editable ComboBox with Contains autocomplete — only opens on click (delegate, no pre-rendering)
- Lazy Loading: only 20 lines initially, more appear when scrolling to the end
- Yellow highlighting for texts without auto-suggestions
- Car suggestion Through normalized text comparison: Prefixes (Heads/Sides/Centers/Boys/Girls…) and suffixes (numbers, fractions, parentheses) are removed.
- Special option „→ Split at a comma“: Calls like
""Flutter Wheel, Sweep 1/4""are split directly within the sequences — subsequent fields automatically shift to the right. - Special entry „"Filler Words"“ (TO=0.001) for filling prophroses that do not have a true level — prevents zero in the level calculation without distorting the result.
- After saving, automatically
recompute_sequence_max_to()initiated
0.60 — F13–F24 Key Triggers (2026-04-25)
Enhanced F-key support
- F13–F24 are now fully-fledged rule triggers — they appear in the rule editor's trigger dropdown menu.
- The capture dialog correctly recognizes F13–F24 when pressed and displays them as „F13” etc.
- Interception via the app-wide event filter (more reliable than QKeySequence strings, which Qt does not parse for F13+)
- Useful for USB remote controls and macro pads that send extended F-key commands.
0.59 — Shortcodes in Notes & Rule Editor Groups (2026-04-24)
Shortcodes in Notes (BL-093)
- Shortcode syntax in notes:
[load_song "Title"]invites a song;[sequence_view id=42]/[sequence_view contains="Swing Thru" limit="MS"]opens the sequence view with optional filter - Shortcodes are triggered when manual check a note as well as via
notes_tick_top-Rule - New module
shortcode_parser.pywith robust regex parser (positional and named parameters, integer recognition) - → Note Button In song list, playlist, sequence overview and sequence detail: inserts the current entry as a shortcode into the notes list.
- → Filter Button In sequence overview: adds the active Contains/Limit filters as
[sequence_view]-shortcode one - Right-click menu (Context menu) in song list, playlist and sequence table: "Add to notes"„
- Warning if no location is selected and a note is to be inserted.
- The song title is copied into the shortcode without display suffixes (type, label, quality).
Rule Editor: Actions grouped
- The 43 rule actions are now in 10 categories structured: Transport · Audio · Layout & Docks · Lyrics & Scroll · Sequence View · Notes · Workflow · Photo · Genre · Info & Warnings
- Non-selectable group headers in the action dropdown for better clarity
- The sequence of actions within the groups is logically sorted.
- Existing rules remain fully compatible — only the display changes.
0.58 — Sequence Detail as a real dock (2026-04-24)
Sequence Detail as QDockWidget (BL-092)
dock_sequence_viewis now a fully functional dock widget — no longer a temporary popup dialog- Can be treated like any other dock:
dock_open,dock_close,dock_fullsize,dock_focus,dual_view, Layout-Save/Restore - Clicking on a line in the sequence overview updates the details dock and brings it to the foreground.
- In the rule editor under the short name
sequence_viewavailable (e.g.dual_viewwithdock_left=sequences+dock_right=sequence_view) sequenceview_maximizeOpens the Dock as a floating 90 % window — no more conflict with Dual View- Navigation (◀/▶, keyboard ← →) remains active;
sequenceview_prev/sequenceview_next-Rule actions directly control the dock - All rule action names are consistently in English:
sequenceview_*(instead ofsequenceview_*) - Filter SyncIf the user changes the Contains or Limit filter in the sequence overview, the detail dock automatically jumps to the first sequence of the new results list (only if the dock is visible).
- Startup pre-fill: When the app starts, the details dock is immediately filled with sequence 1 — no empty window on first opening.
0.57 — SequenceView Navigation & Fullscreen (2026-04-24)
SequenceView — Navigation without closing the dialog (BL-089)
- ‹ / › Buttons In sequence view: scrolls through the currently filtered list
- Position indicator „3 / 12” between the buttons — the caller immediately sees where he is in the list.
- Keyboard support: ← / → Arrow keys also navigate (ideal for hands-free operation)
- Buttons are automatically deactivated at the beginning and end of the list.
- Navigation always refers to the entire filtered list (not just loaded rows).
- New DB method
get_filtered_sequence_ids()provides all matching IDs for navigation
SequenceView — Auto-Zoom & Free Window Size (BL-090)
- Freely enlargeableThe dock can be resized to any size.
- font size as it growsThe font size of the calls automatically adjusts to the available window height — the sequence optimally fills the window.
- ◀ / ▶ Buttons in a uniform size (font-size 16px)
- Position label „X / N“ uses the font color of the active theme.
SequenceView — Rule Actions (BL-091)
sequenceview_open: shows the details dock with the current table selectionsequenceview_close: hides the detail docksequenceview_prev/sequenceview_next: scrolls per rule/Keyboard shortcut to previous/next sequencesequenceview_focus: brings the detail dock to the foregroundsequenceview_maximize: makes the detail dock a floating 90% window- Auto-zoom bidirectionalFont size is also adjusted upwards if the initial estimate was too conservative.
0.56 — Dual-View & Song List Quick Navigation (2026-04-23)
Dual-View: two widgets side by side (BL-077)
- New rule action
dual_viewOpens any two docks as floating windows side by side — together 90 % screen width and height, centered with a 4 px gap - Flexible width ratio: Selection from
50:50,33:67or67:33directly in the rule editor - New promotion
dual_view_closeCloses and docks both dual-view windows. - New promotion
dual_view_toggle: Pressing a button opens the dual view. (Layout is saved automatically), a second keystroke restores the original layout exactly — ideal as a keyboard shortcut - All three actions appear with English display names in the rule editor; parameters
dock_left,dock_rightandsplitas usual dropdowns - Most common combination: Lyrics on the left + sequences on the right, 50:50
0.55 — Planner loop dialog & double-click fix (2026-04-22)
Planner: Loop dialog with target pattern length pre-set (BL-085)
- Loop Count Dialog In the Planner and Playlist widgets, the target pattern length of the active dance program is now automatically used as the default setting (instead of a fixed 7 minutes).
- If no dance program is set, the default value of 7 minutes remains.
Playlist widget: Double-click on the Loops column (BL-085)
- Double-click on the Loops column The Playlist dock now opens the same loop count dialog as in Planner — the number and time setting can be edited directly.
- Reliable triggering via
mouseDoubleClickEvent-Override in_PlaylistTable, which has a known Qt 6 timing conflict between DragDrop mode andcellDoubleClicked-signal bypasses
0.54 — Dance Program System & Location Extensions (2026-04-22)
Dance program display in the player (BL-083)
- New button
btn_programIn the player info bar (next to BPM): displays the currently selected dance program abbreviation (e.g.MS,A1 Class) - Quick Selection DialogClicking the button opens a grid of all configured programs as buttons — button width automatically adjusts to the longest text.
- 14 Default Programs: MS, MS Class, PL, PL Class, A1, A1 Class, A2, A2 Class, C1, C1 Class, C2, C2 Class, C3A, C3A Class — each with configurable target pattern length (standard 7 min)
- Administrative dialogue via menu Database → Manage dance programsCreate, rename, adjust order and target pattern length, and delete programs.
- New DB table
dance_programs; Existing installations will automatically receive the default programs on the next startup (INSERT OR IGNORE)
Location settings: Dance program & temporary tempo (BL-084 + BL-086)
- New "Settings" button In the location dialog: opens a settings dialog for the selected location.
- Dance program assignment per locationWhen a location is selected, the saved dance program is automatically set in the player.
- Temporary pace per locationSpinBox (50–150 %, standard 100 % = no effect). When changing locations, the saved value is automatically transferred to the "Temporary Pace" field — useful for classes and beginner groups with a fixed pace limit.
- New DB columns
dance_program_idandtemp_tempoin thelocations-Table (Migration for existing installations)
0.53 — Class Designer: Review & Optimize, Notes Fine-tuning (2026-04-20)
Class Designer — Check & Optimize (new)
- „"Check" button In column 3: explicitly triggers overload/underload coloring of the daily headers and distance rule check.
- Orange marker for teaches that violate Prereq delay rules (previously red) — clearly separated from the red overload daily header
- „"Optimize" buttonIterative Local Search (Best-Improvement Hill Climbing) on the existing plan does not replace generator reassignment, but retrospectively cleans up violations and load imbalances.
- Objective function:
Violations × 10,000 + Σ(Load − Ø)²— Constraint violations dominate strongly, load variance is fine-tuned below. - Respects manual drag changes in column 3
- Hard constraints are checked for each move: pre-delay, follow-up delay, repeat after teach, no duplicate repeats on the same day.
- Converges deterministically (max. 200 iterations); typically much faster.
- Algorithm classification (RCPSP / Sprint Rebalancing) documented in
docs/16_class_designer.md
Class Designer — UX improvements
- Effort fields as a row of buttons Instead of a ComboBox: all Fibonacci values (1, 2, 3, 5, 8, 13 or 0–13 for Info) are directly visible as toggle buttons — one click instead of opening a dropdown.
- New entries behind selected elementWith „+ Call“ and „+ Info“, the new element is inserted after the currently selected one (instead of at the end) and automatically highlighted — chain insertion works naturally.
- Effort filter in column 2: Toggle button row
0 | 1 | 2 | 3 | 5 | 8 | 13Between the toolbar and the planning table. All are active by default — allowing you to check at a glance whether calls with the same effort are also similarly time-consuming. n_eveningsIt is stored in the Col3 widget so that Optimize works with the correct frame even after manual changes.
Notes widget — Display & Editing
- Top open note enlarged 4x (BL-079): The most important note is prominently displayed as a large, bold headline — magnification factor configurable in INI (
notes/first_note_factor, Default 4.0) - Compact line spacing For long, multi-line texts: The label now renders word breaks itself (instead of using Qt's standard line height) and uses approximately 90 % of the font size as a line break — saving considerable space on the large first line without cutting off the descender.
- Word break For very long notes: Text wraps cleanly within the line, line height increases accordingly.
- Double-click to edit: Left-clicking on a note line opens an edit dialog with a multi-line text field — styled to match the theme, language follows UI setting (DE/EN),
Ctrl+Enterconfirmed - Zoom buttons +/− still active — the new rendering logic respects the zoom level
- New DB method
update_note_text(note_id, text)insong_db
Rule system
- New promotion
notes_tick_top(BL-080): Checks off the top open note of the active location — useful, for example, for keyboard shortcuts or timer events. If the list is empty, it is silently ignored (no error message).
Internal cleanup
- New Helper Widget
_ValueButtonRowfor exclusive value selection (reusable for further discreet selections) - Helper
_insert_after_selected()In Col2 — centralized insertion logic - New QLabel subclass
TightLabelwith ownpaintEvent+ manual word wrapping for precise line spacing control - New modal dialogue
_NoteEditDialog
0.52 — Class Designer (Prototype) & Tracking Fix (2026-04-17)
Class Designer — First Prototype
- NoticeThis is the first prototype of the Class Designer — further refinement is definitely needed
- More even point distribution per daySwitch to greedy bin filling. Each day is filled up to the target budget (total points / number of days) before the next day is filled.
- Repeat constraints are respectedRepetitions of the same figure will still have at least a 1-day interval; pre-delays will remain in place.
- Underfilled days avoidedIf a repeater is used because
earliestIf the constraint jumps ahead, the day pointer lags behind — subsequent teaches fill in the remaining day instead of leaving it empty.
Loop Finder — Time display under search areas
- Playing times under the percentage fields: Under each of the 4 percent fields (Loop-In Start/End, Loop-Out Start/End), the specific playing time of the loaded song is now displayed in the format
m:ssdisplayed (e.g.0:53This allows the caller to see at a glance where the search area is located within the song. - The display updates live when percentage values are entered and when the waveform handles are dragged.
- Uniform line height: Preset combo boxes and load/save buttons now use the same height as the percentage spin boxes.
Bugfix — Playback history
- Tracking only during actual playPreviously, the "Last Played" column was updated simply by selecting/loading a file. Now, the timestamp is only set when the play button is actually pressed. The song does not need to play through completely.
- The DB entry in
play_historyThat was already correct, only the UI column was ahead.
0.51 — Notes widget improvements (2026-04-15)
Notes widget — redesign & new features
- Export folder
notes/A new subfolder will be created automatically; this is the default location for loading/saving JSON files. - background colorThe "Done" list now has the same background color as the "Open" list — a consistent appearance.
- Export marking: Selection checkbox replaced by
_SelectToggle(○ / ✓) — no more Qt-QSS problem with invisible checkmark - Drag Highlight: The dragged row receives a colored background and left border (accent color) during the move.
- Select all / Deselect allTwo new buttons
All ✓andAll ○for fast export selection - Zoom controls:
−/100%/+Top right — only changes the font size of the list entries; icons from the active skin - Zoom persistenceZoom setting is stored in INI file (
notes/zoom_pct) and restored on the next start - Timestamp for completed items: Completion date will be in the format
[DD.MM.YY HH:MM]displayed behind the text - Import orderNotes loaded from JSON are inserted at the top in the correct order.
- Done-Toggle: ☐ (open) / ☑ (done) — Pen experiment undone
Loop Active Checkbox — Accessibility
- Visible hookAll 4 skin QSS files have been expanded —
QCheckBox::indicator:checkednow shows a white checkmark (check.svg) on a colored background
Sequence Widget
- Zoom persistenceZoom setting is stored in INI file (
sequences/zoom_pct) and restored upon startup
performance
- Notes dock lazyThe widget is only created on first opening (like Reports, Potential, Photo) — no startup overhead.
0.50 — Freely assignable key triggers (2026-04-09)
Create your own key triggers (BL-064)
- New button „+“ in the Rules dialog next to the trigger selection
- Clicking opens a mini-dialog: User presses any key — the trigger name is automatically determined.
- Supported keys: A-Z, 0-9, F1-F12, Space, Return, Delete, Tab, Escape, Insert, Backspace, Home, End, PageUp, PageDown
- After creation, the new trigger immediately appears in the trigger list and can be assigned to a rule.
- persistenceNew triggers are automatically restored when the app starts, provided at least one rule is linked to them.
- Focus SafetyKey triggers will not fire when a text field or search is active—these always take priority. This will automatically apply to all future triggers.
- Dynamic event filter: No longer hardcoded — all registered
key_*Triggers are automatically detected and forwarded.
0.49 — Label detection (bidirectional), lyrics co-import (2026-04-08)
Label recognition — bidirectional file naming
- Format 1 (Title Label):
Ring Of Fire-RYL818.mp3→ Title: „Ring Of Fire“, Label: „RYL818“ - Format 2 (Label Title):
RYL818-Ring Of Fire.mp3→ Title: „Ring Of Fire“, Label: „RYL818“ - With spaces in the label:
YRR 043a-Dunderklumpen.mp3orDunderklumpen-YRR 043a.mp3 - Regular expression pattern: letters + optional space + numbers + optional suffix (a/b/+)
- Supported label formats:
BVR113,RYL818+,YRR 043a,RBS 1326
Lyrics co-import
- When importing MP3s, a lyrics file with the same name (without extension suffix) is automatically searched for.
- Source folder (import folder)RTF/HTML/TXT file is converted to
lyrics/-folder copied - Lyrics folder: Already exists → will be linked directly
- Supported poetry formats:
.rtf,.htm,.html,.txt - Log output:
[Import] Lyrics linked:upon successful assignment
0.48 — SqView migration, blind import, theme fix (2026-04-08)
SqView Migration (BL-011)
- Folder selection: User selects the SqView folder directly via Explorer —
sqview.db,MP3/andtext/are automatically detected - Blind importSongs are fully entered into the database even without existing MP3 files (filename as a placeholder). MP3s can be added later via normal file import—existing entries are automatically activated instead of being skipped as duplicates.
- Full song recognitionReads all ~200 songs
markext1/2/3+track-table (not just the ~10 with explicit settings in themusic-Tabel) - Recursive MP3 IndexSearches all subfolders (
pattern/,singer/,Karaoke/etc.) - Lyrics matching: 4-stage regex strategy — exact title, label strip (
- RBS 1234), Normalization (alphanumeric), Combination - Loop and pitch takeover: Values from the SqView-
music-Table will be adopted - Playback history: Out of
track-Table with date/time and location assignment - Music folder is optional (blind import also works without it)
- MP3 counting in the status display is now recursive.
Enable blind import (file import)
- During a normal MP3 import: A database entry already exists for the filename, but the file itself is still missing.
music/-Folder → File is copied and the song is activated (instead of being skipped as a duplicate)
Bugfix: Song Data — light background in the default theme
QScrollArea-The viewport and its contents did not receive a dark background (Qt stylesheet inheritance does not extend across viewport boundaries)- Fix in all 4 themes (default, win11, elegant, light)
0.47 — Loop Finder Presets, CrossFade Beat Snap (2026-04-07)
Loop Finder: Parameter Presets (BL-046)
- Preset Combo Box Replaces the old reset button: displays all saved presets; "Standard" cannot be overwritten.
- Load-Button: Applies the selected preset to search areas, comparison windows, and strategy.
- Save-Button: Always active — with „Standard“ an input dialog for a new name appears, with user presets direct overwriting
- Presets as JSON files in the folder
loop_presets/— portable and editable - Strategy Combo Box In the analysis row: shows all available selection strategies (currently: „"Best multiple of 64 beats"“), is saved and loaded with the preset; further strategies can be added at any time
- Rules action „Auto-Set Best Loop“ now has parameters
preset(Dropdown of all saved presets) - Fully loads search areas, comparison windows, and strategy from the selected preset.
- Newer
preset_choice-Parameter type in rule_widget.py withpreset_names_provider
CrossFade in Beat Snap (BL-067)
- New toggle button CrossFade between Snap and Prelistening
- When active: Pre-listening to the loop jump with the same crossfade as in normal operation.
- Automatically deactivated with every load and every waveform change.
Taskbar icon laptop fix
cc-logo.pngIt is copied to the app root during the build process (previously only available on build machines).
0.46 — Live Volume (BL-070), UI Grid Player (2026-04-07)
Live Volume / Minimum Volume (BL-070)
- Newer Live Volume Slider in the player (4th column next to Today's Tempo / Song Tempo / Pitch)
- Artifact-free volume change via Windows WASAPI (pycaw) — outside the audio stream, no crackling during fast movements
- Reset to 100% on every song change (not persistent)
- INI setting
audio/min_volume(Default0.0): The slider cannot be lowered below this value. - The information will be automatically written to the INI file at app startup if it is missing.
- Graceful Degradation: without pycaw (no Windows device) the function remains silent, the app continues to run normally.
Rules action: Change live volume
- New promotion „Change Live Volume (±)“ with adjustable
deltain percentage points (−100 to +100, default −10) - Automatically respects the
min_volume-Limit from the INI
UI: Player rows in a uniform 4-square grid
- Line „Today’s tempo / song tempo / pitch / live volume“:
QGridLayoutwithcolumnStretch=1+QSizePolicy.Ignored→ columns of exactly equal width - Line „Location / Planner / Lyrics / Loop active“: also transferred to the 4-column grid, flush with the line above.
- Labels with
setWordWrap(True)— no text inflates its column
0.45 — Genre system, rules drag&drop, bug fixes (2026-04-06)
Bugfix: Reports and potential Dock crash on first opening
setFloating(True)in thevisibilityChanged-Handler triggered a re-entrant signal call → Crash- Fix: Disconnect signal immediately + initialize via
QTimer.singleShot(0, ...)reset - Regards
_on_reports_visibilityand_on_potential_visibility
Genre / Tags (BL-063)
- Songs can have multiple genres/tags (Many-to-Many)
- 65 Default Genres from Square Dance Labels + musicforcallers.com (decades, styles, artists, themes, Square Dance specifically, NEW)
seed_default_genres()is idempotent — it only adds missing genres, existing ones remain intact.- Genre management (Menu Database → „Manage genres…“):
- List of all genres with song counter
- Create, rename, delete
- When deleting with associated songs: Option to "Switch to another genre" or "Simply remove"„
- Song recordGenre tags as clickable display + „…“ button opens checkbox dialog
- It's possible to create a new genre directly in the dialogue.
- Changes are saved immediately.
- Import keyword matching: During import, genres are automatically suggested from the filename (e.g., "Christmas" from "Xmas Song.mp3")
- Rules actions: „Add Genre to Song“ and „Remove Genre from Song“
- Parameters as a dropdown of all available genres (no free text → no duplicates)
- Newer
genre_choice-Parameter type in rule_widget.py withgenre_names_provider
Rules: Reorder actions via drag & drop
- Each action row has a [unintelligible element] on the left. ≡-Handle (Cursor ↕)
- Dragging moves the row to the new position live.
- The sequence of actions is saved immediately.
- Bugfix:
_on_action_type_changedhad an incorrect index after handle insertion (combo was removed instead of Params)
0.44 — Multi-music paths, Import Copy/Keep (2026-04-05)
Multiple music directories (up to 4)
- Up to 4 music paths can be configured (Slot 1 = main folder, Slots 2–4 optional)
find_song_file()Searches in sequence slot 1 → 2 → 3 → 4, returns first match.- New dialog „Manage Music Paths“ (Paths menu) with Browse + Clear per slot
- Menu text: „Change music directory“ → „Manage music paths“
- Migration: Alter INI key
paths/music_dirwill be automatically afterpaths/music_dir_1transmitted - Good for callers with program data on one drive and music files on another.
Import: Copy or leave in place
- New intermediate dialog after song type selection: "Copy files?" or "Leave in place"„
- Copying: previous behavior — files go into the music/ main directory
- Leave as is: Files remain where they are, only a database entry is created.
- If you leave it as is: if the source folder is not yet entered as the music path, ask if it should be added as a free slot.
- If all 4 slots are occupied: a warning message will appear with a link to the administration dialog.
Single-Instance-Lock more robust (Race Condition on double-click)
- Replaces QLocalServer/QLocalSocket with atomic QLockFile
- Double-clicking run_test.bat or the EXE file no longer starts a second instance.
Minimum width player and loop dock
- Player dock: min. 340px — prevents unleshares from being squashed together
- Loop dock: min. 400px — all 4 buttons remain readable side by side.
Performance optimization Startup (−22% on laptop)
- Reports Dock:
setFloating(True)is no longer set at startup, but only upon first opening (lazy) → -318ms on laptop - Potential Dock: same optimization → -137ms on laptop
- Total laptop sms saving: ~526ms (2415ms → 1889ms)
- Notice to customersThe app may take a few seconds longer to launch the first time after an update — Windows Defender is scanning the new files. From the second launch onwards, everything is normal.
0.43 — UI minimum heights, song data scroll, first-start voice prompt, Quickwin bundle (2026-04-04)
New Rule Action: Change Song Tempo (persistent)
song_tempo_changesupplements the previoustempo_change- tempo_change (renamed to "Change Today's Tempo (±%)"): current pace, not persistent
- song_tempo_change ("Change Song Tempo (±%, persistent)"): changes the song tempo and saves the value to the existing auto-save chain in the database.
- Parameter:
deltaas integer percent, Clamp 50-150%
Fault-tolerant import/migration (BL-065)
- Manual import: Per-file try/except — corrupt/unreadable files are skipped, session continues.
- CC1 migration:
shutil.copy2Each MP3 file is encapsulated, errors are logged, and a report is generated at the end. - SqView migration: same fault resilience
- Also
player._load_file()Fault-tolerant at the end of the import process — a corrupted last file no longer aborts the summary.
Folder import with subfolders (BL-032)
- New intermediate dialog "Import source": Individual files or folders (including subfolders)
- When selecting a folder, the system recursively searches for .mp3/.wav/.flac/.ogg/.aiff/.aif files.
- Thorsten's long-term feature request fulfilled
Active tab more easily identifiable (BL-060)
QTabBar::tab:selectedin all themes withfont-weight: bold- Win11: Border changed from 2px to 3px, more explicit
widget_bg-Background - Default: additional 2px top border in selection color
- Light: Bold adds to it, elegant was already bold
Import note: where the songs end up (BL-062)
- After successful import, the song list dock is automatically brought to the foreground.
- Import summary includes a new note: "The new songs have been added to the song list."„
TIC-0014: Minimum player height during app resizing
MainWindow.setMinimumSize()increased from (1100, 650) to (1100, 720)- The sum of Player (350) + Loop (240) + Title bars + Menu + Status bar now fits within the minimum height.
- The bottom row of buttons (Location, Planner, Lyrics) is no longer cut off when the main window is minimized.
Initial startup voice prompt (BL-058)
- On the very first start (no language in INI), a dialog box appears: "Start in English" / "Start in German"„
- The language is then stored in the INI file; the dialog only appears once.
UI: Minimum heights against crushing (TIC-0008, TIC-0013)
- Player buttons (Play, Pause, Stop, Fade Out, Location, Planner, Lyrics): Minimum height 34px
- Player spin boxes (tempo, pitch): minimum height 24px with labels 16px
- Total player widget height: Minimum height 350px, will be enforced again after layout restore.
- Loop widget („New Songs“): minimum height 240px, buttons 52px, fixed spacing 6px
- Prevents unreadable UI on small screens or with high DPI scaling (e.g. 1.8x)
Song Data: ScrollArea (TIC-0012)
- The Song Data widget now has a vertical scroll bar instead of being squashed when the dock is small.
- All fields remain readable regardless of the widget height.
Bugfix: "Title" column not translated (TIC-0009)
- The "Title" column in Playlist and Planner is now correctly displayed via the translation system ("Title" in English).
Bugfix: Show/Hide buttons are now true toggles (TIC-0010, TIC-0011)
_toggle_dock()Previously, only Show + raise was displayed — second click did not hide it.- The Planner and Lyrics buttons now hide their respective docks again on the second click.
- Special case of the last tab in the stack: the dock is only brought to the front, not hidden.
- Sorting pre-selection in Planner now only works when opening, not when closing.
0.42 — Rules extensions, Planner deletion, App menu & Song display without file (2026-03-28)
New Rule Actions
- Go To Position (BL-044): Jumps to the start, loop-in, loop-out, or end of the song. Position selectable via dropdown menu; uses crossfade parameters for a smooth transition.
- Toggle Loop Active (BL-045): Toggles the loop checkbox on/off — controllable via keyboard shortcut or rule
Planner: Delete entire playlist (BL-049)
- New red ✖ button above the confirmation button in Planner
- Deletes the entire playlist after the query dialog
Song data without audio file (BL-051)
- Song data and lyrics are now also displayed when no MP3/audio file is present.
- The filename field is highlighted in red as a visual indicator.
- Warning now only appears in the status bar (no more blocking popup)
- Allows manual linking of a file or viewing of migration data.
App Menu (BL-052)
- New first menu item „App“ with „Exit“ — clean closing via the menu instead of just via the X
Rules widget
- New parameter type „choice“ for dropdown selection in rule actions (e.g., GoTo position)
0.41 — Song Management, Photo Widget, RTF Cleanup & MDB Extension Tables (2026-03-27)
Delete song (BL-039)
- Songs can be deleted individually from the database.
- Security prompt with option to delete history data (play_history, song_location_stats).
- Also accessible via the Delete key in the song list.
Multi-file import with type selection
- When importing new songs, the song type is queried beforehand (Pattern / Singing / Both)
- Multiple files can be selected simultaneously (multi-file dialog)
- The selected type will be applied to all imported songs.
Photo widget (BL-041)
- New Dock widget with camera preview (QtMultimedia: QCamera + QMediaCaptureSession)
- RAM-only: Photos are only stored in memory, no file system, no database.
- Lazy init: The camera is only initialized when the dock is first visible.
- QStackedWidget for switching between camera preview and captured photo
- Rules actions: photo_capture (start camera + timer) and photo_show (90% screen)
RTF Cleanup (BL-043)
- Lyrics import: Word junk from RTF files is automatically removed (datastore, themedata, colorschememapping, xmlnstbl, latentstyles etc.)
- Whitelist approach: Only known RTF groups (fonttbl, colortbl, stylesheet) are retained.
- Up to 48% file size saved on affected files
MDB Migration: Extended Tables (BL-047)
- access-parser monkey patches for extended CC1 tables (off-by-one, row count, primary key)
- History-Based Reconstruction: If normal song fields are unreadable, songs are reconstructed from history.
- Case-insensitive fallback for table and column names (access parser returns inconsistent uppercase/lowercase results)
- Windows Console: Unicode-safe log output (ASCII instead of special characters)
Bug fixes
- SqView migration ready for larger test data
0.40 — Loop count, performance optimization & multi-start protection (2026-03-26)
Loop count / Timed loop (BL-042)
- New feature: Caller sets desired pattern duration, Caller's Caddy calculates the required number of loops.
- Two options (one more loop / one less loop) with resulting total duration
- The number of loops is displayed in the player (Loop X/N or Loop infinite).
- Singing Calls display "1" instead of an infinity symbol in the Loops column.
- Loop count per playlist entry (not per song), persisted in playlist files
- Backward-compatible playlist format: Automatically detects old and new formats.
- Double-clicking the Loops column opens the Loop Count dialog (Playlist + Planner)
Player improvements
- Song title on its own line (16px bold), info line below with timer + loop count + BPM
- Loop markers (loop-in / loop-out) are displayed as vertical lines on the position slider.
Playlist + Planner
- New column "Duration" with calculated runtime per song (taking loop count into account)
- Total duration displayed below the playlist — caller can plan their entire evening.
- Planner: Left and right areas can be resized using QSplitter.
Performance optimization (Startup −55%)
- App start: 1724ms → 780ms due to lazy initialization of Reports, Potential and Planner
- Song list: set_last_played_map now only updates the date column instead of rebuilding the table.
- Playlist duration: Negative cache + inline total (250 songs: 367ms → 5ms)
- Performance logging system:
perf_start()/perf_log()/perf_split() - Activated via INI switch
debug/performance_logging = true
Multi-start protection
- Duplicate app launches are prevented (QLocalServer/QLocalSocket)
- Error message if Caller's Caddy is already running
- Wait cursor (hourglass) during app startup
Translations
- New keys: header_duration, playlist_total, loop_count_per_loop, loop_count_before, loop_count_after, already_running
0.39 — SqView migration, song volume & improvements (2026-03-26)
SqView Migration (Beta)
- New migration path: SqView → Callers Caddy 2.0
- Reads sqview.db: Songs (Tempo, Pitch, Volume, Loops), playback history, lyrics assignments
- Auto-Detect: Music and lyrics folders are recognized from SqView-INI.
- Detailed log per song: MP3 status, lyrics, loop points, pitch, volume
- Follow-up report at the end: missing MP3s and lyrics listed
- Beta warning: "Still in the testing stage. Use at your own risk!"„
- Filename parsing: "Title-Label.mp3" is automatically split into title + label.
Song volume
- The volume field in song data is now applied to the audio engine (multiplicatively).
- Smooth ramp-up during volume changes (~50ms), no crackling or popping.
- Debounced DB save: only volume column, no lyrics reload on change
- Range limited to 0.0–1.0 (0%–100%)
Rules actions
- New feature: „Change Pitch“ (±half tones, configurable step size)
- New action: „Change Volume“ (±Factor, configurable step size)
Tutorial Menu
- New menu item „Exit all tutorials“ (counterpart to „Reset all“)
- Ends the current tutorial and marks all tutorials as completed.
Potential Widget
- FlowLayout for check buttons: Buttons have full text width, automatically wrap text when the dock is narrow.
- Double-clicking on "Empty Location" opens a location dialog with the affected location pre-selected.
Bugfix
- The P and L keys now function in the song list/playlist for type-to-search.
(were previously swallowed by the app-wide event filter, even with rules disabled) - Tempo/pitch changes no longer cause audio crackling (Debounced Save without lyrics reload)
0.38 — Lyrics redesign, tutorials & bug fixes (2026-03-25)
Lyrics widget: As-Is rendering (architectural simplification)
- Lyrics are now displayed 1:1 in their original form — just like in a browser or Word document.
- White background, regardless of the chosen theme.
- All colors (text color, background color, highlights) remain original.
- Sanitizer radically simplified: now only CSS link resolution + font size removal
- External CSS files (e.g., cuesheet2.css) are automatically inlined.
- RTF converter: Support for \highlight (background colors)
- RTF converter: Correct handling of *\background and other header groups
- New "Auto-Width" button: Scales font size to fit text within the window width.
- Auto-width is also available as a Rules action ("Lyrics Auto-Width")
Tutorials
- New Tutorial: Loop Finder (6 steps: waveform, search area, search window, analysis, results, apply)
- New Tutorial: Rules (7 steps: Rule list, New rule, Name/Active/Once, Triggers, Conditions, Actions, Import/Export)
Song restart
- Pressing the play button while a song is playing means restarting from the beginning (seek 0).
- No more Stop+Start needed, also usable via F5 rule
Bug fixes
- HTML lyrics with external CSS are now displayed correctly (TIC-0001)
- RTF lyrics with colors and highlights are displayed true to the original (TIC-0002)
- App icon in title bar and Windows taskbar (TIC-0004)
- CP1252 encoding fallback when loading playlists (utf-8 error)
Ticket system
- New ticket system under 5_Tickets/ for error reports and questions
- TICKETS.md provides an overview, with one folder per ticket containing attachments.
0.37 — Rule Engine & Automation (2026-03-24)
Rules engine (new system)
- Completely new automation system: Triggers → Conditions → Actions
- 26 triggersApp lifecycle (start, song started/paused/stopped/resumed/changed), periodic timer, keyboard (F1–F12, Space, L, P), manager closed
- 9 conditionsSong type (singing/pattern), lyrics present/not present, loop set/not present, location selected/not present, playtime exceeds threshold
- 25 actionsOpen/Close Dock/Full Screen/Focus, Load Layout, Play/Pause/Stop/Fade Out/Toggle, Auto Advance, Auto Scroll Start/Stop, Change Pace, Status Bar Message, Log Message, System Ping, Warning Background (Traffic Light), Location Dialog, Manager Toggle, Auto Loop Finder
- Conditional logic: Flexible AND/OR groups (e.g., "Singing AND lyrics present OR pattern AND loop set")
- „"Once per song" option: Rule fires a maximum of once per song.
Rule Editor (new widget)
- Dockable editor widget with split layout (rule list on the left, editor on the right)
- Search field for filtering by name or trigger
- Sortable table: Active checkbox, Name, Trigger, Source (System/User)
- Dynamic parameter input fields depending on the action/condition type
- Buttons: Add, Duplicate, Delete, Up/Down, Export, Import
System vs. User Rules
- 13 pre-installed system rules (only the active toggle can be changed, not edited):
- Singing Call → Lyrics Fullscreen with Auto-Scroll (Start + Resume)
- Singing Call Stop/Pause → Default Layout back
- Song Stop → Auto-Advance
- Manager closed → Focus on playlist
- Keyboard shortcuts: F5=Play, F6=Pause, F7=Stop, F8=Fade-Out, Space=Play/Pause, L=Location, P=Manager
- User rulesFully editable, import/export as JSON, freely sortable
Rule logging
- Own log file
rules/rules.logwith categories: TRIGGER, MATCH, NO_MATCH, ACTION, ERROR, BLOCKED - Automatic rotation at 1 MB (retains 500 lines)
- Helps diagnose why rules fire or don't fire.
Auto Loop Finder (Rule Action)
- New promotion
auto_set_best_loopAutomatically analyzes the song and sets the best 64-beat loop. - Prefers 64-beat loops, fallback to highest score
- „"Please wait" overlay during analysis (semi-transparent, disappears automatically)
- Can be triggered automatically via a rule, e.g., when a song starts?
Performance optimization
- Lazy WaveformLoop finder waveform is only loaded when visible (saves ~100-400ms when changing songs)
- Targeted song updateAfter playback, only the Last Played column is updated instead of rebuilding the entire song list (~4-22ms instead of ~400-1200ms)
Loop widget: New button layout
- All 4 buttons (Set In, Clear, Set Out, Test Loop) in one flat row
- Buttons shrink when space is limited, with automatic text wrapping.
- The player column can now be made significantly narrower.
Dock widget improvements
- Feature persistenceDocking capabilities (move/dock/close) are retained after layout restoration (Qt bug fixed)
- Smaller window sizesDocks can now be docked even when the app is not running in full screen (minimumSize fix)
Bug fixes
- Loop-GuardSnapshot values of 0.0 are correctly identified as invalid — preventing good loop values from being overwritten on closure.
- Audition/Beat SnapPlayback in Loop Finder and Beat Snap will no longer be logged in the play history.
- Close Loop Finder: Automatically stops current playback
- Resume rule: Works reliably again after layout change (Focus-Restore after restoreState)
0.36 — Loop Finder & UI Reorganization (2026-03-21)
Loop Finder (new widget)
- New dockable window „Loop Finder“ — automatically searches for suitable loop points.
- Similarity-based analysis: Compares phrases in the front and back of the song.
- 8-beat numbering: All beats are numbered 1-8, jumps only between the same beat positions.
- Downbeat detection: Prefers candidates on estimated beat 1 (kick energy heuristic)
- Chroma-based harmony score (FFT → 12 semitones, using only Scipy/NumPy)
- Adjustable comparison window: 4, 8, 16, 32 or 64 beats per ComboBox
- Adjustable search areas: 4 percentage fields (Default 7%/21%/64%/79%) with reset button
- Waveform overview with colored search areas (green = Loop-In, orange = Loop-Out)
- 4 movable handles (both sides per region adjustable via mouse)
- 7 Singing-Call segments above the waveform (Opener, 1-4, Middle Break, Closer)
- White dashed lines indicate the selected proposal in the waveform.
- Sortable results table: Click on column header to sort by Score, Beat, Time
- Audition function: Starts 5 seconds before loop-out, skips, stops 2 seconds after loop-in.
- Budget-based loop mechanism: Callback counts output samples, no stretcher access from UI thread as loop-in/loop-out to the player.
- Analysis runs in QThread (non-blocking)
- No new dependencies — everything with Scipy + NumPy
UI reorganization (loop widget)
- Loop Active → Player: Checkbox moved from the Loop widget to the player toolbar (to the right of Lyrics)
- 3-column layoutThe loop-in time and loop-out time are centered above their buttons.
- Button row: Set Loop In | Set Loop Out | Test loop next to each other
- New row of buttonsLoop Finder | Beat Snap side by side
- Fixed row height in the 3-column grid (does not stretch with larger widgets)
Loop Finder Dock
- Custom dock widget, must not dock with other widgets (Qt.NoDockWidgetArea)
- It opens via the new "Loop Finder" button in the Loop widget.
0.35 — Guided Tutorials & Improved Loop Guard (2026-03-20)
Tutorial system (13 tutorials)
- New guided tutorial system with tooltip overlays and highlight frames
- 11 Widget Tutorials: Player, Layout, Song List, Song Data, Planner, Playlist, Loop, Lyrics, Sequences, Reports, Potential
- 2 dialogue tutorials: Locations, Beat Snap
- Priority-based order: Player → Locations → Layout → Song list → … → Potential
- Automatic chaining: After completing one tutorial, the next one is offered.
- Tutorial offer can be declined: „Not now“ pauses tutorials for the session.
- Step navigation: Next, Previous, Skip + Step indicator (e.g. "3 / 5")
- Enter = Continue, Escape = Skip
Tutorial Menu
- New submenu "Tutorials" with all tutorials in priority order
- Checkmark (✓) next to completed tutorials
- „"Reset all tutorials" completely resets your progress.
- Menu selection takes precedence over automatic "next tutorial"„
- Individual tutorials can be restarted at any time via the menu.
Tutorial Architecture
- Three-component system: Transparent overlay (click-catcher) + highlight frame + tooltip popup
- Highlight and tooltip as separate tool windows (located above QDockWidgets)
- Multi-element highlighting: Frame multiple elements simultaneously (e.g., BPM field + Auto button)
- Dialogue tutorials: Custom lightweight engine for modal dialogues (LocationDialog, BeatSnapDialog)
- Special paths:
_menu_bar,_dock_XXX_titlefor menu and dock title bars - Floating dock management: Loose docks are hidden during tutorials and restored afterwards.
- Tooltip box with its own paintEvent (opaque background despite transparent overlay)
- Dedicated skin colors:
tutorial_box_bg,tutorial_box_text,tutorial_highlightin all 4 themes
Beat Snap: „Adjust“ → „Snap“
- Button label renamed from "Adjust" to "Snap" (including tooltip and status text)
Improved Loop Guard (Database)
- Enhanced protection against accidental overwriting of loop values
- New Guard 2: Detects the engine reset pattern (loop_in=0 + loop_out=song duration) and protects saved values.
- The previous guard only protected against 0.0, not against the song duration as loop_out.
Win11 Theme
- Zoom SVG icons: Stroke color changed from dark (#1b1b1b) to white (#ffffff) (better visibility on blue background)
0.34 — Keyboard Shortcuts & Elegant Gold Theme (2026-03-19)
Keyboard shortcuts (app-wide)
- L key: Opens location selection dialog (with focus on location list)
- P key: Opens/closes Planner (focusing on Pool table)
- App-wide EventFilter instead of QShortcut (also works with focused tables/lists)
- Modal dialogs automatically block shortcuts
- Text fields/SpinBoxes are recognized and not intercepted.
- Planner sorting is automatically pre-selected (recommendation for location, quality otherwise)
Elegant Gold Theme
- New theme „Elegant Gold“: Anthracite base with radiant gold (#d4a017)
- Golden title bars, buttons, active tabs, header separators and tooltips
- Deactivated elements in medium gold tone (#7a6a2e)
- Input fields and list areas with a light gold tint (#2e2a1f)
- SVG icons: Arrows and dock buttons black (#000000), magnifying glass/gear dark brown (#2a2518)
- Section-bar segments (Singing Call 1/2/3/5) in medium gold tone
Focus Management
- Startup focus on song list (prevents shortcut blockage by SpinBox)
- Floating dock activation:
activateWindow()beforesetFocus()for keyboard input - Location dialog: Focus on the list if there are existing entries, on the add button if the list is empty.
Tooltip improvements
- Location and Planner buttons display shortcut information in the tooltip (L) / (P)
0.33 — Potential Widget & Menu Redesign (2026-03-18)
Potential widget (data quality)
- New dockable window „Potential“ — shows optimization potential in the song database
- 5 checks with badge counters on the buttons:
- Singing Calls without Lyrics
- Pattern without loop markers
- Loops without BeatSnap optimization
- Locations without playback history
- Orphaned history entries (deleted locations)
- Double-clicking navigates to the affected object (song data, beat snap, location)
- „"Ignore" button: Mark individual entries as consciously accepted.
- „"Clean all": Delete orphaned history entries in batches
- Lazy loading: Data is only loaded when displayed.
- DB: New table
potential_ignored(check_type + entity_id)
Delete location
- The delete function now works correctly (previously blocked by a foreign key).
- Checkbox „Also delete history data“ in the confirmation dialog
- Without checkbox: History remains as orphaned entries (visible in the potential)
- Checkbox selected: History and stats will be completely deleted.
Menu redesign
- „"Design" renamed to "Settings" / "Settings"“
- Date format setting moved from View to Settings
- Language setting moved from Info to Settings
- „"Skin" renamed to "Theme" (menu, dialogues)
- Date format label: „DE“ changed to „EU“ (valid throughout Europe)
Default layout (3 columns)
- New 3-column layout as default on initial installation and layout reset
- Column 1: Player at the top, Loop/New at the bottom
- Column 2: Song list and playlist as tabs (song list active)
- Column 3: Lyrics, song data and sequences as tabs (Lyrics active)
- Planner, Reports, Potential hidden (can be opened via menu)
Technically
- Layout version 3 (new dock requires layout reset)
- Dock setup sequence: First split 3 columns horizontally, then split column 1 vertically.
(prevents the player from spanning the full width)
0.32 — Keyboard, File Selection & Loop Improvements (2026-03-18)
Keyboard & File Selection
- ENTER key: Load song into song list, add song from planner pool to playlist, remove song from playlist
- Function keys (F5-F8, Space) now also work with undocked windows (Application Shortcut).
- File selection button („…“) in song data: Change audio file afterwards
- If the file is already in use: Copy dialog with automatic copy creation.
- Extended audio format support: WAV, FLAC, OGG, AIFF in addition to MP3
- Audio format filter also expanded in the import dialog.
- New DB method
update_filename()with UNIQUE constraint check
Loop crossfade
- Seamless loop transition through crossfade instead of hard cut
- Crossfade duration configurable via INI
loop/crossfade_ms(Default 46ms) - Eliminates WSOLA transient artifacts at the loop point (no flush/warmup needed)
- Budget-based loop mechanism: Callback counts output samples, no stretcher access from UI thread
- Fallback protection: Feed-level loop-back if the UI timer misses the seek.
Loop offset (per song)
- Automatic offset measurement via FFT-based cross-correlation (low-pass filter <200Hz)
- Finds the optimal offset between the loop end and loop beginning in the bass range.
- Search range ±2 seconds, selects the smallest offset with good correlation (>= 0.1)
- The offset is stored in the database for each song (
loop_offset_ms) - Manual fine-tuning via SpinBox in song data (±3000ms, 0.5ms steps)
- Automatic measurement during Beat Snap and Loop tests, result in dB + SpinBox
- Database migration: New column
loop_offset_mswill be created automatically
Bug fixes
- The play position display (time + slider) no longer sticks when starting a pattern with a loop.
- Loop markers are no longer reset to 0 when changing files.
0.31 — Beat Snap Audition (2026-03-16)
- Beat Snap Dialog: Preview the loop jump with waveform visualization
- Dual waveform display (loop-out at the top, loop-in at the bottom) with cursor synchronization
- Playback sample counter (
_playback_sample) in audio engine for precise position determination - Engine loop is deactivated during audition (prevents double jumps due to feed-ahead)
- Layout versioning:
_LAYOUT_VERSIONPrevents corrupted dock states during changes - Versioned
saveState()/restoreState()— old state is automatically discarded - Bugfix: Dock widgets could no longer be snapped to the dock after switching from P30 to P31.
0.30 — BPM detection, reports, lyrics contrast (2026-03-14)
- Auto-BPM detection via comb filter bank (scipy/numpy, no new packages)
- Sub-harmony correction: Check integer multiples, prefer higher tempi.
- BPM detection runs in QThread (non-blocking).
- Reports widget: Setlist/music sequence list for GEMA with TXT export
- Bidirectional ComboBox filtering (location ↔ date)
- Lyrics contrast: WCAG-based color recognition for Word HTML (bgcolor, background, color)
- Sanitizer removes block backgrounds, retains inline highlights, and replaces poor text colors.
- The default stylesheet is updated with every skin change and when setHtml() is called.
0.29 — Release preparation (2026-03-12)
- Internationalization: i18n module with JSON translations (German/English)
- 5-level folder structure: 1_Source, 2_Test, 3_Build, 4_Release, _archive
- Build pipeline: PyInstaller-Spec + build.py (full package, update, source ZIP)
- Clean DB script: Removes user data, retains reference data (sequences, Teaching Order)
- Migration EXE: Separate Access import process
- Portable paths: App directory next to EXE instead of prototype folder
0.28 — Sequence Window + Design Menu + Audio Fix (2026-03-11)
- New dockable window „Sequences“ (Dock 9, tabbed with Lyrics)
- Import of 885 singing call sequences from Access MDB (caller.mdb)
- Cached Live Mapping against Burleson Vocabulary (Teaching Order)
- Contains filter: Autocomplete search for contained calls
- Limit filter: Only sequences up to a certain program level.
- Lazy loading (blocks of 50) for fast scrolling
- Detailed dialog with all calls and program tags
- Remapping button (gear icon) for recalculating teaching orders
- Zoom [-/+] with percentage display (like lyrics widget)
- New module: sequence_mapper.py (Burleson mapping logic)
- Database extension: sequences + sequence_calls Tables with indexes
- Design menu: Load/save/restore layout + skin switching at runtime
- Named layouts: Callers can save "Live.ini", "Workshop.ini", etc.
- Playlist Manager renamed to "Planner" (shorter, renamed everywhere)
- Caller Workflow Guidance: Location → Planner button red → Planner confirmed → Playlist focus
- Audio fix: Persistent stream (no crackling/humming at song start)
- WSOLA warmup: 200ms settling phase is output as silence
0.27 — Performance optimization (2026-03-11)
- Performance measurement framework with Phase A (Baseline) and Phase B (Stress test with 10k songs)
- Test methodology: 10 repetitions, statistics (Mean/StdDev/Min/Max), CSV export
- Pool table in the playlist manager: 40% faster through optimized table pattern
- Song list: 7% faster through the same optimization
- Insight: QTableWidget rebuild is the bottleneck, not the database or sorting.
- Optimized pattern:
setRowCount(0)+setRowCount(n)+setItem()instead ofinsertRow()
0.26 — Lyrics display (2026-03)
- Lyrics widget as a dockable window (tabbed with song data)
- Supported formats: HTML/HTM, RTF, TXT
- Auto-Fit: Font size is automatically adjusted when text fits on a page.
- Auto-scroll: Proportional to the song's progress
- Smart color cleanup: Backgrounds removed, section colors retained.
- Toolbar with auto-scroll/auto-size toggle and zoom +/-
- Light Blue Skin: Second color scheme (light surface, blue accents)
- Muted and indicator colors for better contrast in both skins
- Loop-save bug fix: Snapshot mechanism saves loop values before song changes
- Shared data folders (music/, lyrics/, playlists/) save disk space
0.21 — Playlist and Playlist Manager (2026-03)
- PlaylistWidget: Slim, tabbed next to the song list, load/save as .txt
- PlaylistManagerWidget: Two-panel view with song pool and playlist mirror
- Song transfer: Double-click, arrow buttons, drag & drop
- 4 sorting options: Alphabetical, Quality, Last played, Recommendation
- Filter: All / Pattern only / Singing only
- Auto-Advance: Next song at song end, stop or fade-out
- Fade-Out: Configurable linear volume ramp (default 3s)
- Recommendation system integrated (originally P25)
- Integrated playlist builder (originally P24)
0.20 — Playback history (2026-03)
- Three-layer architecture: play_history, song_location_stats, on-the-fly calculation
- „"Last played" column in the song list
- Location-based statistics (when and where each song was played)
- Renaming: "Club" becomes "Location" (generalized for Club + Special)
- INI setting for date format (German/American)
0.19 — Locations (2026-03)
- Club and special administration as selectable contexts
- Location selection influences song recommendations and history.
0.18 — Pattern/Singing Mode (2026-03)
- Songs can be marked as patterns, singing, or both.
- Type abbreviation (P/S/PS) in song list and pool display
- Filter by mode in the playlist manager
0.17 — Current pace (2026-03)
- Saved tempo per song for tonight
- Tempo is automatically restored when a song is loaded.
0.16 — Song list with search (2026-03)
- Song list as QTableWidget with real-time search filter
- Search by title, label, and filename
0.15 — Portable Paths (2026-03)
- Relative paths for songs and data
- The application can be moved to a USB stick or between computers.
0.14 — Auto-Save (2026-03)
- Automatic saving of all changes (song data, settings)
0.13 — Song Data Model (2026-03)
- SQLite database for songs, locations, history
- Song fields: Title, Filename, Label, Quality, Pattern/Singing, Tempo
0.07 — Dock Window System (2026-03)
- QDockWidget-based windowing system with free arrangement
- Move, dock, stack, and resize windows
- The layout is saved and restored upon restart.
- Resize rules per window type
- Integrated: P8 (Show/Hide), P9 (Move), P10 (Resize Rules), P11 (Docking), P12 (Layout Persistence)
0.06 — Loop with tempo adjustment (2026-03)
- Loop region remains stable during tempo changes
- Proprietary streaming WSOLA algorithm (no Rubber Band/SoundTouch)
0.05 — Loop In / Loop Out (2026-03)
- Markable loop region with start and end point
- Seamless loop during playback
0.04 — Tempo and pitch simultaneously (2026-03)
- Independent simultaneous tempo and pitch control
0.03 — Pitch control (2026-03)
- Change pitch continuously, independent of tempo.
0.02 — Speed control (2026-03)
- Continuously change playback speed
0.01 — MP3 playback (2026-03)
- Load and play MP3 files reliably
- Basic transport controls (Play, Pause, Stop)
- Position indicator and seek slider