12 KiB
DJ workstation — feature/dj_workstation
The main window now opens with the original karaoke workspace above a resizable DJ workspace. The toolbar’s Show/Hide DJ button returns the entire window to karaoke without stopping any deck. Existing singer, venue, rotation, video, background music, library and recursive directory import features remain available. Background music is a compact single-row strip above karaoke transport. In split view, song settings open from the Song Settings button; karaoke-only view keeps the full settings strip. DJ controls have mirrored tone panels, consistent padding and a separate browser area; the DJ workspace scrolls vertically when the split is too short to show everything.
Using the decks
- Use the DJ browser’s Import Files / Folder button for DJ music. It has its own
DJ/Library.sqlite,DJ/Mediaand playlists under the app support folder. It starts empty; existing karaoke songs are not migrated. The tested recursive importer is reused with audio-only import, without CDG graphics. MP3, WAV, M4A, MP4/M4V/MOV audio, AIFF/AIF, CAF, FLAC and AAC extensions are accepted; decoding depends on macOS format support. Imports support progress, cancellation and duplicate detection. - Select a DJ library row and use Load A/B, use the row’s A/B buttons, or drag a DJ library song onto a deck. Loading is paused, with no brief autoplay. Finder audio files can also be dropped onto either deck. Dropping onto a playing deck asks for confirmation before importing or replacing anything; Cancel preserves playback and Replace & Load explicitly overrides protection. Library loads also respect the active-deck protection preference.
- Cyan identifies A; amber identifies B. Each platter’s angle follows actual source playback time, including tempo changes, pauses and seeks. Drag around a platter to jog two source seconds per revolution. This is seek-based jogging, not vinyl scratching.
- Waveforms come from decoded audio and reuse existing waveform caches. Click/drag to seek. A white position line and green loop region show current state.
- High/mid/low EQ and the bipolar filter are beside each platter. Gain and level knobs have been removed from the on-screen decks. Drag a knob vertically; double-click to reset. Knobs expose adjustable accessibility actions and current values. EQ uses the existing three-band filters; filter is low-pass left, bypass centre, high-pass right.
- Play/pause, stop-to-start, set/return cue and four set/jump hot cues are per deck. Right-click a hot cue to clear it. Use the cue-time editor to set an exact cue in seconds or capture the current playhead without moving playback. Manual IN/OUT loops do not need BPM. Beat loops require an estimated, entered or tapped BPM; choose 1–32 beats. Loop toggles off on a second press and continues correctly at the end of a track.
- Loading estimates BPM conservatively from up to the first 90 seconds of audio, searching 70–180 BPM; silence and steady tones remain unknown. Estimates show BPM~ and can be replaced by entering source BPM (40–240) or tapping at least three beats. Either Sync button links both decks to deck A’s effective BPM and both buttons show active. Press either again to unlink and restore both original tempos. Sync follows changes to A’s tempo; it does not align beat phase or detect a beat grid. Use the jog/nudge buttons to align beats. Tempo adjustment preserves pitch, using AVAudioUnitTimePitch.
- The crossfader and DJ output headroom affect only DJ playback. Equal-power and linear crossfader curves are selectable. The karaoke master and saved singer preferences are independent. The wing meters show individual deck peaks, not a summed master meter. There is no master limiter; use gain/levels appropriately.
- Karaoke and DJ music can play simultaneously. The existing background-to-singer interlock is preserved, but it does not automatically duck the new DJ decks.
Library and playlists
The DJ browser supports title/artist/album search and paginates in groups of 50. DJ playlists are stored independently from karaoke. Create, rename or delete them from the folder menu; right-click a song to add it to a playlist, remove it, or move it earlier/later. Karaoke library drag references are rejected by the DJ decks; import the source music using the DJ importer. DRM subscription streaming is not added.
Audio routing
The routing sheet enumerates CoreAudio output devices. Both DJ decks can route to one selected master device; karaoke can independently route to another device. Defaults use the system output. Selections are session-only. Background music retains its existing output.
Headphone preview is real, independent playback on another selected output device. It starts at the selected deck’s position with that deck’s current tempo/EQ/filter, before its gain, level and crossfader. Later deck changes are not followed; restart preview to refresh. One deck can be previewed at a time. Preview is disabled until an output is explicitly selected, and rejects the current master device to avoid sending cue audio publicly.
Not implemented: master/cue channel-pair selection on a single multichannel device, phase-locked PFL, aggregate-device creation, input/microphone routing, automatic device failover, and calibrated round-trip latency. Devices use their default stereo output pair. A Numark’s master and headphone sockets on the same CoreAudio device therefore cannot yet be independently addressed. Hardware routing needs verification on the intended interface.
Controllers
The confirmed model is Numark Mixtrack Go. Its preset was independently implemented from the protocol addresses in the supplied Mixxx mapping. Numark’s product page documents USB class compliance and Bluetooth MIDI.
In DJ Settings → MIDI, select the controller input and choose Apply Mixtrack Go Preset. The profile persists per source ID. Supported controls include transport, cue, shared Sync, deck load, 14-bit tempo, relative jog, channel faders, crossfader, master/cue volume, headphone preview, library browsing and preview, low/filter mode, and four hot-cue/loop pads with shifted clear/off actions. A standard identity request and transport, sync, cue and mode feedback are sent when a matching MIDI output is found. Deck B pad mode follows the XML address 95/00; the upstream JavaScript table contains a conflicting address.
Custom MIDI Learn remains available for note buttons and 7-bit CC controls. Select an action, click Learn Next Control, then operate the control. Learning does not trigger playback, releases are ignored, and continuous CC zero remains valid. The selected MIDI input is remembered across launches and automatically reconnected when it becomes available; choosing Not connected clears that saved selection. Presets and learned mappings remain saved per source.
Hardware limitations: no physical Mixtrack Go has been tested. LED feedback, USB/Bluetooth delivery and audio sockets need on-device verification. Its same-device master 1–2/headphones 3–4 routing is not implemented; cue currently requires a separate output device. Stems, sampler, FX pad modes, touch scratching, HID, motor feedback and controller certification are not implemented. Unsupported pad modes report their limitation rather than triggering unrelated actions.
Verification — 5 November 2026
- Debug build compiled for arm64 and x86_64 without distribution signing; the macOS XCTest suite passed 128 tests with zero failures on Apple silicon. Intel runtime playback was not exercised.
- Tests cover actual looping playback including end-of-file, editable cues, linked Sync and tempo restoration, audio-derived BPM, Finder replacement confirmation, JPG artwork, real knob double-click resets, native fader orientation/actions, preset addresses, 14-bit tempo, pad modes, MIDI releases/persistence and virtual CoreMIDI input delivery.
- Existing karaoke, recursive CDG/audio import, independent DJ library/playlists, rotation, background handoff, media-copy repair and audio processing checks passed.
- Native console and settings captures use actual NSHostingView windows. Physical controller controls, LEDs and separate physical audio outputs remain untested. Loops/jogs use seek scheduling rather than sample-accurate scratching.
Import repair and settings modal
Media imports now stream audio/CDG content into a private staging file, verify its SHA-256, and atomically rename it into place. Source permissions, ACLs and protected security-scope metadata are not copied. Failed or cancelled transfers remove staging files and never publish a partial destination. Existing empty destinations are not accepted as completed imports; retrying repairs them. Empty playback files show a reimport instruction instead of the raw AVAudioFile error.
The three zero-byte files observed in the local DJ media directory were repaired from checksum-matched originals. Their sources and library records were preserved; macOS afinfo successfully recognised all three repaired MP3s. The interrupted, unregistered item will be registered when its folder is imported again.
Studio settings open as a dedicated modal from the toolbar, sidebar or Command-comma. Song Settings also opens as a titled modal with a Done action. The deprecated AVAsset metadata read in FileTagWriter now uses asynchronous loading.
Verification includes partial-copy repair, source permission preservation, failed-verification/cancellation cleanup and readable empty-audio errors.
Continuous console and separate preferences
The deck area is now one continuous console following the supplied reference: track headers and overview waveforms above; mirrored tempo/platter/EQ/filter wings; stacked, source-timed eight-second scrolling waveforms in the centre; and a shared bottom transport strip with a centred rectangular-cap crossfader. Native vertical tempo faders have visible scale marks, keyboard/accessibility support and a tested control-to-binding action. Play, Cue, loop size, headphones and hot cues remain available. No on-screen gain or channel-level knobs are shown. Track headers show embedded artwork or a nearby JPG/JPEG/PNG, prioritising a matching track name or cover/folder/front/artwork image. Platters have a clear rotating radial marker. Musical key analysis is not implemented.
Settings now use an icon-category toolbar with separate Karaoke and DJ selectors. DJ Settings opens directly in DJ scope; Audio Routing and MIDI open the corresponding DJ categories. Karaoke device routing applies only to the singer deck. DJ General, Sound, Library, Appearance and Advanced preferences are persisted independently in DJ/DJSettings.json. Working options include paused/automatic load, active-deck protection, reset EQ/filter on load, ±8/16/50% tempo range and inversion, equal-power/linear crossfade curves, output headroom, waveform colours/window/grid, rotating marker, inactive-deck dimming, library font/row height and optional hot-cue autoplay. MIDI learning is cancelled when leaving its settings category. Singer Web is available only in Karaoke settings, with its existing server controls preserved.
No nonfunctional switches were added for DVS, booth/microphone routing, Neural Mix, automix, recording, Spotify or cloud sync. Sync uses estimated or entered/tapped BPM for tempo matching; both overview and scrolling waveforms show BPM-relative beat guides, with stronger marks every four beats. Guides begin at source time zero and are not analysed downbeats. Active loops are highlighted green with IN/OUT boundary lines in both views.
Validation: full suite 128 tests, zero failures, including preference persistence, load protection, EQ reset, cue autoplay, tempo mapping and native fader orientation/actions. Native console and settings captures were visually inspected. Temporary builds, logs and repair tools were moved outside Developer to /private/tmp.