alphatheta-connect 0.19.2 → 0.21.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/README.md +6 -0
- package/lib/artwork/parsers/index.d.ts +2 -2
- package/lib/cli.js +684 -80
- package/lib/cli.js.map +1 -1
- package/lib/control/index.d.ts +33 -2
- package/lib/control/stagehand.d.ts +20 -0
- package/lib/entities.d.ts +2 -2
- package/lib/index.d.ts +4 -4
- package/lib/index.js +690 -90
- package/lib/index.js.map +1 -1
- package/lib/localdb/onelibrary/index.d.ts +1 -1
- package/lib/network.d.ts +19 -5
- package/lib/passive/status.d.ts +10 -6
- package/lib/remotedb/fields.d.ts +6 -6
- package/lib/remotedb/message/index.d.ts +1 -1
- package/lib/status/index.d.ts +7 -6
- package/lib/status/position.d.ts +4 -0
- package/lib/status/types.d.ts +87 -0
- package/lib/status/utils.d.ts +9 -0
- package/lib/types.d.ts +4 -3
- package/lib/types.js +1 -3
- package/lib/types.js.map +1 -1
- package/lib/virtualcdj/index.d.ts +1 -0
- package/lib/virtualcdj/stagehand.d.ts +51 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -74,26 +74,30 @@ async function extractArtworkFromDevice(device, slot, filePath, logger = logger_
|
|
|
74
74
|
|
|
75
75
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
76
76
|
exports.extractFromAiff = extractFromAiff;
|
|
77
|
-
const id3_1 = __webpack_require__(/*! ./id3 */ "./src/artwork/parsers/id3.ts");
|
|
78
77
|
const reader_1 = __webpack_require__(/*! ../reader */ "./src/artwork/reader.ts");
|
|
78
|
+
const id3_1 = __webpack_require__(/*! ./id3 */ "./src/artwork/parsers/id3.ts");
|
|
79
79
|
async function extractFromAiff(reader) {
|
|
80
80
|
const header = await reader.read(0, 12);
|
|
81
|
-
if (header.length < 12 || header.toString('ascii', 0, 4) !== 'FORM')
|
|
81
|
+
if (header.length < 12 || header.toString('ascii', 0, 4) !== 'FORM') {
|
|
82
82
|
return null;
|
|
83
|
+
}
|
|
83
84
|
const formType = header.toString('ascii', 8, 12);
|
|
84
|
-
if (formType !== 'AIFF' && formType !== 'AIFC')
|
|
85
|
+
if (formType !== 'AIFF' && formType !== 'AIFC') {
|
|
85
86
|
return null;
|
|
87
|
+
}
|
|
86
88
|
const formSize = header.readUInt32BE(4);
|
|
87
89
|
const fileEnd = Math.min(8 + formSize, reader.size);
|
|
88
90
|
let offset = 12;
|
|
89
91
|
while (offset + 8 < fileEnd) {
|
|
90
92
|
const chunkHeader = await reader.read(offset, 8);
|
|
91
|
-
if (chunkHeader.length < 8)
|
|
93
|
+
if (chunkHeader.length < 8) {
|
|
92
94
|
break;
|
|
95
|
+
}
|
|
93
96
|
const chunkId = chunkHeader.toString('ascii', 0, 4);
|
|
94
97
|
const chunkSize = chunkHeader.readUInt32BE(4);
|
|
95
|
-
if (chunkSize <= 0 || offset + 8 + chunkSize > fileEnd)
|
|
98
|
+
if (chunkSize <= 0 || offset + 8 + chunkSize > fileEnd) {
|
|
96
99
|
break;
|
|
100
|
+
}
|
|
97
101
|
if (chunkId === 'ID3 ' || chunkId === 'id3 ') {
|
|
98
102
|
const id3Data = await reader.read(offset + 8, chunkSize);
|
|
99
103
|
const id3Reader = (0, reader_1.createBufferReader)(id3Data, 'mp3');
|
|
@@ -120,32 +124,37 @@ exports.extractFromFlac = extractFromFlac;
|
|
|
120
124
|
const types_1 = __webpack_require__(/*! ../types */ "./src/artwork/types.ts");
|
|
121
125
|
const utils_1 = __webpack_require__(/*! ./utils */ "./src/artwork/parsers/utils.ts");
|
|
122
126
|
function parsePictureBlock(data) {
|
|
123
|
-
if (data.length < 32)
|
|
127
|
+
if (data.length < 32) {
|
|
124
128
|
return null;
|
|
129
|
+
}
|
|
125
130
|
let offset = 0;
|
|
126
131
|
const pictureType = data.readUInt32BE(offset);
|
|
127
132
|
offset += 4;
|
|
128
133
|
const mimeLength = data.readUInt32BE(offset);
|
|
129
134
|
offset += 4;
|
|
130
|
-
if (offset + mimeLength > data.length)
|
|
135
|
+
if (offset + mimeLength > data.length) {
|
|
131
136
|
return null;
|
|
137
|
+
}
|
|
132
138
|
const mimeType = data.toString('utf8', offset, offset + mimeLength);
|
|
133
139
|
offset += mimeLength;
|
|
134
140
|
const descLength = data.readUInt32BE(offset);
|
|
135
141
|
offset += 4 + descLength;
|
|
136
|
-
if (offset + 16 > data.length)
|
|
142
|
+
if (offset + 16 > data.length) {
|
|
137
143
|
return null;
|
|
144
|
+
}
|
|
138
145
|
const width = data.readUInt32BE(offset);
|
|
139
146
|
offset += 4;
|
|
140
147
|
const height = data.readUInt32BE(offset);
|
|
141
148
|
offset += 4 + 8; // Skip depth and colors
|
|
142
149
|
const imageLength = data.readUInt32BE(offset);
|
|
143
150
|
offset += 4;
|
|
144
|
-
if (offset + imageLength > data.length)
|
|
151
|
+
if (offset + imageLength > data.length) {
|
|
145
152
|
return null;
|
|
153
|
+
}
|
|
146
154
|
const imageData = data.subarray(offset, offset + imageLength);
|
|
147
|
-
if (imageData.length === 0)
|
|
155
|
+
if (imageData.length === 0) {
|
|
148
156
|
return null;
|
|
157
|
+
}
|
|
149
158
|
return {
|
|
150
159
|
data: imageData,
|
|
151
160
|
mimeType: (0, utils_1.normalizeMimeType)(mimeType),
|
|
@@ -156,29 +165,34 @@ function parsePictureBlock(data) {
|
|
|
156
165
|
}
|
|
157
166
|
async function extractFromFlac(reader) {
|
|
158
167
|
const signature = await reader.read(0, 4);
|
|
159
|
-
if (signature.toString('ascii') !== 'fLaC')
|
|
168
|
+
if (signature.toString('ascii') !== 'fLaC') {
|
|
160
169
|
return null;
|
|
170
|
+
}
|
|
161
171
|
let offset = 4;
|
|
162
172
|
let isLastBlock = false;
|
|
163
173
|
let frontCover = null;
|
|
164
174
|
let anyArtwork = null;
|
|
165
175
|
while (!isLastBlock && offset < reader.size) {
|
|
166
176
|
const blockHeader = await reader.read(offset, 4);
|
|
167
|
-
if (blockHeader.length < 4)
|
|
177
|
+
if (blockHeader.length < 4) {
|
|
168
178
|
break;
|
|
179
|
+
}
|
|
169
180
|
isLastBlock = (blockHeader[0] & 0x80) !== 0;
|
|
170
181
|
const blockType = blockHeader[0] & 0x7f;
|
|
171
182
|
const blockLength = (blockHeader[1] << 16) | (blockHeader[2] << 8) | blockHeader[3];
|
|
172
|
-
if (blockLength <= 0 || offset + 4 + blockLength > reader.size)
|
|
183
|
+
if (blockLength <= 0 || offset + 4 + blockLength > reader.size) {
|
|
173
184
|
break;
|
|
185
|
+
}
|
|
174
186
|
if (blockType === 6 /* MetadataBlockType.PICTURE */) {
|
|
175
187
|
const pictureData = await reader.read(offset + 4, blockLength);
|
|
176
188
|
const artwork = parsePictureBlock(pictureData);
|
|
177
189
|
if (artwork) {
|
|
178
|
-
if (artwork.pictureType === types_1.PictureType.FrontCover)
|
|
190
|
+
if (artwork.pictureType === types_1.PictureType.FrontCover) {
|
|
179
191
|
frontCover = artwork;
|
|
180
|
-
|
|
192
|
+
}
|
|
193
|
+
else if (!anyArtwork) {
|
|
181
194
|
anyArtwork = artwork;
|
|
195
|
+
}
|
|
182
196
|
}
|
|
183
197
|
}
|
|
184
198
|
offset += 4 + blockLength;
|
|
@@ -212,14 +226,16 @@ function readNullTerminatedString(buffer, offset, encoding) {
|
|
|
212
226
|
let end = offset;
|
|
213
227
|
if (isUtf16) {
|
|
214
228
|
while (end < buffer.length - 1) {
|
|
215
|
-
if (buffer[end] === 0 && buffer[end + 1] === 0)
|
|
229
|
+
if (buffer[end] === 0 && buffer[end + 1] === 0) {
|
|
216
230
|
break;
|
|
231
|
+
}
|
|
217
232
|
end += 2;
|
|
218
233
|
}
|
|
219
234
|
}
|
|
220
235
|
else {
|
|
221
|
-
while (end < buffer.length && buffer[end] !== 0)
|
|
236
|
+
while (end < buffer.length && buffer[end] !== 0) {
|
|
222
237
|
end++;
|
|
238
|
+
}
|
|
223
239
|
}
|
|
224
240
|
let value;
|
|
225
241
|
if (encoding === 'utf16be') {
|
|
@@ -237,56 +253,70 @@ function readNullTerminatedString(buffer, offset, encoding) {
|
|
|
237
253
|
}
|
|
238
254
|
function getTextEncoding(encodingByte) {
|
|
239
255
|
switch (encodingByte) {
|
|
240
|
-
case 0:
|
|
241
|
-
|
|
242
|
-
case
|
|
243
|
-
|
|
244
|
-
|
|
256
|
+
case 0:
|
|
257
|
+
return 'latin1';
|
|
258
|
+
case 1:
|
|
259
|
+
return 'utf16le';
|
|
260
|
+
case 2:
|
|
261
|
+
return 'utf16be';
|
|
262
|
+
case 3:
|
|
263
|
+
return 'utf8';
|
|
264
|
+
default:
|
|
265
|
+
return 'latin1';
|
|
245
266
|
}
|
|
246
267
|
}
|
|
247
268
|
function parseApicFrame(data) {
|
|
248
|
-
if (data.length < 4)
|
|
269
|
+
if (data.length < 4) {
|
|
249
270
|
return null;
|
|
271
|
+
}
|
|
250
272
|
let offset = 0;
|
|
251
273
|
const encodingByte = data[offset++];
|
|
252
274
|
let encoding = getTextEncoding(encodingByte);
|
|
253
275
|
if (encodingByte === 1 && data.length > offset + 2) {
|
|
254
276
|
const bom = data.readUInt16BE(offset);
|
|
255
|
-
if (bom === 0xfeff)
|
|
277
|
+
if (bom === 0xfeff) {
|
|
256
278
|
encoding = 'utf16be';
|
|
257
|
-
|
|
279
|
+
}
|
|
280
|
+
else if (bom === 0xfffe) {
|
|
258
281
|
encoding = 'utf16le';
|
|
282
|
+
}
|
|
259
283
|
}
|
|
260
284
|
const mimeResult = readNullTerminatedString(data, offset, 'latin1');
|
|
261
285
|
const mimeType = mimeResult.value;
|
|
262
286
|
offset += mimeResult.bytesConsumed;
|
|
263
|
-
if (offset >= data.length)
|
|
287
|
+
if (offset >= data.length) {
|
|
264
288
|
return null;
|
|
289
|
+
}
|
|
265
290
|
const pictureType = data[offset++];
|
|
266
|
-
if (offset >= data.length)
|
|
291
|
+
if (offset >= data.length) {
|
|
267
292
|
return null;
|
|
293
|
+
}
|
|
268
294
|
const descResult = readNullTerminatedString(data, offset, encoding);
|
|
269
295
|
offset += descResult.bytesConsumed;
|
|
270
|
-
if (offset >= data.length)
|
|
296
|
+
if (offset >= data.length) {
|
|
271
297
|
return null;
|
|
298
|
+
}
|
|
272
299
|
const imageData = data.subarray(offset);
|
|
273
|
-
if (imageData.length === 0)
|
|
300
|
+
if (imageData.length === 0) {
|
|
274
301
|
return null;
|
|
302
|
+
}
|
|
275
303
|
const detectedType = (0, utils_1.detectImageType)(imageData);
|
|
276
304
|
const finalMimeType = detectedType !== null && detectedType !== void 0 ? detectedType : (mimeType.includes('png') ? 'image/png' : 'image/jpeg');
|
|
277
305
|
return { data: imageData, mimeType: finalMimeType, pictureType };
|
|
278
306
|
}
|
|
279
307
|
async function extractFromMp3(reader) {
|
|
280
308
|
const header = await reader.read(0, 10);
|
|
281
|
-
if (header.length < 10 || header.toString('ascii', 0, 3) !== 'ID3')
|
|
309
|
+
if (header.length < 10 || header.toString('ascii', 0, 3) !== 'ID3') {
|
|
282
310
|
return null;
|
|
311
|
+
}
|
|
283
312
|
const majorVersion = header[3];
|
|
284
313
|
const flags = header[5];
|
|
285
314
|
const tagSize = readSyncsafe(header, 6);
|
|
286
315
|
let extendedHeaderSize = 0;
|
|
287
316
|
if (flags & 0x40) {
|
|
288
317
|
const extHeader = await reader.read(10, 4);
|
|
289
|
-
extendedHeaderSize =
|
|
318
|
+
extendedHeaderSize =
|
|
319
|
+
majorVersion === 4 ? readSyncsafe(extHeader, 0) : extHeader.readUInt32BE(0);
|
|
290
320
|
}
|
|
291
321
|
const tagData = await reader.read(10 + extendedHeaderSize, tagSize - extendedHeaderSize);
|
|
292
322
|
let offset = 0;
|
|
@@ -294,29 +324,37 @@ async function extractFromMp3(reader) {
|
|
|
294
324
|
let frontCover = null;
|
|
295
325
|
let anyArtwork = null;
|
|
296
326
|
while (offset < tagData.length - frameHeaderSize) {
|
|
297
|
-
if (tagData[offset] === 0)
|
|
327
|
+
if (tagData[offset] === 0) {
|
|
298
328
|
break;
|
|
329
|
+
}
|
|
299
330
|
let frameId;
|
|
300
331
|
let frameSize;
|
|
301
332
|
if (majorVersion >= 3) {
|
|
302
333
|
frameId = tagData.toString('ascii', offset, offset + 4);
|
|
303
|
-
frameSize =
|
|
334
|
+
frameSize =
|
|
335
|
+
majorVersion === 4
|
|
336
|
+
? readSyncsafe(tagData, offset + 4)
|
|
337
|
+
: tagData.readUInt32BE(offset + 4);
|
|
304
338
|
}
|
|
305
339
|
else {
|
|
306
340
|
frameId = tagData.toString('ascii', offset, offset + 3);
|
|
307
|
-
frameSize =
|
|
341
|
+
frameSize =
|
|
342
|
+
(tagData[offset + 3] << 16) | (tagData[offset + 4] << 8) | tagData[offset + 5];
|
|
308
343
|
}
|
|
309
|
-
if (frameSize <= 0 || frameSize > tagData.length - offset)
|
|
344
|
+
if (frameSize <= 0 || frameSize > tagData.length - offset) {
|
|
310
345
|
break;
|
|
346
|
+
}
|
|
311
347
|
const frameIdNormalized = majorVersion >= 3 ? frameId : frameId === 'PIC' ? 'APIC' : frameId;
|
|
312
348
|
if (frameIdNormalized === 'APIC') {
|
|
313
349
|
const frameData = tagData.subarray(offset + frameHeaderSize, offset + frameHeaderSize + frameSize);
|
|
314
350
|
const artwork = parseApicFrame(frameData);
|
|
315
351
|
if (artwork) {
|
|
316
|
-
if (artwork.pictureType === types_1.PictureType.FrontCover)
|
|
352
|
+
if (artwork.pictureType === types_1.PictureType.FrontCover) {
|
|
317
353
|
frontCover = artwork;
|
|
318
|
-
|
|
354
|
+
}
|
|
355
|
+
else if (!anyArtwork) {
|
|
319
356
|
anyArtwork = artwork;
|
|
357
|
+
}
|
|
320
358
|
}
|
|
321
359
|
}
|
|
322
360
|
offset += frameHeaderSize + frameSize;
|
|
@@ -336,15 +374,15 @@ async function extractFromMp3(reader) {
|
|
|
336
374
|
"use strict";
|
|
337
375
|
|
|
338
376
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
339
|
-
exports.normalizeMimeType = exports.detectImageType = exports.
|
|
377
|
+
exports.normalizeMimeType = exports.detectImageType = exports.extractFromMp4 = exports.extractFromMp3 = exports.extractFromFlac = exports.extractFromAiff = void 0;
|
|
378
|
+
var aiff_1 = __webpack_require__(/*! ./aiff */ "./src/artwork/parsers/aiff.ts");
|
|
379
|
+
Object.defineProperty(exports, "extractFromAiff", ({ enumerable: true, get: function () { return aiff_1.extractFromAiff; } }));
|
|
380
|
+
var flac_1 = __webpack_require__(/*! ./flac */ "./src/artwork/parsers/flac.ts");
|
|
381
|
+
Object.defineProperty(exports, "extractFromFlac", ({ enumerable: true, get: function () { return flac_1.extractFromFlac; } }));
|
|
340
382
|
var id3_1 = __webpack_require__(/*! ./id3 */ "./src/artwork/parsers/id3.ts");
|
|
341
383
|
Object.defineProperty(exports, "extractFromMp3", ({ enumerable: true, get: function () { return id3_1.extractFromMp3; } }));
|
|
342
384
|
var mp4_1 = __webpack_require__(/*! ./mp4 */ "./src/artwork/parsers/mp4.ts");
|
|
343
385
|
Object.defineProperty(exports, "extractFromMp4", ({ enumerable: true, get: function () { return mp4_1.extractFromMp4; } }));
|
|
344
|
-
var flac_1 = __webpack_require__(/*! ./flac */ "./src/artwork/parsers/flac.ts");
|
|
345
|
-
Object.defineProperty(exports, "extractFromFlac", ({ enumerable: true, get: function () { return flac_1.extractFromFlac; } }));
|
|
346
|
-
var aiff_1 = __webpack_require__(/*! ./aiff */ "./src/artwork/parsers/aiff.ts");
|
|
347
|
-
Object.defineProperty(exports, "extractFromAiff", ({ enumerable: true, get: function () { return aiff_1.extractFromAiff; } }));
|
|
348
386
|
var utils_1 = __webpack_require__(/*! ./utils */ "./src/artwork/parsers/utils.ts");
|
|
349
387
|
Object.defineProperty(exports, "detectImageType", ({ enumerable: true, get: function () { return utils_1.detectImageType; } }));
|
|
350
388
|
Object.defineProperty(exports, "normalizeMimeType", ({ enumerable: true, get: function () { return utils_1.normalizeMimeType; } }));
|
|
@@ -365,30 +403,37 @@ exports.extractFromMp4 = extractFromMp4;
|
|
|
365
403
|
const types_1 = __webpack_require__(/*! ../types */ "./src/artwork/types.ts");
|
|
366
404
|
const utils_1 = __webpack_require__(/*! ./utils */ "./src/artwork/parsers/utils.ts");
|
|
367
405
|
async function readAtomHeader(reader, offset) {
|
|
368
|
-
if (offset + 8 > reader.size)
|
|
406
|
+
if (offset + 8 > reader.size) {
|
|
369
407
|
return null;
|
|
408
|
+
}
|
|
370
409
|
const header = await reader.read(offset, 8);
|
|
371
410
|
const size = header.readUInt32BE(0);
|
|
372
411
|
const type = header.toString('ascii', 4, 8);
|
|
373
412
|
if (size === 1) {
|
|
374
|
-
if (offset + 16 > reader.size)
|
|
413
|
+
if (offset + 16 > reader.size) {
|
|
375
414
|
return null;
|
|
415
|
+
}
|
|
376
416
|
const extHeader = await reader.read(offset + 8, 8);
|
|
377
417
|
const extSize = Number(extHeader.readBigUInt64BE(0));
|
|
378
418
|
return { size: extSize, type, headerSize: 16 };
|
|
379
419
|
}
|
|
380
|
-
if (size === 0)
|
|
420
|
+
if (size === 0) {
|
|
381
421
|
return { size: reader.size - offset, type, headerSize: 8 };
|
|
422
|
+
}
|
|
382
423
|
return { size, type, headerSize: 8 };
|
|
383
424
|
}
|
|
384
425
|
async function findAtom(reader, startOffset, endOffset, targetType) {
|
|
385
426
|
let offset = startOffset;
|
|
386
427
|
while (offset < endOffset) {
|
|
387
428
|
const header = await readAtomHeader(reader, offset);
|
|
388
|
-
if (!header || header.size <= 0)
|
|
429
|
+
if (!header || header.size <= 0) {
|
|
389
430
|
break;
|
|
431
|
+
}
|
|
390
432
|
if (header.type === targetType) {
|
|
391
|
-
return {
|
|
433
|
+
return {
|
|
434
|
+
dataOffset: offset + header.headerSize,
|
|
435
|
+
dataSize: header.size - header.headerSize,
|
|
436
|
+
};
|
|
392
437
|
}
|
|
393
438
|
offset += header.size;
|
|
394
439
|
}
|
|
@@ -399,35 +444,43 @@ async function findMoovAtom(reader) {
|
|
|
399
444
|
}
|
|
400
445
|
async function findCoverArtData(reader, moovOffset, moovSize) {
|
|
401
446
|
const udta = await findAtom(reader, moovOffset, moovOffset + moovSize, 'udta');
|
|
402
|
-
if (!udta)
|
|
447
|
+
if (!udta) {
|
|
403
448
|
return null;
|
|
449
|
+
}
|
|
404
450
|
const meta = await findAtom(reader, udta.dataOffset, udta.dataOffset + udta.dataSize, 'meta');
|
|
405
|
-
if (!meta)
|
|
451
|
+
if (!meta) {
|
|
406
452
|
return null;
|
|
453
|
+
}
|
|
407
454
|
const metaDataStart = meta.dataOffset + 4;
|
|
408
455
|
const metaDataEnd = meta.dataOffset + meta.dataSize;
|
|
409
456
|
const ilst = await findAtom(reader, metaDataStart, metaDataEnd, 'ilst');
|
|
410
|
-
if (!ilst)
|
|
457
|
+
if (!ilst) {
|
|
411
458
|
return null;
|
|
459
|
+
}
|
|
412
460
|
const covr = await findAtom(reader, ilst.dataOffset, ilst.dataOffset + ilst.dataSize, 'covr');
|
|
413
|
-
if (!covr)
|
|
461
|
+
if (!covr) {
|
|
414
462
|
return null;
|
|
463
|
+
}
|
|
415
464
|
const data = await findAtom(reader, covr.dataOffset, covr.dataOffset + covr.dataSize, 'data');
|
|
416
|
-
if (!data || data.dataSize < 8)
|
|
465
|
+
if (!data || data.dataSize < 8) {
|
|
417
466
|
return null;
|
|
467
|
+
}
|
|
418
468
|
return reader.read(data.dataOffset + 8, data.dataSize - 8);
|
|
419
469
|
}
|
|
420
470
|
async function extractFromMp4(reader) {
|
|
421
471
|
var _a;
|
|
422
472
|
const ftypHeader = await reader.read(0, 8);
|
|
423
|
-
if (ftypHeader.length < 8 || ftypHeader.toString('ascii', 4, 8) !== 'ftyp')
|
|
473
|
+
if (ftypHeader.length < 8 || ftypHeader.toString('ascii', 4, 8) !== 'ftyp') {
|
|
424
474
|
return null;
|
|
475
|
+
}
|
|
425
476
|
const moov = await findMoovAtom(reader);
|
|
426
|
-
if (!moov)
|
|
477
|
+
if (!moov) {
|
|
427
478
|
return null;
|
|
479
|
+
}
|
|
428
480
|
const imageData = await findCoverArtData(reader, moov.dataOffset, moov.dataSize);
|
|
429
|
-
if (!imageData || imageData.length === 0)
|
|
481
|
+
if (!imageData || imageData.length === 0) {
|
|
430
482
|
return null;
|
|
483
|
+
}
|
|
431
484
|
const mimeType = (_a = (0, utils_1.detectImageType)(imageData)) !== null && _a !== void 0 ? _a : 'image/jpeg';
|
|
432
485
|
return { data: imageData, mimeType, pictureType: types_1.PictureType.FrontCover };
|
|
433
486
|
}
|
|
@@ -447,22 +500,28 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
447
500
|
exports.detectImageType = detectImageType;
|
|
448
501
|
exports.normalizeMimeType = normalizeMimeType;
|
|
449
502
|
function detectImageType(data) {
|
|
450
|
-
if (data.length < 4)
|
|
503
|
+
if (data.length < 4) {
|
|
451
504
|
return null;
|
|
452
|
-
|
|
505
|
+
}
|
|
506
|
+
if (data[0] === 0xff && data[1] === 0xd8 && data[2] === 0xff) {
|
|
453
507
|
return 'image/jpeg';
|
|
454
|
-
|
|
508
|
+
}
|
|
509
|
+
if (data[0] === 0x89 && data.toString('ascii', 1, 4) === 'PNG') {
|
|
455
510
|
return 'image/png';
|
|
456
|
-
|
|
511
|
+
}
|
|
512
|
+
if (data.toString('ascii', 0, 3) === 'GIF') {
|
|
457
513
|
return 'image/gif';
|
|
514
|
+
}
|
|
458
515
|
return null;
|
|
459
516
|
}
|
|
460
517
|
function normalizeMimeType(mimeType) {
|
|
461
518
|
const lower = mimeType.toLowerCase();
|
|
462
|
-
if (lower.includes('png'))
|
|
519
|
+
if (lower.includes('png')) {
|
|
463
520
|
return 'image/png';
|
|
464
|
-
|
|
521
|
+
}
|
|
522
|
+
if (lower.includes('gif')) {
|
|
465
523
|
return 'image/gif';
|
|
524
|
+
}
|
|
466
525
|
return 'image/jpeg';
|
|
467
526
|
}
|
|
468
527
|
|
|
@@ -639,19 +698,20 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
639
698
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
640
699
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
641
700
|
};
|
|
642
|
-
var _Control_hostDevice, _Control_beatSocket;
|
|
701
|
+
var _Control_hostDevice, _Control_beatSocket, _Control_correlationByte;
|
|
643
702
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
644
703
|
exports.makePlaystatePacket = void 0;
|
|
645
704
|
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
646
705
|
const types_1 = __webpack_require__(/*! src/types */ "./src/types.ts");
|
|
647
706
|
const utils_1 = __webpack_require__(/*! src/utils */ "./src/utils/index.ts");
|
|
648
707
|
const udp_1 = __webpack_require__(/*! src/utils/udp */ "./src/utils/udp.ts");
|
|
708
|
+
const stagehand_1 = __webpack_require__(/*! ./stagehand */ "./src/control/stagehand.ts");
|
|
649
709
|
const STATE_MAP = {
|
|
650
710
|
[types_1.CDJStatus.PlayState.Cued]: 0x01,
|
|
651
711
|
[types_1.CDJStatus.PlayState.Playing]: 0x00,
|
|
652
712
|
};
|
|
653
713
|
/**
|
|
654
|
-
* Generates the packet used to control the playstate of CDJs
|
|
714
|
+
* Generates the packet used to control the playstate of CDJs in active connection mode
|
|
655
715
|
*/
|
|
656
716
|
const makePlaystatePacket = ({ hostDevice, device, playState }) => Uint8Array.from([
|
|
657
717
|
...constants_1.PROLINK_HEADER,
|
|
@@ -672,21 +732,174 @@ class Control {
|
|
|
672
732
|
* The socket used to send control packets
|
|
673
733
|
*/
|
|
674
734
|
_Control_beatSocket.set(this, void 0);
|
|
735
|
+
/**
|
|
736
|
+
* Randomized correlation byte per session for Stagehand commands
|
|
737
|
+
*/
|
|
738
|
+
_Control_correlationByte.set(this, void 0);
|
|
675
739
|
__classPrivateFieldSet(this, _Control_beatSocket, beatSocket, "f");
|
|
676
740
|
__classPrivateFieldSet(this, _Control_hostDevice, hostDevice, "f");
|
|
741
|
+
__classPrivateFieldSet(this, _Control_correlationByte, Math.floor(Math.random() * 256), "f");
|
|
677
742
|
}
|
|
678
743
|
/**
|
|
679
|
-
* Start or stop a CDJ on the network
|
|
744
|
+
* Start or stop a CDJ on the network.
|
|
745
|
+
* Delegates automatically to Stagehand-specific transport control if connected in Stagehand mode.
|
|
680
746
|
*/
|
|
681
747
|
async setPlayState(device, playState) {
|
|
748
|
+
if (__classPrivateFieldGet(this, _Control_hostDevice, "f").type === types_1.DeviceType.Stagehand) {
|
|
749
|
+
if (playState === types_1.CDJStatus.PlayState.Playing) {
|
|
750
|
+
await this.play(device);
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
await this.pause(device);
|
|
754
|
+
}
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
682
757
|
const packet = (0, exports.makePlaystatePacket)({ hostDevice: __classPrivateFieldGet(this, _Control_hostDevice, "f"), device, playState });
|
|
683
758
|
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), packet, constants_1.BEAT_PORT, device.ip.address);
|
|
684
759
|
}
|
|
760
|
+
/**
|
|
761
|
+
* Send Stagehand PLAY command (paired 0x0f and 0x14 packets)
|
|
762
|
+
*/
|
|
763
|
+
async play(device) {
|
|
764
|
+
const p1 = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x0f, true, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
765
|
+
const p2 = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x14, true, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
766
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p1, constants_1.BEAT_PORT, device.ip.address);
|
|
767
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p2, constants_1.BEAT_PORT, device.ip.address);
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Send Stagehand PAUSE command (paired 0x14 packet)
|
|
771
|
+
*/
|
|
772
|
+
async pause(device) {
|
|
773
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x14, false, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
774
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* Send Stagehand SEEK forward command
|
|
778
|
+
* @param press - true to start seek, false to release
|
|
779
|
+
*/
|
|
780
|
+
async seekForward(device, press) {
|
|
781
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x1a, press, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
782
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Send Stagehand SEEK backward command
|
|
786
|
+
* @param press - true to start seek, false to release
|
|
787
|
+
*/
|
|
788
|
+
async seekBackward(device, press) {
|
|
789
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x1b, press, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
790
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Send Stagehand SKIP track command
|
|
794
|
+
* @param press - true to start skip, false to release
|
|
795
|
+
*/
|
|
796
|
+
async skip(device, press) {
|
|
797
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x18, press, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
798
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Send Stagehand preference write command (0x6b packet) to port 50002
|
|
802
|
+
*/
|
|
803
|
+
async setPreference(device, options) {
|
|
804
|
+
const p = (0, stagehand_1.makeStagehandPrefWritePacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), options);
|
|
805
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.STATUS_PORT, device.ip.address);
|
|
806
|
+
}
|
|
685
807
|
}
|
|
686
|
-
_Control_hostDevice = new WeakMap(), _Control_beatSocket = new WeakMap();
|
|
808
|
+
_Control_hostDevice = new WeakMap(), _Control_beatSocket = new WeakMap(), _Control_correlationByte = new WeakMap();
|
|
687
809
|
exports["default"] = Control;
|
|
688
810
|
|
|
689
811
|
|
|
812
|
+
/***/ },
|
|
813
|
+
|
|
814
|
+
/***/ "./src/control/stagehand.ts"
|
|
815
|
+
/*!**********************************!*\
|
|
816
|
+
!*** ./src/control/stagehand.ts ***!
|
|
817
|
+
\**********************************/
|
|
818
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
819
|
+
|
|
820
|
+
"use strict";
|
|
821
|
+
|
|
822
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
823
|
+
exports.makeStagehandTransportPacket = makeStagehandTransportPacket;
|
|
824
|
+
exports.makeStagehandPrefWritePacket = makeStagehandPrefWritePacket;
|
|
825
|
+
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
826
|
+
const utils_1 = __webpack_require__(/*! src/utils */ "./src/utils/index.ts");
|
|
827
|
+
/**
|
|
828
|
+
* Generates a Stagehand transport control packet (0x07, 56 bytes)
|
|
829
|
+
*
|
|
830
|
+
* @param hostDevice - The Stagehand device posing as sender
|
|
831
|
+
* @param op - The command opcode (e.g. 0x0f, 0x14, 0x18, 0x1a, 0x1b)
|
|
832
|
+
* @param press - Whether the action is press (true) or release (false)
|
|
833
|
+
* @param correlationByte - The randomized per-session correlation byte
|
|
834
|
+
*/
|
|
835
|
+
function makeStagehandTransportPacket(hostDevice, op, press, correlationByte) {
|
|
836
|
+
const packet = new Uint8Array(56);
|
|
837
|
+
// 0-9: magic header
|
|
838
|
+
packet.set(constants_1.PROLINK_HEADER, 0);
|
|
839
|
+
// 10: opcode 0x07
|
|
840
|
+
packet[10] = 0x07;
|
|
841
|
+
// 11-30: device name
|
|
842
|
+
packet.set((0, utils_1.buildName)(hostDevice), 11);
|
|
843
|
+
// 31: 0x01
|
|
844
|
+
packet[31] = 0x01;
|
|
845
|
+
// 32: 0x03
|
|
846
|
+
packet[32] = 0x03;
|
|
847
|
+
// 33: per-session correlation byte
|
|
848
|
+
packet[33] = correlationByte;
|
|
849
|
+
// 34-35: remaining length 0x0030 (48 bytes)
|
|
850
|
+
packet[34] = 0x00;
|
|
851
|
+
packet[35] = 0x30;
|
|
852
|
+
// 40: Stagehand sub-id 0x3a
|
|
853
|
+
packet[40] = 0x3a;
|
|
854
|
+
// 44: command opcode
|
|
855
|
+
packet[44] = op;
|
|
856
|
+
// 46: press/release flag
|
|
857
|
+
packet[46] = press ? 0x01 : 0x00;
|
|
858
|
+
return packet;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Generates a Stagehand preference write packet (0x6b, 124 bytes)
|
|
862
|
+
*
|
|
863
|
+
* @param hostDevice - The Stagehand device posing as sender
|
|
864
|
+
* @param options - The preferences to write (onAir, quantize)
|
|
865
|
+
*/
|
|
866
|
+
function makeStagehandPrefWritePacket(hostDevice, options) {
|
|
867
|
+
const packet = new Uint8Array(124);
|
|
868
|
+
// 0-9: magic header
|
|
869
|
+
packet.set(constants_1.PROLINK_HEADER, 0);
|
|
870
|
+
// 10: opcode 0x6b
|
|
871
|
+
packet[10] = 0x6b;
|
|
872
|
+
// 11-30: device name
|
|
873
|
+
const name = (0, utils_1.buildName)(hostDevice);
|
|
874
|
+
// Trailing byte 30 (which is offset 30, meaning index 19 of name) is set to 0x03
|
|
875
|
+
name[19] = 0x03;
|
|
876
|
+
packet.set(name, 11);
|
|
877
|
+
// 31: 0x01 (subscription-id-a constant)
|
|
878
|
+
packet[31] = 0x01;
|
|
879
|
+
// 32: 0x03 (constant)
|
|
880
|
+
packet[32] = 0x03;
|
|
881
|
+
// 33: Stagehand sub-id constant 0x3a
|
|
882
|
+
packet[33] = 0x3a;
|
|
883
|
+
// 34-35: body length 0x0050 (80 bytes)
|
|
884
|
+
packet[34] = 0x00;
|
|
885
|
+
packet[35] = 0x50;
|
|
886
|
+
// 36: transaction flag (0x01 = write)
|
|
887
|
+
packet[36] = 0x01;
|
|
888
|
+
// 44: on_air slot (0x80 = OFF, 0x81 = ON, 0x00 = untouched)
|
|
889
|
+
if (options.onAir === 'on') {
|
|
890
|
+
packet[44] = 0x81;
|
|
891
|
+
}
|
|
892
|
+
else if (options.onAir === 'off') {
|
|
893
|
+
packet[44] = 0x80;
|
|
894
|
+
}
|
|
895
|
+
// 60: quantize slot (0x80 | enum_index, e.g. 0x81, 0x82 etc.)
|
|
896
|
+
if (options.quantize !== undefined) {
|
|
897
|
+
packet[60] = 0x80 | options.quantize;
|
|
898
|
+
}
|
|
899
|
+
return packet;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
|
|
690
903
|
/***/ },
|
|
691
904
|
|
|
692
905
|
/***/ "./src/db/getArtworkFromFile.ts"
|
|
@@ -1840,10 +2053,6 @@ function deviceFromPacket(packet) {
|
|
|
1840
2053
|
|
|
1841
2054
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1842
2055
|
exports.EntityFK = void 0;
|
|
1843
|
-
/**
|
|
1844
|
-
* Re-export entity types from onelibrary-connect.
|
|
1845
|
-
* These types represent what is stored in the rekordbox database.
|
|
1846
|
-
*/
|
|
1847
2056
|
var onelibrary_connect_1 = __webpack_require__(/*! onelibrary-connect */ "onelibrary-connect");
|
|
1848
2057
|
Object.defineProperty(exports, "EntityFK", ({ enumerable: true, get: function () { return onelibrary_connect_1.EntityFK; } }));
|
|
1849
2058
|
|
|
@@ -1884,25 +2093,21 @@ var position_1 = __webpack_require__(/*! ./status/position */ "./src/status/posi
|
|
|
1884
2093
|
Object.defineProperty(exports, "PositionEmitter", ({ enumerable: true, get: function () { return __importDefault(position_1).default; } }));
|
|
1885
2094
|
// Passive mode (pcap-based monitoring without announcing a VCDJ)
|
|
1886
2095
|
__exportStar(__webpack_require__(/*! ./passive */ "./src/passive/index.ts"), exports);
|
|
1887
|
-
// Artwork extraction
|
|
1888
2096
|
var artwork_1 = __webpack_require__(/*! ./artwork */ "./src/artwork/index.ts");
|
|
1889
2097
|
Object.defineProperty(exports, "extractArtwork", ({ enumerable: true, get: function () { return artwork_1.extractArtwork; } }));
|
|
1890
2098
|
Object.defineProperty(exports, "extractArtworkFromDevice", ({ enumerable: true, get: function () { return artwork_1.extractArtworkFromDevice; } }));
|
|
1891
2099
|
Object.defineProperty(exports, "isArtworkExtractionSupported", ({ enumerable: true, get: function () { return artwork_1.isArtworkExtractionSupported; } }));
|
|
1892
2100
|
Object.defineProperty(exports, "PictureType", ({ enumerable: true, get: function () { return artwork_1.PictureType; } }));
|
|
1893
|
-
// Full metadata extraction (title, artist, album, BPM, key, genre, artwork)
|
|
1894
2101
|
var metadata_1 = __webpack_require__(/*! ./metadata */ "./src/metadata.ts");
|
|
1895
2102
|
Object.defineProperty(exports, "extractFullMetadata", ({ enumerable: true, get: function () { return metadata_1.extractFullMetadata; } }));
|
|
1896
2103
|
Object.defineProperty(exports, "extractMetadataFromDevice", ({ enumerable: true, get: function () { return metadata_1.extractMetadataFromDevice; } }));
|
|
1897
2104
|
Object.defineProperty(exports, "isMetadataExtractionSupported", ({ enumerable: true, get: function () { return metadata_1.isMetadataExtractionSupported; } }));
|
|
1898
|
-
// ANLZ file loading (for analysis data: beat grid, cues, phrases, waveforms)
|
|
1899
2105
|
var rekordbox_1 = __webpack_require__(/*! ./localdb/rekordbox */ "./src/localdb/rekordbox.ts");
|
|
1900
2106
|
Object.defineProperty(exports, "loadAnlz", ({ enumerable: true, get: function () { return rekordbox_1.loadAnlz; } }));
|
|
1901
2107
|
var nfs_1 = __webpack_require__(/*! ./nfs */ "./src/nfs/index.ts");
|
|
1902
2108
|
Object.defineProperty(exports, "fetchFile", ({ enumerable: true, get: function () { return nfs_1.fetchFile; } }));
|
|
1903
2109
|
var onelibrary_connect_1 = __webpack_require__(/*! onelibrary-connect */ "onelibrary-connect");
|
|
1904
2110
|
Object.defineProperty(exports, "OneLibraryAdapter", ({ enumerable: true, get: function () { return onelibrary_connect_1.OneLibraryAdapter; } }));
|
|
1905
|
-
// Logger interface for pluggable logging
|
|
1906
2111
|
var logger_1 = __webpack_require__(/*! ./logger */ "./src/logger.ts");
|
|
1907
2112
|
Object.defineProperty(exports, "noopLogger", ({ enumerable: true, get: function () { return logger_1.noopLogger; } }));
|
|
1908
2113
|
// Types are exported last to avoid overwriting values with type-only exports
|
|
@@ -6161,8 +6366,8 @@ exports.extractFullMetadata = extractFullMetadata;
|
|
|
6161
6366
|
exports.isMetadataExtractionSupported = isMetadataExtractionSupported;
|
|
6162
6367
|
exports.extractMetadataFromDevice = extractMetadataFromDevice;
|
|
6163
6368
|
const metadata_connect_1 = __webpack_require__(/*! metadata-connect */ "metadata-connect");
|
|
6164
|
-
const nfs_1 = __webpack_require__(/*! ./nfs */ "./src/nfs/index.ts");
|
|
6165
6369
|
const reader_1 = __webpack_require__(/*! ./artwork/reader */ "./src/artwork/reader.ts");
|
|
6370
|
+
const nfs_1 = __webpack_require__(/*! ./nfs */ "./src/nfs/index.ts");
|
|
6166
6371
|
/**
|
|
6167
6372
|
* Extract full metadata from an audio file using a FileReader.
|
|
6168
6373
|
*
|
|
@@ -6653,14 +6858,15 @@ var _ProlinkNetwork_state, _ProlinkNetwork_announceSocket, _ProlinkNetwork_beatS
|
|
|
6653
6858
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6654
6859
|
exports.ProlinkNetwork = void 0;
|
|
6655
6860
|
exports.bringOnline = bringOnline;
|
|
6861
|
+
exports.bringOnlineStagehand = bringOnlineStagehand;
|
|
6656
6862
|
const crypto_1 = __webpack_require__(/*! crypto */ "crypto");
|
|
6657
6863
|
const dgram_1 = __importDefault(__webpack_require__(/*! dgram */ "dgram"));
|
|
6658
6864
|
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
6659
6865
|
const control_1 = __importDefault(__webpack_require__(/*! src/control */ "./src/control/index.ts"));
|
|
6660
6866
|
const db_1 = __importDefault(__webpack_require__(/*! src/db */ "./src/db/index.ts"));
|
|
6661
6867
|
const devices_1 = __importDefault(__webpack_require__(/*! src/devices */ "./src/devices/index.ts"));
|
|
6662
|
-
const logger_1 = __webpack_require__(/*! src/logger */ "./src/logger.ts");
|
|
6663
6868
|
const localdb_1 = __importDefault(__webpack_require__(/*! src/localdb */ "./src/localdb/index.ts"));
|
|
6869
|
+
const logger_1 = __webpack_require__(/*! src/logger */ "./src/logger.ts");
|
|
6664
6870
|
const mixstatus_1 = __webpack_require__(/*! src/mixstatus */ "./src/mixstatus/index.ts");
|
|
6665
6871
|
const remotedb_1 = __importDefault(__webpack_require__(/*! src/remotedb */ "./src/remotedb/index.ts"));
|
|
6666
6872
|
const status_1 = __importDefault(__webpack_require__(/*! src/status */ "./src/status/index.ts"));
|
|
@@ -6715,6 +6921,17 @@ async function bringOnline(config) {
|
|
|
6715
6921
|
});
|
|
6716
6922
|
return network;
|
|
6717
6923
|
}
|
|
6924
|
+
/**
|
|
6925
|
+
* Brings the Prolink network online using the Pioneer Stagehand connection method.
|
|
6926
|
+
*
|
|
6927
|
+
* This connects to the network as a non-player Stagehand device using its abbreviated handshake.
|
|
6928
|
+
*/
|
|
6929
|
+
async function bringOnlineStagehand(config) {
|
|
6930
|
+
return bringOnline({
|
|
6931
|
+
...config,
|
|
6932
|
+
connectMethod: 'stagehand',
|
|
6933
|
+
});
|
|
6934
|
+
}
|
|
6718
6935
|
class ProlinkNetwork {
|
|
6719
6936
|
/**
|
|
6720
6937
|
* @internal
|
|
@@ -6764,6 +6981,7 @@ class ProlinkNetwork {
|
|
|
6764
6981
|
* Defaults the Virtual CDJ ID to 7.
|
|
6765
6982
|
*/
|
|
6766
6983
|
async autoconfigFromPeers() {
|
|
6984
|
+
var _a;
|
|
6767
6985
|
const tx = Telemetry.startTransaction({ name: 'autoConfigure' });
|
|
6768
6986
|
// wait for first device to appear on the network
|
|
6769
6987
|
const firstDevice = await new Promise(resolve => __classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f").once('connected', resolve));
|
|
@@ -6779,7 +6997,10 @@ class ProlinkNetwork {
|
|
|
6779
6997
|
tx.finish();
|
|
6780
6998
|
throw new Error('Unable to determine network interface');
|
|
6781
6999
|
}
|
|
6782
|
-
|
|
7000
|
+
const defaultId = ((_a = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f")) === null || _a === void 0 ? void 0 : _a.connectMethod) === 'stagehand'
|
|
7001
|
+
? (0, virtualcdj_1.generateStagehandDeviceId)()
|
|
7002
|
+
: constants_1.DEFAULT_VCDJ_ID;
|
|
7003
|
+
__classPrivateFieldSet(this, _ProlinkNetwork_config, { ...__classPrivateFieldGet(this, _ProlinkNetwork_config, "f"), vcdjId: defaultId, iface }, "f");
|
|
6783
7004
|
tx.finish();
|
|
6784
7005
|
}
|
|
6785
7006
|
/**
|
|
@@ -6789,23 +7010,34 @@ class ProlinkNetwork {
|
|
|
6789
7010
|
* or manual configuration). This will then initialize all the network services.
|
|
6790
7011
|
*/
|
|
6791
7012
|
connect() {
|
|
6792
|
-
var _a, _b, _c;
|
|
7013
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6793
7014
|
if (__classPrivateFieldGet(this, _ProlinkNetwork_config, "f") === null) {
|
|
6794
7015
|
throw new Error(connectErrorHelp);
|
|
6795
7016
|
}
|
|
6796
7017
|
const tx = Telemetry.startTransaction({ name: 'connect' });
|
|
6797
|
-
|
|
6798
|
-
const
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
7018
|
+
const connectMethod = (_a = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").connectMethod) !== null && _a !== void 0 ? _a : 'active';
|
|
7019
|
+
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);
|
|
7020
|
+
const vcdjName = (_c = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").vcdjName) !== null && _c !== void 0 ? _c : (connectMethod === 'stagehand' ? 'Stagehand' : undefined);
|
|
7021
|
+
// Create VCDJ or Stagehand device
|
|
7022
|
+
const vcdj = connectMethod === 'stagehand'
|
|
7023
|
+
? (0, virtualcdj_1.getVirtualStagehand)(__classPrivateFieldGet(this, _ProlinkNetwork_config, "f").iface, vcdjId, vcdjName)
|
|
7024
|
+
: (0, virtualcdj_1.getVirtualCDJ)(__classPrivateFieldGet(this, _ProlinkNetwork_config, "f").iface, vcdjId, vcdjName);
|
|
7025
|
+
// Update device manager to filter out our device name
|
|
7026
|
+
if (vcdjName !== undefined) {
|
|
7027
|
+
__classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f").reconfigure({ vcdjName });
|
|
6802
7028
|
}
|
|
6803
7029
|
// Start announcing
|
|
6804
|
-
|
|
7030
|
+
let announcer;
|
|
7031
|
+
if (connectMethod === 'stagehand') {
|
|
7032
|
+
announcer = new virtualcdj_1.StagehandAnnouncer(vcdj, __classPrivateFieldGet(this, _ProlinkNetwork_announceSocket, "f"), this.deviceManager, __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").iface, __classPrivateFieldGet(this, _ProlinkNetwork_logger, "f"));
|
|
7033
|
+
}
|
|
7034
|
+
else {
|
|
7035
|
+
announcer = new virtualcdj_1.Announcer(vcdj, __classPrivateFieldGet(this, _ProlinkNetwork_announceSocket, "f"), this.deviceManager, __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").iface, (_d = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").fullStartup) !== null && _d !== void 0 ? _d : false, (_e = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").announceToStagehand) !== null && _e !== void 0 ? _e : false, __classPrivateFieldGet(this, _ProlinkNetwork_logger, "f"));
|
|
7036
|
+
}
|
|
6805
7037
|
announcer.start();
|
|
6806
7038
|
// Create remote and local databases
|
|
6807
7039
|
const remotedb = new remotedb_1.default(__classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f"), vcdj);
|
|
6808
|
-
const localdb = new localdb_1.default(vcdj, __classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f"), __classPrivateFieldGet(this, _ProlinkNetwork_statusEmitter, "f"), (
|
|
7040
|
+
const localdb = new localdb_1.default(vcdj, __classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f"), __classPrivateFieldGet(this, _ProlinkNetwork_statusEmitter, "f"), (_f = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").databasePreference) !== null && _f !== void 0 ? _f : 'auto');
|
|
6809
7041
|
// Create unified database
|
|
6810
7042
|
const database = new db_1.default(localdb, remotedb, __classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f"));
|
|
6811
7043
|
// Create controller service
|
|
@@ -10062,7 +10294,11 @@ class PassiveStatusEmitter {
|
|
|
10062
10294
|
constructor(adapter) {
|
|
10063
10295
|
_PassiveStatusEmitter_emitter.set(this, new events_1.EventEmitter());
|
|
10064
10296
|
_PassiveStatusEmitter_adapter.set(this, void 0);
|
|
10065
|
-
// Bind public event emitter interface
|
|
10297
|
+
// Bind public event emitter interface. Use explicit generic signatures keyed
|
|
10298
|
+
// on StatusEvents rather than `Emitter['on']`: extracting the indexed `on`
|
|
10299
|
+
// type out of strict-event-emitter-types degrades to its unique-symbol
|
|
10300
|
+
// compatibility overload under newer TypeScript, so consumers calling
|
|
10301
|
+
// `.on('status', …)` would fail to typecheck. The runtime is unchanged.
|
|
10066
10302
|
this.on = __classPrivateFieldGet(this, _PassiveStatusEmitter_emitter, "f").addListener.bind(__classPrivateFieldGet(this, _PassiveStatusEmitter_emitter, "f"));
|
|
10067
10303
|
this.off = __classPrivateFieldGet(this, _PassiveStatusEmitter_emitter, "f").removeListener.bind(__classPrivateFieldGet(this, _PassiveStatusEmitter_emitter, "f"));
|
|
10068
10304
|
this.once = __classPrivateFieldGet(this, _PassiveStatusEmitter_emitter, "f").once.bind(__classPrivateFieldGet(this, _PassiveStatusEmitter_emitter, "f"));
|
|
@@ -10601,11 +10837,11 @@ exports["default"] = RemoteDatabase;
|
|
|
10601
10837
|
|
|
10602
10838
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10603
10839
|
exports.Message = void 0;
|
|
10604
|
-
const telemetry_1 = __webpack_require__(/*! src/utils/telemetry */ "./src/utils/telemetry.ts");
|
|
10605
10840
|
const constants_1 = __webpack_require__(/*! src/remotedb/constants */ "./src/remotedb/constants.ts");
|
|
10606
10841
|
const fields_1 = __webpack_require__(/*! src/remotedb/fields */ "./src/remotedb/fields.ts");
|
|
10607
10842
|
const response_1 = __webpack_require__(/*! src/remotedb/message/response */ "./src/remotedb/message/response.ts");
|
|
10608
10843
|
const types_1 = __webpack_require__(/*! src/remotedb/message/types */ "./src/remotedb/message/types.ts");
|
|
10844
|
+
const telemetry_1 = __webpack_require__(/*! src/utils/telemetry */ "./src/utils/telemetry.ts");
|
|
10609
10845
|
/**
|
|
10610
10846
|
* Argument types are used in argument list fields. This is essentially
|
|
10611
10847
|
* duplicating the field type, but has different values for whatever reason.
|
|
@@ -11680,11 +11916,22 @@ class StatusEmitter {
|
|
|
11680
11916
|
* Lock used to avoid media slot query races
|
|
11681
11917
|
*/
|
|
11682
11918
|
_StatusEmitter_mediaSlotQueryLock.set(this, new async_mutex_1.Mutex());
|
|
11683
|
-
// Bind public event emitter interface
|
|
11919
|
+
// Bind public event emitter interface. Use explicit generic signatures keyed
|
|
11920
|
+
// on StatusEvents rather than `Emitter['on']`: extracting the indexed `on`
|
|
11921
|
+
// type out of strict-event-emitter-types degrades to its unique-symbol
|
|
11922
|
+
// compatibility overload under newer TypeScript, so consumers calling
|
|
11923
|
+
// `.on('status', …)` would fail to typecheck. The runtime is unchanged.
|
|
11684
11924
|
this.on = __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").addListener.bind(__classPrivateFieldGet(this, _StatusEmitter_emitter, "f"));
|
|
11685
11925
|
this.off = __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").removeListener.bind(__classPrivateFieldGet(this, _StatusEmitter_emitter, "f"));
|
|
11686
11926
|
this.once = __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").once.bind(__classPrivateFieldGet(this, _StatusEmitter_emitter, "f"));
|
|
11687
11927
|
_StatusEmitter_handleStatus.set(this, (message) => {
|
|
11928
|
+
// Stagehand mixer state (type 0x39)
|
|
11929
|
+
if (message.length >= 11 && message[10] === 0x39) {
|
|
11930
|
+
const mixerState = (0, utils_1.mixerStateFromPacket)(message);
|
|
11931
|
+
if (mixerState !== undefined) {
|
|
11932
|
+
return __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").emit('mixerState', mixerState);
|
|
11933
|
+
}
|
|
11934
|
+
}
|
|
11688
11935
|
const status = (0, utils_1.statusFromPacket)(message);
|
|
11689
11936
|
if (status !== undefined) {
|
|
11690
11937
|
return __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").emit('status', status);
|
|
@@ -11808,6 +12055,14 @@ class PositionEmitter {
|
|
|
11808
12055
|
this.off = __classPrivateFieldGet(this, _PositionEmitter_emitter, "f").removeListener.bind(__classPrivateFieldGet(this, _PositionEmitter_emitter, "f"));
|
|
11809
12056
|
this.once = __classPrivateFieldGet(this, _PositionEmitter_emitter, "f").once.bind(__classPrivateFieldGet(this, _PositionEmitter_emitter, "f"));
|
|
11810
12057
|
_PositionEmitter_handlePosition.set(this, (message) => {
|
|
12058
|
+
// Stagehand VU meter (type 0x58)
|
|
12059
|
+
if (message.length >= 11 && message[10] === 0x58) {
|
|
12060
|
+
const vu = (0, utils_1.vuFromPacket)(message);
|
|
12061
|
+
if (vu !== undefined) {
|
|
12062
|
+
__classPrivateFieldGet(this, _PositionEmitter_emitter, "f").emit('vu', vu);
|
|
12063
|
+
return;
|
|
12064
|
+
}
|
|
12065
|
+
}
|
|
11811
12066
|
const position = (0, utils_1.positionFromPacket)(message);
|
|
11812
12067
|
if (position !== undefined) {
|
|
11813
12068
|
__classPrivateFieldGet(this, _PositionEmitter_emitter, "f").emit('position', position);
|
|
@@ -11876,6 +12131,8 @@ exports.statusFromPacket = statusFromPacket;
|
|
|
11876
12131
|
exports.mediaSlotFromPacket = mediaSlotFromPacket;
|
|
11877
12132
|
exports.positionFromPacket = positionFromPacket;
|
|
11878
12133
|
exports.onAirFromPacket = onAirFromPacket;
|
|
12134
|
+
exports.mixerStateFromPacket = mixerStateFromPacket;
|
|
12135
|
+
exports.vuFromPacket = vuFromPacket;
|
|
11879
12136
|
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
11880
12137
|
const types_1 = __webpack_require__(/*! src/types */ "./src/types.ts");
|
|
11881
12138
|
const MAX_INT32 = Math.pow(2, 32) - 1;
|
|
@@ -12058,6 +12315,83 @@ function onAirFromPacket(packet) {
|
|
|
12058
12315
|
}
|
|
12059
12316
|
return undefined;
|
|
12060
12317
|
}
|
|
12318
|
+
/**
|
|
12319
|
+
* Parse unicast mixer state packet from DJM-A9 (packet type 0x39 on port 50002).
|
|
12320
|
+
*/
|
|
12321
|
+
function mixerStateFromPacket(packet) {
|
|
12322
|
+
if (packet.indexOf(constants_1.PROLINK_HEADER) !== 0) {
|
|
12323
|
+
return undefined;
|
|
12324
|
+
}
|
|
12325
|
+
// Verify packet type 0x39
|
|
12326
|
+
if (packet[10] !== 0x39) {
|
|
12327
|
+
return undefined;
|
|
12328
|
+
}
|
|
12329
|
+
if (packet.length < 266) {
|
|
12330
|
+
return undefined;
|
|
12331
|
+
}
|
|
12332
|
+
const deviceName = packet.slice(11, 30).toString().replace(/\0/g, '').trim();
|
|
12333
|
+
const crossfader = packet[180];
|
|
12334
|
+
const channels = {};
|
|
12335
|
+
for (let ch = 1; ch <= 4; ch++) {
|
|
12336
|
+
const offset = 36 + (ch - 1) * 24;
|
|
12337
|
+
let crossfaderAssign = 'thru';
|
|
12338
|
+
const assignVal = packet[offset + 12];
|
|
12339
|
+
if (assignVal === 0x01) {
|
|
12340
|
+
crossfaderAssign = 'A';
|
|
12341
|
+
}
|
|
12342
|
+
else if (assignVal === 0x02) {
|
|
12343
|
+
crossfaderAssign = 'B';
|
|
12344
|
+
}
|
|
12345
|
+
channels[ch] = {
|
|
12346
|
+
trim: packet[offset + 1],
|
|
12347
|
+
eqHi: packet[offset + 3],
|
|
12348
|
+
eqMid: packet[offset + 4],
|
|
12349
|
+
eqLow: packet[offset + 6],
|
|
12350
|
+
colorFx: packet[offset + 7],
|
|
12351
|
+
fader: packet[offset + 11],
|
|
12352
|
+
crossfaderAssign,
|
|
12353
|
+
};
|
|
12354
|
+
}
|
|
12355
|
+
return {
|
|
12356
|
+
deviceId: 33, // Mixers are typically device 33 on ProDJLink
|
|
12357
|
+
deviceName,
|
|
12358
|
+
channels,
|
|
12359
|
+
crossfader,
|
|
12360
|
+
};
|
|
12361
|
+
}
|
|
12362
|
+
/**
|
|
12363
|
+
* Parse unicast VU meter packet from DJM-A9 (packet type 0x58 on port 50001).
|
|
12364
|
+
* Contains 15 sample-tuples (16-bit BE left/right levels) per channel.
|
|
12365
|
+
*/
|
|
12366
|
+
function vuFromPacket(packet) {
|
|
12367
|
+
if (packet.indexOf(constants_1.PROLINK_HEADER) !== 0) {
|
|
12368
|
+
return undefined;
|
|
12369
|
+
}
|
|
12370
|
+
// Verify packet type 0x58
|
|
12371
|
+
if (packet[10] !== 0x58) {
|
|
12372
|
+
return undefined;
|
|
12373
|
+
}
|
|
12374
|
+
if (packet.length < 584) {
|
|
12375
|
+
return undefined;
|
|
12376
|
+
}
|
|
12377
|
+
const channels = {};
|
|
12378
|
+
for (let ch = 1; ch <= 4; ch++) {
|
|
12379
|
+
const chOffset = 44 + (ch - 1) * 60; // 15 frames * 4 bytes per frame = 60 bytes
|
|
12380
|
+
const frames = [];
|
|
12381
|
+
for (let i = 0; i < 15; i++) {
|
|
12382
|
+
const frameOffset = chOffset + i * 4;
|
|
12383
|
+
frames.push({
|
|
12384
|
+
left: packet.readUInt16BE(frameOffset),
|
|
12385
|
+
right: packet.readUInt16BE(frameOffset + 2),
|
|
12386
|
+
});
|
|
12387
|
+
}
|
|
12388
|
+
channels[ch] = frames;
|
|
12389
|
+
}
|
|
12390
|
+
return {
|
|
12391
|
+
deviceId: 33, // Mixers are typically device 33 on ProDJLink
|
|
12392
|
+
channels,
|
|
12393
|
+
};
|
|
12394
|
+
}
|
|
12061
12395
|
|
|
12062
12396
|
|
|
12063
12397
|
/***/ },
|
|
@@ -12114,6 +12448,7 @@ var DeviceType;
|
|
|
12114
12448
|
DeviceType[DeviceType["CDJ"] = 1] = "CDJ";
|
|
12115
12449
|
DeviceType[DeviceType["Mixer"] = 3] = "Mixer";
|
|
12116
12450
|
DeviceType[DeviceType["Rekordbox"] = 4] = "Rekordbox";
|
|
12451
|
+
DeviceType[DeviceType["Stagehand"] = 5] = "Stagehand";
|
|
12117
12452
|
})(DeviceType || (exports.DeviceType = DeviceType = {}));
|
|
12118
12453
|
var MediaColor;
|
|
12119
12454
|
(function (MediaColor) {
|
|
@@ -12154,9 +12489,6 @@ var TrackType;
|
|
|
12154
12489
|
TrackType[TrackType["AudioCD"] = 5] = "AudioCD";
|
|
12155
12490
|
TrackType[TrackType["Streaming"] = 6] = "Streaming";
|
|
12156
12491
|
})(TrackType || (exports.TrackType = TrackType = {}));
|
|
12157
|
-
/**
|
|
12158
|
-
* Re-export cue types from onelibrary-connect
|
|
12159
|
-
*/
|
|
12160
12492
|
var onelibrary_connect_1 = __webpack_require__(/*! onelibrary-connect */ "onelibrary-connect");
|
|
12161
12493
|
Object.defineProperty(exports, "CueColor", ({ enumerable: true, get: function () { return onelibrary_connect_1.CueColor; } }));
|
|
12162
12494
|
Object.defineProperty(exports, "HotcueButton", ({ enumerable: true, get: function () { return onelibrary_connect_1.HotcueButton; } }));
|
|
@@ -12613,6 +12945,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
12613
12945
|
return result;
|
|
12614
12946
|
};
|
|
12615
12947
|
})();
|
|
12948
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
12949
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
12950
|
+
};
|
|
12616
12951
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12617
12952
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
12618
12953
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
@@ -13105,6 +13440,271 @@ _Announcer_announceSocket = new WeakMap(), _Announcer_deviceManager = new WeakMa
|
|
|
13105
13440
|
// Then schedule regular keep-alives
|
|
13106
13441
|
__classPrivateFieldSet(this, _Announcer_intervalHandle, setInterval(sendKeepAlive, constants_1.ANNOUNCE_INTERVAL), "f");
|
|
13107
13442
|
};
|
|
13443
|
+
__exportStar(__webpack_require__(/*! ./stagehand */ "./src/virtualcdj/stagehand.ts"), exports);
|
|
13444
|
+
|
|
13445
|
+
|
|
13446
|
+
/***/ },
|
|
13447
|
+
|
|
13448
|
+
/***/ "./src/virtualcdj/stagehand.ts"
|
|
13449
|
+
/*!*************************************!*\
|
|
13450
|
+
!*** ./src/virtualcdj/stagehand.ts ***!
|
|
13451
|
+
\*************************************/
|
|
13452
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
13453
|
+
|
|
13454
|
+
"use strict";
|
|
13455
|
+
|
|
13456
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13457
|
+
if (k2 === undefined) k2 = k;
|
|
13458
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13459
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13460
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13461
|
+
}
|
|
13462
|
+
Object.defineProperty(o, k2, desc);
|
|
13463
|
+
}) : (function(o, m, k, k2) {
|
|
13464
|
+
if (k2 === undefined) k2 = k;
|
|
13465
|
+
o[k2] = m[k];
|
|
13466
|
+
}));
|
|
13467
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
13468
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
13469
|
+
}) : function(o, v) {
|
|
13470
|
+
o["default"] = v;
|
|
13471
|
+
});
|
|
13472
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
13473
|
+
var ownKeys = function(o) {
|
|
13474
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
13475
|
+
var ar = [];
|
|
13476
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
13477
|
+
return ar;
|
|
13478
|
+
};
|
|
13479
|
+
return ownKeys(o);
|
|
13480
|
+
};
|
|
13481
|
+
return function (mod) {
|
|
13482
|
+
if (mod && mod.__esModule) return mod;
|
|
13483
|
+
var result = {};
|
|
13484
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
13485
|
+
__setModuleDefault(result, mod);
|
|
13486
|
+
return result;
|
|
13487
|
+
};
|
|
13488
|
+
})();
|
|
13489
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
13490
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13491
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
13492
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
13493
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
13494
|
+
};
|
|
13495
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
13496
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
13497
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
13498
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
13499
|
+
};
|
|
13500
|
+
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;
|
|
13501
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
13502
|
+
exports.StagehandAnnouncer = exports.getVirtualStagehand = exports.StagehandStartupStage = exports.STAGEHAND_KEEP_ALIVE_INTERVAL = exports.STAGEHAND_STARTUP_INTERVAL = void 0;
|
|
13503
|
+
exports.generateStagehandMac = generateStagehandMac;
|
|
13504
|
+
exports.generateStagehandDeviceId = generateStagehandDeviceId;
|
|
13505
|
+
exports.makeStagehand0aPacket = makeStagehand0aPacket;
|
|
13506
|
+
exports.makeStagehand02Packet = makeStagehand02Packet;
|
|
13507
|
+
exports.makeStagehand06Packet = makeStagehand06Packet;
|
|
13508
|
+
const ip = __importStar(__webpack_require__(/*! ip-address */ "ip-address"));
|
|
13509
|
+
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
13510
|
+
const logger_1 = __webpack_require__(/*! src/logger */ "./src/logger.ts");
|
|
13511
|
+
const types_1 = __webpack_require__(/*! src/types */ "./src/types.ts");
|
|
13512
|
+
const utils_1 = __webpack_require__(/*! src/utils */ "./src/utils/index.ts");
|
|
13513
|
+
exports.STAGEHAND_STARTUP_INTERVAL = 305;
|
|
13514
|
+
exports.STAGEHAND_KEEP_ALIVE_INTERVAL = 2000;
|
|
13515
|
+
var StagehandStartupStage;
|
|
13516
|
+
(function (StagehandStartupStage) {
|
|
13517
|
+
StagehandStartupStage[StagehandStartupStage["InitialAnnounce"] = 10] = "InitialAnnounce";
|
|
13518
|
+
StagehandStartupStage[StagehandStartupStage["SecondStageClaim"] = 2] = "SecondStageClaim";
|
|
13519
|
+
StagehandStartupStage[StagehandStartupStage["KeepAlive"] = 6] = "KeepAlive";
|
|
13520
|
+
})(StagehandStartupStage || (exports.StagehandStartupStage = StagehandStartupStage = {}));
|
|
13521
|
+
/**
|
|
13522
|
+
* Generates a randomized MAC address with the AlphaTheta OUI (c8:3d:fc).
|
|
13523
|
+
*/
|
|
13524
|
+
function generateStagehandMac() {
|
|
13525
|
+
const mac = new Uint8Array(6);
|
|
13526
|
+
mac[0] = 0xc8;
|
|
13527
|
+
mac[1] = 0x3d;
|
|
13528
|
+
mac[2] = 0xfc;
|
|
13529
|
+
mac[3] = Math.floor(Math.random() * 256);
|
|
13530
|
+
mac[4] = Math.floor(Math.random() * 256);
|
|
13531
|
+
mac[5] = Math.floor(Math.random() * 256);
|
|
13532
|
+
return mac;
|
|
13533
|
+
}
|
|
13534
|
+
/**
|
|
13535
|
+
* Generates a random Stagehand device ID in the observed range of 141 to 211.
|
|
13536
|
+
*/
|
|
13537
|
+
function generateStagehandDeviceId() {
|
|
13538
|
+
return Math.floor(Math.random() * (211 - 141 + 1)) + 141;
|
|
13539
|
+
}
|
|
13540
|
+
/**
|
|
13541
|
+
* Constructs a virtual Stagehand Device.
|
|
13542
|
+
*
|
|
13543
|
+
* @param iface - The network interface to use
|
|
13544
|
+
* @param id - The device ID to use (defaults to random Stagehand ID)
|
|
13545
|
+
* @param name - The device name (defaults to 'Stagehand')
|
|
13546
|
+
* @param macAddr - The optional randomized MAC address
|
|
13547
|
+
*/
|
|
13548
|
+
const getVirtualStagehand = (iface, id = generateStagehandDeviceId(), name = 'Stagehand', macAddr = generateStagehandMac()) => ({
|
|
13549
|
+
id,
|
|
13550
|
+
name,
|
|
13551
|
+
type: types_1.DeviceType.Stagehand,
|
|
13552
|
+
ip: new ip.Address4(iface.address),
|
|
13553
|
+
macAddr,
|
|
13554
|
+
});
|
|
13555
|
+
exports.getVirtualStagehand = getVirtualStagehand;
|
|
13556
|
+
/**
|
|
13557
|
+
* Build Stagehand stage 0x0a packet: Initial announcement.
|
|
13558
|
+
* Sent 3 times at 305ms intervals.
|
|
13559
|
+
*/
|
|
13560
|
+
function makeStagehand0aPacket(device) {
|
|
13561
|
+
const parts = [
|
|
13562
|
+
...constants_1.PROLINK_HEADER, // 10 bytes
|
|
13563
|
+
...[0x0a, 0x00], // 2 bytes packet type (0x0a)
|
|
13564
|
+
...(0, utils_1.buildName)(device), // 20 bytes device name
|
|
13565
|
+
...[0x01, 0x03], // 2 bytes protocol / structure bytes
|
|
13566
|
+
...[0x00, 0x25], // 2 bytes packet length (37)
|
|
13567
|
+
...[types_1.DeviceType.Stagehand], // 1 byte device type (0x05)
|
|
13568
|
+
];
|
|
13569
|
+
return Uint8Array.from(parts);
|
|
13570
|
+
}
|
|
13571
|
+
/**
|
|
13572
|
+
* Build Stagehand stage 0x02 packet: Second-stage device number claim.
|
|
13573
|
+
* Sent 3 times at 305ms intervals with counter N (1, 2, 3).
|
|
13574
|
+
*/
|
|
13575
|
+
function makeStagehand02Packet(device, mac, counter) {
|
|
13576
|
+
const parts = [
|
|
13577
|
+
...constants_1.PROLINK_HEADER, // 10 bytes
|
|
13578
|
+
...[0x02, 0x00], // 2 bytes packet type (0x02)
|
|
13579
|
+
...(0, utils_1.buildName)(device), // 20 bytes device name
|
|
13580
|
+
...[0x01, 0x03], // 2 bytes protocol / structure bytes
|
|
13581
|
+
...[0x00, 0x32], // 2 bytes packet length (50)
|
|
13582
|
+
...device.ip.toArray(), // 4 bytes IP
|
|
13583
|
+
...mac, // 6 bytes identifier
|
|
13584
|
+
...[0x3a], // 1 byte constant
|
|
13585
|
+
...[counter], // 1 byte counter
|
|
13586
|
+
...[types_1.DeviceType.Stagehand], // 1 byte device type (0x05)
|
|
13587
|
+
...[0x01], // 1 byte constant
|
|
13588
|
+
];
|
|
13589
|
+
return Uint8Array.from(parts);
|
|
13590
|
+
}
|
|
13591
|
+
/**
|
|
13592
|
+
* Build Stagehand stage 0x06 packet: Keep-alive.
|
|
13593
|
+
* Sent every 2.0s after startup complete.
|
|
13594
|
+
*/
|
|
13595
|
+
function makeStagehand06Packet(device, mac) {
|
|
13596
|
+
const parts = [
|
|
13597
|
+
...constants_1.PROLINK_HEADER, // 10 bytes
|
|
13598
|
+
...[0x06, 0x00], // 2 bytes packet type (0x06)
|
|
13599
|
+
...(0, utils_1.buildName)(device), // 20 bytes device name
|
|
13600
|
+
...[0x01, 0x03], // 2 bytes protocol / structure bytes
|
|
13601
|
+
...[0x00, 0x36], // 2 bytes packet length (54)
|
|
13602
|
+
...[device.id], // 1 byte device number
|
|
13603
|
+
...[0x01], // 1 byte constant
|
|
13604
|
+
...mac, // 6 bytes identifier
|
|
13605
|
+
...device.ip.toArray(), // 4 bytes IP
|
|
13606
|
+
...[0x01, 0x00, 0x00, 0x00], // 4 bytes constant
|
|
13607
|
+
...[types_1.DeviceType.Stagehand], // 1 byte device-type (0x05)
|
|
13608
|
+
...[0x20], // 1 byte trailing byte
|
|
13609
|
+
];
|
|
13610
|
+
return Uint8Array.from(parts);
|
|
13611
|
+
}
|
|
13612
|
+
class StagehandAnnouncer {
|
|
13613
|
+
constructor(vcdj, announceSocket, deviceManager, iface, logger = logger_1.noopLogger) {
|
|
13614
|
+
_StagehandAnnouncer_instances.add(this);
|
|
13615
|
+
_StagehandAnnouncer_announceSocket.set(this, void 0);
|
|
13616
|
+
_StagehandAnnouncer_vcdj.set(this, void 0);
|
|
13617
|
+
_StagehandAnnouncer_intervalHandle.set(this, void 0);
|
|
13618
|
+
_StagehandAnnouncer_currentStage.set(this, StagehandStartupStage.InitialAnnounce);
|
|
13619
|
+
_StagehandAnnouncer_stageCounter.set(this, 0);
|
|
13620
|
+
_StagehandAnnouncer_iface.set(this, void 0);
|
|
13621
|
+
_StagehandAnnouncer_logger.set(this, void 0);
|
|
13622
|
+
_StagehandAnnouncer_onStartupComplete.set(this, void 0);
|
|
13623
|
+
_StagehandAnnouncer_mac.set(this, void 0);
|
|
13624
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_vcdj, vcdj, "f");
|
|
13625
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_announceSocket, announceSocket, "f");
|
|
13626
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_iface, iface, "f");
|
|
13627
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_logger, logger, "f");
|
|
13628
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_mac, vcdj.macAddr, "f");
|
|
13629
|
+
}
|
|
13630
|
+
get ready() {
|
|
13631
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_currentStage, "f") === StagehandStartupStage.KeepAlive) {
|
|
13632
|
+
return Promise.resolve();
|
|
13633
|
+
}
|
|
13634
|
+
return new Promise(resolve => {
|
|
13635
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_onStartupComplete, resolve, "f");
|
|
13636
|
+
});
|
|
13637
|
+
}
|
|
13638
|
+
start() {
|
|
13639
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").info(`Starting Stagehand announcer: device name "${__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f").name}", ID ${__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f").id}`);
|
|
13640
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_startStartup).call(this);
|
|
13641
|
+
}
|
|
13642
|
+
stop() {
|
|
13643
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").info('Stopping Stagehand announcer');
|
|
13644
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f") !== undefined) {
|
|
13645
|
+
clearInterval(__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f"));
|
|
13646
|
+
clearTimeout(__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f"));
|
|
13647
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, undefined, "f");
|
|
13648
|
+
}
|
|
13649
|
+
}
|
|
13650
|
+
}
|
|
13651
|
+
exports.StagehandAnnouncer = StagehandAnnouncer;
|
|
13652
|
+
_StagehandAnnouncer_announceSocket = new WeakMap(), _StagehandAnnouncer_vcdj = new WeakMap(), _StagehandAnnouncer_intervalHandle = new WeakMap(), _StagehandAnnouncer_currentStage = new WeakMap(), _StagehandAnnouncer_stageCounter = new WeakMap(), _StagehandAnnouncer_iface = new WeakMap(), _StagehandAnnouncer_logger = new WeakMap(), _StagehandAnnouncer_onStartupComplete = new WeakMap(), _StagehandAnnouncer_mac = new WeakMap(), _StagehandAnnouncer_instances = new WeakSet(), _StagehandAnnouncer_startStartup = function _StagehandAnnouncer_startStartup() {
|
|
13653
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_currentStage, StagehandStartupStage.InitialAnnounce, "f");
|
|
13654
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_stageCounter, 0, "f");
|
|
13655
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendStagePackets).call(this);
|
|
13656
|
+
}, _StagehandAnnouncer_sendPacket = function _StagehandAnnouncer_sendPacket(packet) {
|
|
13657
|
+
const broadcastAddr = (0, utils_1.getBroadcastAddress)(__classPrivateFieldGet(this, _StagehandAnnouncer_iface, "f"));
|
|
13658
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_announceSocket, "f").send(packet, constants_1.ANNOUNCE_PORT, broadcastAddr);
|
|
13659
|
+
}, _StagehandAnnouncer_sendStagePackets = function _StagehandAnnouncer_sendStagePackets() {
|
|
13660
|
+
var _a;
|
|
13661
|
+
var _b;
|
|
13662
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_stageCounter, (_b = __classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f"), _b++, _b), "f");
|
|
13663
|
+
let packet;
|
|
13664
|
+
switch (__classPrivateFieldGet(this, _StagehandAnnouncer_currentStage, "f")) {
|
|
13665
|
+
case StagehandStartupStage.InitialAnnounce:
|
|
13666
|
+
packet = makeStagehand0aPacket(__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f"));
|
|
13667
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").debug(`Stagehand sending stage 0x0a (announce) packet ${__classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f")}/3`);
|
|
13668
|
+
break;
|
|
13669
|
+
case StagehandStartupStage.SecondStageClaim:
|
|
13670
|
+
packet = makeStagehand02Packet(__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f"), __classPrivateFieldGet(this, _StagehandAnnouncer_mac, "f"), __classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f"));
|
|
13671
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").debug(`Stagehand sending stage 0x02 (claim) packet ${__classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f")}/3`);
|
|
13672
|
+
break;
|
|
13673
|
+
case StagehandStartupStage.KeepAlive:
|
|
13674
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").info('Stagehand join sequence complete, transitioning to keep-alive');
|
|
13675
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_startKeepAlive).call(this);
|
|
13676
|
+
(_a = __classPrivateFieldGet(this, _StagehandAnnouncer_onStartupComplete, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
13677
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_onStartupComplete, undefined, "f");
|
|
13678
|
+
return;
|
|
13679
|
+
}
|
|
13680
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendPacket).call(this, packet);
|
|
13681
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f") >= 3) {
|
|
13682
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_advanceStage).call(this);
|
|
13683
|
+
}
|
|
13684
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, setTimeout(() => __classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendStagePackets).call(this), exports.STAGEHAND_STARTUP_INTERVAL), "f");
|
|
13685
|
+
}, _StagehandAnnouncer_advanceStage = function _StagehandAnnouncer_advanceStage() {
|
|
13686
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_stageCounter, 0, "f");
|
|
13687
|
+
switch (__classPrivateFieldGet(this, _StagehandAnnouncer_currentStage, "f")) {
|
|
13688
|
+
case StagehandStartupStage.InitialAnnounce:
|
|
13689
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_currentStage, StagehandStartupStage.SecondStageClaim, "f");
|
|
13690
|
+
break;
|
|
13691
|
+
case StagehandStartupStage.SecondStageClaim:
|
|
13692
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_currentStage, StagehandStartupStage.KeepAlive, "f");
|
|
13693
|
+
break;
|
|
13694
|
+
}
|
|
13695
|
+
}, _StagehandAnnouncer_startKeepAlive = function _StagehandAnnouncer_startKeepAlive() {
|
|
13696
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f")) {
|
|
13697
|
+
clearTimeout(__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f"));
|
|
13698
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, undefined, "f");
|
|
13699
|
+
}
|
|
13700
|
+
const sendKeepAlive = () => {
|
|
13701
|
+
const packet = makeStagehand06Packet(__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f"), __classPrivateFieldGet(this, _StagehandAnnouncer_mac, "f"));
|
|
13702
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").debug('Stagehand sending keep-alive packet');
|
|
13703
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendPacket).call(this, packet);
|
|
13704
|
+
};
|
|
13705
|
+
sendKeepAlive();
|
|
13706
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, setInterval(sendKeepAlive, exports.STAGEHAND_KEEP_ALIVE_INTERVAL), "f");
|
|
13707
|
+
};
|
|
13108
13708
|
|
|
13109
13709
|
|
|
13110
13710
|
/***/ },
|