alphatheta-connect 0.25.3 → 0.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli.js +65 -29
- package/lib/cli.js.map +1 -1
- package/lib/index.js +65 -29
- package/lib/index.js.map +1 -1
- package/lib/virtualcdj/stagehand.d.ts +13 -3
- package/package.json +3 -1
package/lib/index.js
CHANGED
|
@@ -1356,7 +1356,9 @@ async function viaLocal(local, opts) {
|
|
|
1356
1356
|
if (!orm) {
|
|
1357
1357
|
break;
|
|
1358
1358
|
}
|
|
1359
|
-
|
|
1359
|
+
// Playlist entries reference the track through trackId; entry.id is the
|
|
1360
|
+
// entry's own row id (or its index, for OneLibrary), not a track.
|
|
1361
|
+
yield orm.findTrack(entry.trackId);
|
|
1360
1362
|
}
|
|
1361
1363
|
};
|
|
1362
1364
|
const tracks = { [Symbol.asyncIterator]: iterateTracks };
|
|
@@ -3255,7 +3257,9 @@ var RekordboxAnlz = (function() {
|
|
|
3255
3257
|
this.time = this._io.readU4be();
|
|
3256
3258
|
this.loopTime = this._io.readU4be();
|
|
3257
3259
|
this.colorId = this._io.readU1();
|
|
3258
|
-
this._unnamed9 = this._io.readBytes(
|
|
3260
|
+
this._unnamed9 = this._io.readBytes(7);
|
|
3261
|
+
this.loopNumerator = this._io.readU2be();
|
|
3262
|
+
this.loopDenominator = this._io.readU2be();
|
|
3259
3263
|
if (this.lenEntry > 43) {
|
|
3260
3264
|
this.lenComment = this._io.readU4be();
|
|
3261
3265
|
}
|
|
@@ -3275,7 +3279,7 @@ var RekordboxAnlz = (function() {
|
|
|
3275
3279
|
this.colorBlue = this._io.readU1();
|
|
3276
3280
|
}
|
|
3277
3281
|
if ((this.lenEntry - this.lenComment) > 48) {
|
|
3278
|
-
this.
|
|
3282
|
+
this._unnamed18 = this._io.readBytes(((this.lenEntry - 48) - this.lenComment));
|
|
3279
3283
|
}
|
|
3280
3284
|
}
|
|
3281
3285
|
|
|
@@ -3307,6 +3311,16 @@ var RekordboxAnlz = (function() {
|
|
|
3307
3311
|
* and has been assigned a color.
|
|
3308
3312
|
*/
|
|
3309
3313
|
|
|
3314
|
+
/**
|
|
3315
|
+
* The numerator of the loop size fraction for a quantized loop,
|
|
3316
|
+
* e.g. 4 for a 4-beat loop. Zero when the loop is not quantized.
|
|
3317
|
+
*/
|
|
3318
|
+
|
|
3319
|
+
/**
|
|
3320
|
+
* The denominator of the loop size fraction for a quantized loop,
|
|
3321
|
+
* e.g. 1 for a 4-beat loop.
|
|
3322
|
+
*/
|
|
3323
|
+
|
|
3310
3324
|
/**
|
|
3311
3325
|
* The comment assigned to this cue by the DJ, if any, with a trailing NUL.
|
|
3312
3326
|
*/
|
|
@@ -5760,16 +5774,20 @@ function makeBeatGrid(data) {
|
|
|
5760
5774
|
* Fill cue and loop data from the ANLZ section
|
|
5761
5775
|
*/
|
|
5762
5776
|
function makeCueAndLoop(data) {
|
|
5763
|
-
return data.body.cues
|
|
5777
|
+
return data.body.cues
|
|
5778
|
+
.map((entry) => {
|
|
5764
5779
|
// Cues with the status 0 are likely leftovers that were removed
|
|
5765
|
-
|
|
5780
|
+
// `hotCue` is the button number (1-8, A-H); zero marks a memory cue.
|
|
5781
|
+
// `type` only says whether the entry is a cue point (1) or a loop (2).
|
|
5782
|
+
const button = entry.hotCue === 0 ? false : entry.hotCue;
|
|
5766
5783
|
const isCue = entry.type === 0x01;
|
|
5767
5784
|
const isLoop = entry.type === 0x02;
|
|
5768
5785
|
// NOTE: Unlike the remotedb, these entries are already in milliseconds.
|
|
5769
5786
|
const offset = entry.time;
|
|
5770
5787
|
const length = entry.loopTime - offset;
|
|
5771
5788
|
return (0, utils_1.makeCueLoopEntry)(isCue, isLoop, offset, length, button);
|
|
5772
|
-
})
|
|
5789
|
+
})
|
|
5790
|
+
.filter((c) => c !== null);
|
|
5773
5791
|
}
|
|
5774
5792
|
/**
|
|
5775
5793
|
* Fill waveform HD data from the ANLZ section
|
|
@@ -5805,9 +5823,13 @@ function makeExtendedCues(data) {
|
|
|
5805
5823
|
b: (_c = entry.colorBlue) !== null && _c !== void 0 ? _c : 0,
|
|
5806
5824
|
};
|
|
5807
5825
|
}
|
|
5808
|
-
// Add comment if present
|
|
5826
|
+
// Add comment if present. The tag stores it with a trailing NUL, which
|
|
5827
|
+
// is not part of what the DJ typed.
|
|
5809
5828
|
if (entry.lenComment > 0 && entry.comment) {
|
|
5810
|
-
|
|
5829
|
+
const comment = entry.comment.replace(/\0+$/, '');
|
|
5830
|
+
if (comment.length > 0) {
|
|
5831
|
+
cue.comment = comment;
|
|
5832
|
+
}
|
|
5811
5833
|
}
|
|
5812
5834
|
// Add quantized loop information if present
|
|
5813
5835
|
if (entry.loopNumerator !== undefined && entry.loopNumerator > 0) {
|
|
@@ -5873,19 +5895,24 @@ function makeSongStructure(data) {
|
|
|
5873
5895
|
},
|
|
5874
5896
|
};
|
|
5875
5897
|
const mood = (_a = moodMap[data.body.mood]) !== null && _a !== void 0 ? _a : 'high';
|
|
5876
|
-
const bank = (_b = bankMap[data.body.
|
|
5898
|
+
const bank = (_b = bankMap[data.body.bank]) !== null && _b !== void 0 ? _b : 'default';
|
|
5899
|
+
// Field names follow the Kaitai-generated object (rekordbox_anlz.ksy
|
|
5900
|
+
// `song_structure_entry`): `phraseNumber`, `beatNumber`, `fillIn`,
|
|
5901
|
+
// `fillInBeatNumber`, and `kind` is a `phrase_high` / `phrase_mid` /
|
|
5902
|
+
// `phrase_low` object whose `id` carries the raw kind value.
|
|
5877
5903
|
const phrases = data.body.entries.map((entry) => {
|
|
5878
5904
|
var _a;
|
|
5905
|
+
const kind = typeof entry.kind === 'object' ? entry.kind.id : entry.kind;
|
|
5879
5906
|
const phrase = {
|
|
5880
|
-
index: entry.
|
|
5881
|
-
beat: entry.
|
|
5882
|
-
kind
|
|
5883
|
-
phraseType: (_a = phraseTypeMap[mood][
|
|
5907
|
+
index: entry.phraseNumber,
|
|
5908
|
+
beat: entry.beatNumber,
|
|
5909
|
+
kind,
|
|
5910
|
+
phraseType: (_a = phraseTypeMap[mood][kind]) !== null && _a !== void 0 ? _a : 'Unknown',
|
|
5884
5911
|
};
|
|
5885
5912
|
// Add fill-in information if present
|
|
5886
|
-
if (entry.
|
|
5887
|
-
phrase.fill = entry.
|
|
5888
|
-
phrase.fillBeat = entry.
|
|
5913
|
+
if (entry.fillIn > 0) {
|
|
5914
|
+
phrase.fill = entry.fillIn;
|
|
5915
|
+
phrase.fillBeat = entry.fillInBeatNumber;
|
|
5889
5916
|
}
|
|
5890
5917
|
return phrase;
|
|
5891
5918
|
});
|
|
@@ -7187,7 +7214,12 @@ class ProlinkNetwork {
|
|
|
7187
7214
|
}
|
|
7188
7215
|
const tx = Telemetry.startTransaction({ name: 'connect' });
|
|
7189
7216
|
const connectMethod = (_a = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").connectMethod) !== null && _a !== void 0 ? _a : 'active';
|
|
7217
|
+
// Pick the device number once and keep it. A CDJ-3000 that already holds
|
|
7218
|
+
// a record for our IP ignores a re-claim under a different number, so a
|
|
7219
|
+
// disconnect/connect cycle must present the same identity (see
|
|
7220
|
+
// getStagehandMac).
|
|
7190
7221
|
const vcdjId = (_b = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").vcdjId) !== null && _b !== void 0 ? _b : (connectMethod === 'stagehand' ? (0, virtualcdj_1.generateStagehandDeviceId)() : constants_1.DEFAULT_VCDJ_ID);
|
|
7222
|
+
__classPrivateFieldGet(this, _ProlinkNetwork_config, "f").vcdjId = vcdjId;
|
|
7191
7223
|
const vcdjName = (_c = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").vcdjName) !== null && _c !== void 0 ? _c : (connectMethod === 'stagehand' ? 'Stagehand' : undefined);
|
|
7192
7224
|
// Create VCDJ or Stagehand device
|
|
7193
7225
|
const vcdj = connectMethod === 'stagehand'
|
|
@@ -14146,7 +14178,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
14146
14178
|
var _StagehandAnnouncer_instances, _StagehandAnnouncer_announceSocket, _StagehandAnnouncer_vcdj, _StagehandAnnouncer_intervalHandle, _StagehandAnnouncer_currentStage, _StagehandAnnouncer_stageCounter, _StagehandAnnouncer_iface, _StagehandAnnouncer_logger, _StagehandAnnouncer_onStartupComplete, _StagehandAnnouncer_mac, _StagehandAnnouncer_startStartup, _StagehandAnnouncer_sendPacket, _StagehandAnnouncer_sendStagePackets, _StagehandAnnouncer_advanceStage, _StagehandAnnouncer_startKeepAlive;
|
|
14147
14179
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
14148
14180
|
exports.StagehandAnnouncer = exports.getVirtualStagehand = exports.StagehandStartupStage = exports.STAGEHAND_KEEP_ALIVE_INTERVAL = exports.STAGEHAND_STARTUP_INTERVAL = void 0;
|
|
14149
|
-
exports.
|
|
14181
|
+
exports.getStagehandMac = getStagehandMac;
|
|
14150
14182
|
exports.generateStagehandDeviceId = generateStagehandDeviceId;
|
|
14151
14183
|
exports.makeStagehand0aPacket = makeStagehand0aPacket;
|
|
14152
14184
|
exports.makeStagehand02Packet = makeStagehand02Packet;
|
|
@@ -14165,17 +14197,21 @@ var StagehandStartupStage;
|
|
|
14165
14197
|
StagehandStartupStage[StagehandStartupStage["KeepAlive"] = 6] = "KeepAlive";
|
|
14166
14198
|
})(StagehandStartupStage || (exports.StagehandStartupStage = StagehandStartupStage = {}));
|
|
14167
14199
|
/**
|
|
14168
|
-
*
|
|
14200
|
+
* The protocol-layer MAC a Stagehand device embeds in its 0x02 claim and 0x06
|
|
14201
|
+
* keep-alive: the AlphaTheta OUI (c8:3d:fc) followed by the low three bytes of
|
|
14202
|
+
* the interface's own MAC.
|
|
14203
|
+
*
|
|
14204
|
+
* This must stay stable for the life of the host. A CDJ-3000 records a peer by
|
|
14205
|
+
* the identity in its claim, and once it holds a record for our IP it ignores
|
|
14206
|
+
* later claims from the same IP that carry a different MAC or device number:
|
|
14207
|
+
* the new peer never receives the unicast status/position stream. Observed on
|
|
14208
|
+
* emulated CDJ-3000 firmware 3.20: a freshly randomized identity on every
|
|
14209
|
+
* connect() was served once and then never again until the player rebooted,
|
|
14210
|
+
* while the previously registered identity kept being served immediately.
|
|
14169
14211
|
*/
|
|
14170
|
-
function
|
|
14171
|
-
const
|
|
14172
|
-
|
|
14173
|
-
mac[1] = 0x3d;
|
|
14174
|
-
mac[2] = 0xfc;
|
|
14175
|
-
mac[3] = Math.floor(Math.random() * 256);
|
|
14176
|
-
mac[4] = Math.floor(Math.random() * 256);
|
|
14177
|
-
mac[5] = Math.floor(Math.random() * 256);
|
|
14178
|
-
return mac;
|
|
14212
|
+
function getStagehandMac(iface) {
|
|
14213
|
+
const ifaceMac = iface.mac.split(':').map(s => parseInt(s, 16));
|
|
14214
|
+
return Uint8Array.from([0xc8, 0x3d, 0xfc, ...ifaceMac.slice(3, 6)]);
|
|
14179
14215
|
}
|
|
14180
14216
|
/**
|
|
14181
14217
|
* Generates a random Stagehand device ID in the observed range of 141 to 211.
|
|
@@ -14189,9 +14225,9 @@ function generateStagehandDeviceId() {
|
|
|
14189
14225
|
* @param iface - The network interface to use
|
|
14190
14226
|
* @param id - The device ID to use (defaults to random Stagehand ID)
|
|
14191
14227
|
* @param name - The device name (defaults to 'Stagehand')
|
|
14192
|
-
* @param macAddr - The
|
|
14228
|
+
* @param macAddr - The protocol-layer MAC (defaults to one derived from iface)
|
|
14193
14229
|
*/
|
|
14194
|
-
const getVirtualStagehand = (iface, id = generateStagehandDeviceId(), name = 'Stagehand', macAddr =
|
|
14230
|
+
const getVirtualStagehand = (iface, id = generateStagehandDeviceId(), name = 'Stagehand', macAddr = getStagehandMac(iface)) => ({
|
|
14195
14231
|
id,
|
|
14196
14232
|
name,
|
|
14197
14233
|
type: types_1.DeviceType.Stagehand,
|