KJamsClone — initial macOS implementation, v0.1.0
This is a real Xcode application project, not a Swift Package renamed as one. Open KJamsClone.xcodeproj. Its required project file is KJamsClone.xcodeproj/project.pbxproj. No version-control restoration, project generator, third-party packages, or network downloads are needed.
Start
- Extract the whole source ZIP to a writable folder. Do not open the project from inside the archive.
- Open
KJamsClone/KJamsClone.xcodeprojin Xcode, select the KJamsClone scheme and My Mac, then Run. - Click the + import button and select
Fixtures/Demo.zipfor an original four-second tone and animated tile demonstration. This is a decoder demonstration, not a song with lyrics. - Double-click the imported song. Use the eye button to open the Video window, then move it onto another monitor or use macOS's window fullscreen control.
- Double-click a library row to play it; the large Play/Pause button resumes or pauses the current track. The smaller transport buttons seek back/forward ten seconds and play the next song. The volume slider and repeat button control actual playback. Use the + button to import and the eye button to open the Video window.
- Import your own
.mp3and matching.cdgfiles, or a ZIP containing those files. Names must match, ignoring case, in the same folder. Select the audio file; its sibling CDG is found automatically. Audio-only MP3/WAV/M4A and WAV+G are also accepted.
App deployment target: macOS 13+. Verified here with Xcode 27.2 on Apple Silicon macOS 27.2; older systems and Intel execution have not been tested. The build produces arm64 and x86_64 slices. XCTest execution with this Xcode may require macOS 14+.
Implemented
| Feature | Scope |
|---|---|
| macOS app | Screenshot-inspired charcoal/silver controls, navy source sidebar and library grid, blue status capsule, library/search, rating menu, separate Video window |
| MP3+G | AVAudioPlayer master clock; CDG packets decoded at 300 packets/sec; play, pause, resume, stop, seek, volume and repeat |
| CDG | Memory/border preset, normal/XOR tiles, low/high palette, scroll preset/copy with fine offsets, transparent color; 288×192 cropped graphics |
| ZIP import | Automatic extraction and pairing, nested folders, traversal/symlink rejection; system /usr/bin/unzip |
| Library | SQLite persistence, copied media, SHA-256 audio-content deduplication for the same extension, search by filename title |
| Ratings | Persistent per-song 0–5 stars |
| Singers / venues | Create, list, select; persistent SQLite records |
| Play history | Song/singer/venue/timestamp stored on each new song start; play counts shown |
| Tests | Eight XCTest cases covering decoder behavior, backward seeking, SQLite reopening, ratings, play counts, pair/dedup import, ZIP import/rejection, real MP3 loading/pause/seeking |
| Scripts | Debug build, tests, unsigned Release app ZIP |
Library and copied media are stored under ~/Library/Application Support/KJamsClone/.
Imported source files remain untouched. Back up that entire folder together; paths are absolute.
No music catalogue or copyrighted songs are included. Demo tone/graphics are original and may be used freely.
Incomplete / unverified
This is not a complete kJams replacement or production-qualified release. There is no singer rotation queue, playlist management, history browser, singer/venue editing or deletion, per-singer ratings/preferences, pitch/tempo adjustment, crossfade, key detection, metadata tag parsing, physical CD ripping, or standalone CDG-only playback. Titles come from filenames. The rating is global per song. Play counts count playback starts, not completed performances.
Synthetic fixtures and automated MP3 checks passed; real commercial karaoke collections, long performances, audible output quality, visual lyric accuracy, external monitors, and full UI interactions have not been manually validated. The decoder ignores parity/error correction, unsupported instructions and channel selection; all tile channels are combined. CDG has no adjustable synchronization offset. Backward seeking rebuilds graphics from packet zero on the main thread. Large imports also run on the main thread, without progress/cancel controls or archive expansion limits; use trusted, reasonably sized archives. Importing multiple files is not one database/filesystem transaction. A failed import may leave copied media to clean up. The app is intentionally not sandboxed, signed for distribution, or notarized. It has the default macOS application icon.
Build, test, release
Run from this extracted project folder:
./scripts/build.sh
./scripts/test.sh
./scripts/release.sh
Scripts work from any working directory and stop on failure. Build products go under build/ and build-release/; release output is dist/KJamsClone-unsigned-macOS.zip. Release builds disable signing. Developer ID signing and Apple notarization must be added before distributing the app to other users. The source ZIP contains neither personal media nor your library database.
VERIFICATION.md records the checks performed on this delivery. verification/ contains the corresponding build/test excerpts.
Implementation reference
CDG packet layout and commands were implemented using Jim Bumgardner's CD+G Revealed as a format reference. The implementation is original Swift code; no third-party player source is bundled.
Screenshot-inspired interface
The interface follows the supplied reference: charcoal frame, silver transport controls, blue status capsule, navy panes, compact column headings, source selection and bottom song count. Library, Singers and Venues are functional sources. Third-party music stores and playlists from the reference are not implemented. Artist, Album, Key Adjust and Tempo columns show dashes because those features are not available; the Label column identifies the imported format. Rating menus persist changes. The separate Video window remains black when no graphics are loaded.
Single main window and adding people / places
The app uses a single main library window; the File menu has no New Window command. The optional Video display remains separate for karaoke output.
Choose File → New Singer… or File → New Venue…, enter a name, then click Add. You can also use New Singer… / New Venue… at the top of the matching source pane, or the + button beside the singer/venue selector. New entries save to SQLite, appear immediately, and become selected for subsequent playback. Empty names are rejected, and adding an existing name selects its existing record.