Patcher: ledsaver and credit mods, beat jump needs the hot cue engine
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
bbe784aad2
commit
7dbb4ec6f8
3 files changed
+68
-14
No files matched your search
@@ -57,14 +57,17 @@ From the emulator checkout `../CDJ900NXSVirtual` (`--repo` for another place):
|
||||
| `code` | arnoldasr: BPM with two decimals, two-line phase meter, RGB waveform |
|
||||
| `utility` | arnoldasr: UTILITY > PHASE METER switch (needs `code`) |
|
||||
| `overview` | arnoldasr: overview waveform colour gradient |
|
||||
| `beatjump` | TRACK SEARCH jumps 1/2/4/8 beats, UTILITY > BEAT JUMP (known faults on a player, see Risk) |
|
||||
| `beatjump` | TRACK SEARCH jumps 1/2/4/8 beats, UTILITY > BEAT JUMP (needs `hotcuekeys`), see below |
|
||||
| `cuecolours` | memory cues in their rekordbox colours, hot cues shown |
|
||||
| `hotcuekeys` | hot cues A-E on the BEAT DIVIDE keys (needs `cuecolours`), see below |
|
||||
| `hotcuekeys` | hot cues A-C on the BEAT DIVIDE keys (needs `cuecolours`), see below |
|
||||
| `ledsaver` | UTILITY > LED ANIMATION: while the screen saver dims the display, the button LEDs and the jog's rings play a loop |
|
||||
| `credit` | the boot screen says "Pionaarr Mods by Givou" where it said "Ver 1.31" (ticked at the start, can be unticked) |
|
||||
|
||||
`hotcuekeys`: UTILITY > HOT CUE KEYS ON; then QUANTIZE pressed briefly
|
||||
switches the hot key mode (HOT KEYS box beside QUANTIZE), held it is
|
||||
QUANTIZE. In the mode the BEAT DIVIDE keys 3/4, 1/3, 1/2, 1/4, 1/8 are hot
|
||||
cues A-E:
|
||||
QUANTIZE. In the mode the BEAT DIVIDE keys 3/4, 1/3, 1/2 are hot cues A-C
|
||||
(1/4 and 1/8 do nothing and stay dark: the player has three hot cue buffers,
|
||||
one for each):
|
||||
|
||||
- press: jump to the hot cue and play (from pause too);
|
||||
- hold 0.5 s or longer, then let go: back to the hot cue, standing (gate);
|
||||
@@ -72,8 +75,36 @@ cues A-E:
|
||||
- DELETE held, a key pressed: its hot cue deleted (DELETE alone is DELETE);
|
||||
- LEDs: off without a hot cue, dim with one, two bright blinks when pressed.
|
||||
|
||||
Hot cues set or deleted live until the next track load; nothing is written
|
||||
to the USB stick. As with CALL, the CUE point moves to the hot cue.
|
||||
Hot cues set or deleted are written to the USB stick (the track's rekordbox
|
||||
analysis files, as MEMORY and DELETE keep memory cues), so they are there
|
||||
after the next load too. As with MEMORY, the player takes this only once the
|
||||
track has settled (a few seconds after loading). Hot cues A-C start at once: once a track is loaded and the
|
||||
deck stands at its CUE point for a second (in hot key mode), they are loaded
|
||||
into the player's three hot cue buffers, silently, and the deck goes back to
|
||||
its CUE point. PLAY or CUE pressed meanwhile wait for it (PLAY is played
|
||||
after). A hot cue set later loads into
|
||||
its own buffer on its first press (about a second). A hot cue played from a buffer
|
||||
leaves the CUE point where it is; one recalled without a buffer moves it, as
|
||||
CALL does.
|
||||
|
||||
`ledsaver`: UTILITY > LED ANIMATION, ON from the first start (set it to OFF
|
||||
to switch it off; the player keeps the choice). When the
|
||||
player's own screen saver dims the display (5 minutes without a track, or
|
||||
100 minutes paused), the BEAT DIVIDE keys fade in a wave down and back up,
|
||||
SYNC / MASTER and MASTER TEMPO / DISC EJECT fade in and out, CUE, PLAY, REV,
|
||||
SLIP, the SLIP LOOP bar and RELOOP/EXIT light one after another, and the
|
||||
jog's three rings light in turn from the inside out and back in. Any key ends
|
||||
it, as it ends the screen saver.
|
||||
|
||||
`beatjump`: UTILITY > BEAT JUMP (where SCREEN SAVER was) sets 1, 2, 4 or 8
|
||||
beats (OFF: TRACK SEARCH as before); TRACK SEARCH back and forward then jump
|
||||
that many beats along the track's beat grid, keeping the position within the
|
||||
beat. While playing, the jump is loaded into a buffer of the player's own
|
||||
that only beat jumps use (A-C keep theirs): there is a short silence while it loads, but the
|
||||
deck comes back in phase, as if it had played on through it (the load time is
|
||||
measured on every jump and allowed for), and the CUE point stays. Paused, it
|
||||
is a CALL (the CUE point moves with it). A press while a jump or hot cue is
|
||||
still loading is ignored.
|
||||
|
||||
arnoldasr's mods need his repository checked out in
|
||||
`../CDJ900NXSVirtual/mods/cdj900nxs/upstream` (it has no licence, so it is
|
||||
@@ -83,9 +114,11 @@ not copied here); without it they are greyed out.
|
||||
|
||||
Nothing here talks to a player; you copy the file to a FAT32 USB stick and run
|
||||
the update yourself. Our mods were developed with Claude Code in an emulator.
|
||||
On a player: `beatjump` jumped off the grid and, after a few jumps, reported a
|
||||
corrupted file and needed a restart; it is being reworked. `cuecolours` and
|
||||
earlier versions of `hotcuekeys` ran on a player. Recovery from an
|
||||
An earlier `beatjump` jumped off the grid on a player and, after a few quick
|
||||
jumps, reported a corrupted file and needed a restart; it has been rebuilt on
|
||||
the hot cue engine (no overlapping loads), which has not run on a player yet,
|
||||
nor has the hot cue engine. A jump while a loop plays ends the loop. `cuecolours` and earlier versions of `hotcuekeys`
|
||||
ran on a player. Recovery from an
|
||||
application that crashes at start-up has not been tested by anyone. Keep the
|
||||
`--stock` file at hand.
|
||||
|
||||
|
||||
+12
-5
@@ -40,10 +40,11 @@ import upd # noqa: E402
|
||||
DEFAULT_REPO = os.path.join(os.path.dirname(HERE), 'CDJ900NXSVirtual')
|
||||
UPSTREAM_MODS = ('code', 'utility', 'overview')
|
||||
NEEDS = {'utility': 'code', # the PHASE METER switch chooses the code mod's meter
|
||||
'hotcuekeys': 'cuecolours'} # the hot cues the keys play are read by cuecolours
|
||||
'hotcuekeys': 'cuecolours', # the hot cues the keys play are read by cuecolours
|
||||
'beatjump': 'hotcuekeys'} # hotcuekeys' engine makes the jumps
|
||||
LABEL = '1.32'
|
||||
# not ticked at the start of the list, and why
|
||||
KNOWN_FAULTS = {'beatjump': 'known faults on a player (jumps off the grid, "file corrupted" after a few jumps)'}
|
||||
KNOWN_FAULTS = {}
|
||||
|
||||
|
||||
def load_repo(repo):
|
||||
@@ -114,13 +115,19 @@ def _toggle(chosen, name, mods):
|
||||
"""Tick or untick one mod: ticking one ticks what it needs, unticking
|
||||
one unticks what needs it (so every mod can be unticked)."""
|
||||
if name in chosen:
|
||||
chosen.discard(name)
|
||||
chosen.difference_update(n for n, need in NEEDS.items() if need == name)
|
||||
drop = {name}
|
||||
while True:
|
||||
more = {n for n, need in NEEDS.items() if need in drop} - drop
|
||||
if not more:
|
||||
break
|
||||
drop |= more
|
||||
chosen.difference_update(drop)
|
||||
else:
|
||||
chosen.add(name)
|
||||
need = NEEDS.get(name)
|
||||
if need and any(m[0] == need and m[2] for m in mods):
|
||||
while need and any(m[0] == need and m[2] for m in mods):
|
||||
chosen.add(need)
|
||||
need = NEEDS.get(need)
|
||||
|
||||
|
||||
def choose(mods):
|
||||
|
||||
@@ -109,6 +109,10 @@ def test_every_mod_can_be_unticked():
|
||||
assert {'hotcuekeys', 'cuecolours'} <= chosen # and ticking brings what it needs
|
||||
cli._toggle(chosen, 'overview', MODS)
|
||||
assert 'overview' not in chosen
|
||||
cli._toggle(chosen, 'cuecolours', MODS)
|
||||
assert not {'cuecolours', 'hotcuekeys', 'beatjump'} & chosen # and what needs that
|
||||
cli._toggle(chosen, 'beatjump', MODS)
|
||||
assert {'beatjump', 'hotcuekeys', 'cuecolours'} <= chosen
|
||||
|
||||
|
||||
def test_disclaimer_must_be_accepted(monkeypatch):
|
||||
@@ -125,3 +129,13 @@ def test_disclaimer_without_a_terminal(monkeypatch):
|
||||
monkeypatch.setattr(cli.sys.stdin, 'isatty', lambda: False, raising=False)
|
||||
with pytest.raises(SystemExit, match='--accept'):
|
||||
cli.confirm(False)
|
||||
|
||||
|
||||
def test_credit_can_be_unticked():
|
||||
import types
|
||||
mods = cli.available(types.SimpleNamespace(MODS={"code": "c", "credit": "x"}), cli.DEFAULT_REPO)
|
||||
assert [m[0] for m in mods] == ['code', 'credit']
|
||||
chosen = {m[0] for m in mods if m[0] not in cli.KNOWN_FAULTS}
|
||||
assert 'credit' in chosen # ticked at the start
|
||||
cli._toggle(chosen, 'credit', mods)
|
||||
assert chosen == {'code'}
|
||||
Reference in new issue
Block a user