25 KiB
KJMix Pro 0.6.9 — karaoke hosting studio
Open KJMix Pro.xcodeproj, choose the shared KJMix Pro scheme and My Mac, then Run. The project contains a real project.pbxproj, SwiftUI macOS app, SQLite library, XCTest target, complete icon assets and build/test/release scripts. No project generator or third-party package is required.
DJ workstation branch
feature/dj_workstation adds the split karaoke/DJ workspace, cyan/amber two-deck controls, rotating jog platters, decoded waveforms, EQ/filter/gain, transport/cues/loops, tempo matching, crossfader, independent DJ library/imports/playlists, device routing and MIDI learn. See DJ workstation usage and limits, especially independent headphone preview, manual BPM sync and unverified controller hardware.
Feature status
| Feature | This build |
|---|---|
| Individual singer pitch, tempo and ratings | Saved per singer/song, shared across that singer's venues; automatic save in library and playback settings |
| Singer rotation | Automatic round-robin from pending requests, persistent per-venue Here roster/order/cursor, upcoming preview |
| Manual rotation | Ordered venue queue, multiple performances per singer, reassignment, reorder/remove, unassigned filler/slides |
| Singer web server | Opt-in local HTTP songbook; per-singer invitations, catalogue search, Tonight ordering, favourites, repertoire/history, saved tuning/ratings |
| Fade-out | Automatic timed fade at song endings and manual Fade Out & Stop; audio and shared video fade together |
| ShowScreen Songs | Create/edit timed text slides, colour themes/placeholders; show now, queue, or insert automatically between performances |
| Playlists | Create/rename/delete, add/remove songs, search, sort by title/artist/album/time/rating, save order and sort preference |
| Batch metadata | Multi-select, checked-field changes, find/replace, preview, atomic database updates; optional backed-up file tag writing |
| Online metadata | User-initiated Apple catalogue suggestions, reviewed before applying; recording search rather than CD-disc/fingerprint identification |
| Music stores | All four requested provider profiles, configurable websites/search links, imported JSON catalogue search/sort and browser links |
| Direct store purchasing, subscription playback, DRM cache and purchase-history sync | Not implemented. Requires provider partner integration documentation/SDKs and application credentials. Website links/catalogue import are not full store integration. |
This is not complete kJams parity. Remaining limits are listed below; there is no YouTube integration.
Venue → singer → song
- Create a venue with File → New Venue or the + beside Current venue. The active venue is remembered. A singer can belong to multiple venues.
- New Singer + Songs lets you choose a venue and initial songs together. The singer is marked Here and those songs go directly into Tonight and the pending rotation. Manage Venue Singers adds/removes existing singers from that venue; it does not delete their other memberships or repertoire.
- Expand a singer in the native sidebar to open Tonight, Favourites, History or All Songs. Use their + menu, Add Songs picker, library context menu, or a library drag handle to assign songs.
- Tonight is a persistent request list per singer/venue. Adding a song also creates one pending performance if needed. Playback consumes that performance but keeps the Tonight request. Use Queue Again to schedule another performance. Reordering played requests does not requeue them.
- Drag from the library grip beside the song ID onto a singer or Tonight. Reorder Tonight with row drops or arrow buttons. Cross-singer drops copy the request. Media paths are not exported; stale/foreign session references are rejected.
- Gold favourites and repertoire follow the singer across venues. History records performance starts, not completed songs.
Individual settings
Select a singer, then edit key/tempo/rating in the library or lower settings strip. Changes save immediately for that singer and song. Selecting another singer recalls their independent settings. Tuning applies live only if that same singer/song is playing. With Singer set to None, key/tempo are song defaults and stars are the library rating. Song Info and batch metadata ratings are explicitly library ratings, not personal ratings. The actual playing singer remains associated with playback even while you browse another singer.
EQ, filter, bypass and master volume remain global, never song/singer preferences. They are saved across launches in GlobalMixer.json. HIGH/MID/LOW, filter, output meters and master fader are available in Mixer. The waveform represents source audio before processing; boosts can clip.
Automatic and manual rotation
Open Rotation. Choose Automatic · Round Robin and mark participating singers Here. Reorder their roster by dragging or using Earlier/Later in the context menu. Each marked singer takes one turn per cycle; an empty singer keeps their roster position and is skipped until they have pending requests. The last singer called is remembered at each venue. New arrivals join the end; a singer marked away and then Here rejoins at the end. Reset Round starts from the top.
The preview is computed from pending queue entries, not the persistent already-played portion of Tonight. For four A requests and two B requests the order is A-B-A-B-A-A. Play Next and automatic advancement use this computed order. Unassigned filler entries follow the singer rounds. Unmarked singers are excluded from automatic playback.
Choose Manual to play the queue exactly as arranged. In Queue, move/remove performances and assign a singer or No singer / Filler. Multiple performances per singer are allowed. Changing a queue assignment does not remove another singer's saved Tonight list. Existing queue data survives mode changes; the automatic preview never destructively rewrites the manual queue.
Auto play next is controlled in Queue. Repeat takes precedence. Open ShowScreens to create a slide, then choose it under Rotation → Between singers to insert it during automatic advancement. The timed slide finishes before the next performance starts.
Fade-out and slides
Rotation includes Fade song endings and a 1–15 second fade duration. The ending fade uses source time adjusted for playback tempo; it is not a silence detector. Fade Out & Stop also works manually from Rotation, the transport stop button, or Command-period. This changes a temporary playback gain and shared video opacity, preserving saved master/EQ. Loading another track cancels a pending fade. Seeking cancels a manual fade.
ShowScreens have a title, body, footer, indigo/teal/rose theme and 3–300 second duration. Placeholders are {venue}, {singer}, {next}, and {song}. Output is a shared 1920×1080 image used by both monitors. Slides can play now, as unassigned manual queue entries, or between singers; pause/seek/repeat apply. These are text slides, not a general video/animation slide editor.
Singer Web
Choose a current venue, then Singer Web → Start Server. Port defaults to 8080; a port from 1024–65535 can be entered before starting. The server is off by default and does not start automatically on launch.
Use the displayed local IPv4 address or enter this Mac's reachable hostname/IP and port. The Mac and phones must share a reachable network, and macOS/firewall must permit the app's incoming connections. Copy Invitation for each singer and give that singer the link. The token is in the URL fragment rather than an HTTP query; the page clears it from the visible URL and stores it in that browser tab's session storage. Revoke disables a singer's invitation; copying a new one after revocation creates a new token. Switching venue makes invitations for other venues inactive.
The responsive page provides catalogue search, Tonight add/remove/up/down ordering, favourites, repertoire/history and individual key/tempo/rating controls. Each API request is authenticated to its singer/venue; a supplied different singer ID cannot redirect an action. No audio, filesystem paths, host controls or other singers' history are served. Catalogue results are paged in groups of 50.
This is local HTTP, not a public Internet/TLS hosting service. Invitations grant control of that singer's lists; keep them private. There is no kJams Cue protocol compatibility, public account registration, QR code, Bonjour discovery or remote audio streaming. The host must leave the app running and explicitly start the server. Transport bounds include 16 KB request bodies, 8 KB headers, connection deadlines and concurrency/rate limits.
Search, sorting and playlists
Native library columns sort and resize; horizontal scrolling exposes columns in small windows. Toolbar search supports multiple AND terms, comma/space separation, quoted phrases, title:/s:, artist:/a:, album:, label:, id:, rating:, and = exact matching. A digits-only search matches song ID. Examples: beat love me, artist:beat title:"love me", album:="Live, Now". These are the supported fields, not every kJams query operator.
Playlists have their own create/rename/delete controls and Add Songs picker. Toolbar search filters the active playlist. Choose Saved Order, Title, Artist, Album, Duration or Rating, with ascending/descending order. Sort preferences persist per playlist. Saved order arrows are enabled when no search is active; changing a display sort does not destroy saved order. Add songs from the library context menu too. Continuous show playback uses the venue queue.
Metadata and file tags
Song Info (Command-I) edits title, artist, album, label and library rating in SQLite. Library edits are protected from being overwritten by later imports.
Command/Shift-select library rows, then choose Edit N Songs in the status bar or Batch Edit Selected in the lower-right menu. Only checked fields are changed; unchecked fields remain untouched. Find/replace is case-insensitive and operates on a chosen text field. Review the preview, then apply. Database updates are atomic and reject invalid/empty titles before committing. Singer preferences are separate.
Write File Tags is a separate, explicit action in that menu/context menu. It copies originals into TagBackups/, writes a temporary file beside the original, and replaces the original after success. Stop selected playback before writing. MP3 ID3v2.3/v2.4 title/artist/album/publisher tags are supported; unrelated supported frames and audio bytes are retained. Unsupported/extended/unsynchronised ID3 layouts fail without replacing originals. M4A/MP4/M4V/MOV use AVFoundation passthrough export; unsupported containers fail safely. WAV and other formats retain library metadata only. File tag writing does not export personal ratings or rewrite CDG lyrics. Backups are retained; there is no one-click restore UI. Batch file writes are per-file, with successes and issues reported, rather than one all-or-nothing filesystem transaction.
Find Metadata Online searches Apple's public music catalogue for suggestions. Review the recording/version and use the desired result to update library title/artist/album. It does not purchase music, download samples, identify karaoke discs/fingerprints, or silently overwrite files. Requests are paced at least 3.1 seconds apart and cached during the app session; network errors are shown. No Freedb, Gracenote or paid karaoke metadata accounts are integrated.
All music-store profiles
Party Tyme Downloads, Party Tyme Pro Streaming, KaraokeCloud and KaraokeCloud Pro profiles are added once for existing/new libraries. Edits and deletions are respected; Add All Provider Profiles restores missing profiles. Custom stores and optional {query} website search templates remain supported.
Catalogue… supports local JSON import/reload, saved catalogue browsing, search/sort, format/price text and optional provider website/preview links in the browser. Fixtures/StoreCatalogue.example.json documents the format using a clearly labelled original example. It is not a downloaded real provider catalogue. Imports require unique IDs, valid HTTP/HTTPS links without credentials, at most 25,000 entries and 10 MB. Purchased DRM-free media can be imported or indexed from a download folder using the normal library tools.
Full provider integration remains outstanding. Direct catalogue/account APIs, one-click purchases, subscription playback, provider DRM/licensed offline cache and purchase-history synchronisation require partner documentation/SDKs and KJMix Pro application credentials for each service. No fake connected/streaming/purchase controls are included, and account passwords/payment details are not collected by KJMix Pro. A consumer subscription alone does not supply an application integration.
Local playback, waveform and external drives
Import MP3/WAV/M4A, same-basename CDG pairs, MP3+G ZIPs or MP4/M4V/MOV with macOS-decodable audio/video. Choose files or a top-level folder in either Import picker; folders are scanned recursively, including nested ZIPs. Keep MP3 and CDG together in the same folder (matching is case-insensitive). Overlapping folder/file selections are checked once. Hidden items, packages, symlinks and the active managed media folder are skipped during folder scans. Scanning and importing run in the background with progress and cancellation. An unreadable input or invalid archive stops the job with an error; completed imports remain saved for a retry. Direct imports copy managed media; registered locations reference regular files in place. Exact content of the same extension is deduplicated. ZIP entries are validated against traversal/symlinks and extracted media is copied for playback.
Library Locations recursively scans mounted drives/folders, indexes supported media and prepares cached 4096-bin RMS/frequency waveforms in the background. Cancel keeps completed work. Rescan reuses unchanged entries/caches; Rebuild Waveforms forces analysis. Offline sources retain their catalogue; removing a location keeps songs/media. Reconnect the drive to play referenced files. Results refresh at completion; there is no filesystem watcher/scheduled rescan.
Waveforms use source bass/mid/treble energy for RGB colours. Hover for exact time, click/drag to scrub, and zoom 1×–32× for precision. Re-analyse is in the waveform menu. Cache keys use source path, size, modification time and analyser version; bad/changed caches rebuild. Background analysis has its own reader and cannot replace a newer track's result.
The sidebar monitor stays fixed while navigation scrolls. It and the separate Video window share one published CDG/video/slide frame. Local MP4 video is muted and follows the processed audio clock with drift correction; its sound uses the global mixer and independent pitch/tempo engine. The app has one main UI window and optional Video output, with no New Window command. There is no YouTube support.
Storage, tests and release
Data stays under ~/Library/Application Support/KJamsClone/ for continuity. Back up the entire folder: Library.sqlite and its WAL files while running, Media, Waveforms, GlobalMixer.json, StudioSettings.json and TagBackups. Stop the app before copying for a consistent backup. Paths are absolute. Existing libraries migrate additively to schema 9. Host rotation settings, slide definitions, invitations, provider profiles and imported catalogue data live in SQLite. Invitation tokens and user data are excluded from source/app ZIPs.
./scripts/build.sh
./scripts/test.sh
./scripts/release.sh
Release output: only the current branded DMG in dist. Verification reports and the checksum are stored under build-release/release-verification. Normal ./scripts/release.sh requires Developer ID signing and a saved notarization profile, notarizes/staples both app and DMG, and requires Gatekeeper checks before publishing the final files. Run ./scripts/setup-notarization.sh once in Terminal to save the default KJMixPro profile. For a deliberately unnotarized local build use ./scripts/release.sh --signed-only; --unsigned creates an unsigned preview DMG. See release setup. The approved icon, complete AppIcon set, high-resolution master and original generation prompt are included under Brand/assets. Bundle/module identifiers remain compatible internally; displayed branding is KJMix Pro.
73 XCTest cases passed, including real loopback HTTP, access isolation/revocation, rotation, independent singer settings, fades, timed slides, batch atomicity, search, MP3/MP4 tag backup/media preservation and all earlier library/playback/waveform/venue/drop regressions. Release builds arm64 and x86_64, tested on Apple Silicon macOS 27.2 with Xcode 27.2/Swift 6.4.2. Deployment target macOS 13; this Xcode's XCTest runtime may require macOS 14+. Intel/older macOS execution is untested. See docs/VERIFICATION.md.
Original test media: TestTrack.zip/MP3/CDG (20-second synthetic melody and original highlighted lyrics), Demo.* (four-second tone), VideoDemo.mp4 (original colour/motion pattern with synthetic sound). There are no vocals or commercial songs in the distribution. Unsafe.zip is deliberately invalid for tests. Generating test media needs ffmpeg; app playback does not.
Remaining limits
No full commercial-store APIs/DRM, CD ripping/burning/disc lookup, vocal-channel routing/removal, crossfade, automatic BPM/key analysis, CDG parity correction/channel selection, or complete kJams compatibility. ShowScreens are static text slides. The server is local HTTP and lacks public Internet account hosting. Native mouse/touch/keyboard flows, hardware display latency, broad commercial-media conformance, large-library/live-show stress, older macOS and Intel execution are not exhaustively validated.
Direct imports run on a background worker; large/backward CDG seeks use cancellable background decoding and sparse checkpoints; there is no archive expansion quota. A multi-file direct import is not one filesystem/database transaction and can leave orphan copied media on failure. File tag support is limited as described above. Some AVFoundation metadata/export accessors compile with deprecation warnings. The app is not sandboxed. Design follows native macOS conventions but is not Apple-certified.
References: Rotation, Manual rotation, Singer server, Music stores, Apple Search API, CD+G Revealed. Implementation and bundled test media are original.
Studio deck and background music (0.6.0)
Singer chevrons are separate click targets; expansion survives navigation. Preferences are cached in bulk and library sorting is reused between sections. Rotation has an on-stage card, upcoming queue, attendance roster, New/Existing Singer menu, per-singer Add Songs buttons, and Tonight search with Queued / Queue Again status. Adding to Tonight marks the singer Here; drag from library to a rotation singer also adds a request.
Choose a background audio file in the bottom strip. Auto starts it between singers, pauses it before singer audio starts, and resumes it after a singer finishes, stops or pauses. Immediate next-singer playback takes priority, with a short handoff delay to avoid a background burst. Manual background Pause/Stop turns Auto off; enable Auto to restore automatic handoffs. A restored track does not autoplay at launch. Background loops and trim are configurable; EQ and master remain global.
The waveform deck offers play/pause, stop with track retained, jog, Option-scroll jog, cue, four hot cues, A/B loop and fade/unload. Cues and loops last for the loaded deck session. There is no beat sync or vinyl scratching DSP. Settings (sidebar, gear or Command-comma) configures playback, jog, graphics offset, hosting, background and default server port. StudioSettings.json stores these options. Minimum main window: 1060 × 760; default: 1320 × 900.
Rotation controls (0.6.1)
Use Start Rotation to begin continuous playback or resume the current rotation performance; Pause, Stop and Next Singer are beside it. Starting enables Auto advance. Stop rewinds the current performance and turns automatic advancement off; Start can play it again. An empty/away roster produces an explanation rather than silently doing nothing.
Reorder singers with the dedicated grip or visible up/down arrows. Singer drops and library-song drops share a single validated dispatcher, so a singer drag cannot be consumed by the song-assignment target. Reordering saves the venue roster and resets the round cursor so Upcoming reflects the chosen order; in Manual Queue it also groups pending performances in the singer order while preserving each singer’s request order.
Click Songs beside a singer or Add Songs to open the inline searchable browser. Choose a singer and click Add to Tonight; this also marks them Here and creates a pending request. Switch back to Upcoming to see the performance order. Both views have their own scrolling space at the minimum window size. Dragging a song onto a singer adds it to that singer’s Tonight.
Background music now has an elapsed/total time seek slider in the bottom strip. Scrub while playing to audition a point, or while paused to choose where the next Play resumes. Seeking while paused for a singer does not start background audio. The selected position lasts for the loaded track session; Stop rewinds it and track reload starts at zero.
Background fade times are available in Settings → Background Music: separate Fade in and Fade out sliders (0–15 seconds, saved automatically). Zero disables the fade. Background Play fades in; background Pause/Stop fades out. Singer start fades background out first, then begins singer audio after it reaches silence. Scrubbing cancels an active fade; paused scrubbing stays silent.
In 0.6.3 the configured background Fade out also applies when starting/resuming a singer. The deck shows “Fading background…” during the wait; singer audio and its source clock start only after the fade. Pause, Stop, seek or replacing the loaded track cancels a pending singer start. A zero-second Fade out retains an immediate handoff.
Prepare waveforms for library tracks (0.6.4)
Click Waveforms in the toolbar or bottom status bar. Generate for the loaded track, one selected library track, all selected tracks (Command/Shift-select), or every track in the library, including tracks hidden by search. Right-click a track or selection for the same generation actions.
Generate reuses valid saved waveforms. Regenerate forces fresh analysis and replaces the saved waveform. Work runs on a background worker without starting/stopping music, importing media or changing singer lists. Progress shows completed/generated/reused counts and read issues; Cancel retains completed caches. Details lists up to 100 file issues. ShowScreen slides are skipped, and disconnected drives/read failures are reported while the remaining tracks continue. Reconnect unavailable drives before retrying. Existing location scans and batch waveform jobs run one at a time; the playing track’s display refreshes from its updated cache.
Import from an SMB/NAS server
Open the Import Music toolbar menu → Import from SMB/NAS. Enter smb://server/share, click Connect in Finder, and complete macOS sign-in. Click Choose Server Folder and select the connected share under Locations. Imports copy supported files recursively into the configured managed media folder, using the normal duplicate checks, MP3/CDG pairing, progress and cancellation. Already connected shares can be selected without reconnecting. Keep the share connected until import finishes; connection or read errors stop the job and retain completed tracks. Reconnect and retry to skip completed imports. Credentials are handled by macOS, not saved by KJMix Pro.
Reinterpret Names
Select songs and use Advanced → Reinterpret Names… to split combined names using templates such as L-T - R - S. Preview album, track, artist, title and rendition before applying; save custom templates and undo completed batches. Playlists provide selection/visible-song actions and stable Saved Order (PLI) or Song ID sorting.
See the Reinterpret Names guide for folder templates, repeated fields, dash handling and original filename recovery for older imports.
Live tuning and library pages
Key and Tempo controls beside the main transport adjust the loaded performance immediately. Changes save to the performing singer and song, even while browsing another singer or track. With no assigned performer, live changes are temporary. The library shows 20 songs per page; search and sorting cover the entire library, and Next Song can cross page boundaries.
Optional DJ console development
The pending DJSystem / DJConsole integration is retained behind KJMIX_DJ_CONSOLE. Default Debug and Release builds compile the working karaoke interface. Add the missing console implementation to the target before enabling that Active Compilation Condition.