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/cli.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
|
|
|
@@ -750,19 +809,20 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
750
809
|
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");
|
|
751
810
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
752
811
|
};
|
|
753
|
-
var _Control_hostDevice, _Control_beatSocket;
|
|
812
|
+
var _Control_hostDevice, _Control_beatSocket, _Control_correlationByte;
|
|
754
813
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
755
814
|
exports.makePlaystatePacket = void 0;
|
|
756
815
|
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
757
816
|
const types_1 = __webpack_require__(/*! src/types */ "./src/types.ts");
|
|
758
817
|
const utils_1 = __webpack_require__(/*! src/utils */ "./src/utils/index.ts");
|
|
759
818
|
const udp_1 = __webpack_require__(/*! src/utils/udp */ "./src/utils/udp.ts");
|
|
819
|
+
const stagehand_1 = __webpack_require__(/*! ./stagehand */ "./src/control/stagehand.ts");
|
|
760
820
|
const STATE_MAP = {
|
|
761
821
|
[types_1.CDJStatus.PlayState.Cued]: 0x01,
|
|
762
822
|
[types_1.CDJStatus.PlayState.Playing]: 0x00,
|
|
763
823
|
};
|
|
764
824
|
/**
|
|
765
|
-
* Generates the packet used to control the playstate of CDJs
|
|
825
|
+
* Generates the packet used to control the playstate of CDJs in active connection mode
|
|
766
826
|
*/
|
|
767
827
|
const makePlaystatePacket = ({ hostDevice, device, playState }) => Uint8Array.from([
|
|
768
828
|
...constants_1.PROLINK_HEADER,
|
|
@@ -783,21 +843,174 @@ class Control {
|
|
|
783
843
|
* The socket used to send control packets
|
|
784
844
|
*/
|
|
785
845
|
_Control_beatSocket.set(this, void 0);
|
|
846
|
+
/**
|
|
847
|
+
* Randomized correlation byte per session for Stagehand commands
|
|
848
|
+
*/
|
|
849
|
+
_Control_correlationByte.set(this, void 0);
|
|
786
850
|
__classPrivateFieldSet(this, _Control_beatSocket, beatSocket, "f");
|
|
787
851
|
__classPrivateFieldSet(this, _Control_hostDevice, hostDevice, "f");
|
|
852
|
+
__classPrivateFieldSet(this, _Control_correlationByte, Math.floor(Math.random() * 256), "f");
|
|
788
853
|
}
|
|
789
854
|
/**
|
|
790
|
-
* Start or stop a CDJ on the network
|
|
855
|
+
* Start or stop a CDJ on the network.
|
|
856
|
+
* Delegates automatically to Stagehand-specific transport control if connected in Stagehand mode.
|
|
791
857
|
*/
|
|
792
858
|
async setPlayState(device, playState) {
|
|
859
|
+
if (__classPrivateFieldGet(this, _Control_hostDevice, "f").type === types_1.DeviceType.Stagehand) {
|
|
860
|
+
if (playState === types_1.CDJStatus.PlayState.Playing) {
|
|
861
|
+
await this.play(device);
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
await this.pause(device);
|
|
865
|
+
}
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
793
868
|
const packet = (0, exports.makePlaystatePacket)({ hostDevice: __classPrivateFieldGet(this, _Control_hostDevice, "f"), device, playState });
|
|
794
869
|
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), packet, constants_1.BEAT_PORT, device.ip.address);
|
|
795
870
|
}
|
|
871
|
+
/**
|
|
872
|
+
* Send Stagehand PLAY command (paired 0x0f and 0x14 packets)
|
|
873
|
+
*/
|
|
874
|
+
async play(device) {
|
|
875
|
+
const p1 = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x0f, true, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
876
|
+
const p2 = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x14, true, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
877
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p1, constants_1.BEAT_PORT, device.ip.address);
|
|
878
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p2, constants_1.BEAT_PORT, device.ip.address);
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Send Stagehand PAUSE command (paired 0x14 packet)
|
|
882
|
+
*/
|
|
883
|
+
async pause(device) {
|
|
884
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x14, false, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
885
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Send Stagehand SEEK forward command
|
|
889
|
+
* @param press - true to start seek, false to release
|
|
890
|
+
*/
|
|
891
|
+
async seekForward(device, press) {
|
|
892
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x1a, press, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
893
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Send Stagehand SEEK backward command
|
|
897
|
+
* @param press - true to start seek, false to release
|
|
898
|
+
*/
|
|
899
|
+
async seekBackward(device, press) {
|
|
900
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x1b, press, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
901
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Send Stagehand SKIP track command
|
|
905
|
+
* @param press - true to start skip, false to release
|
|
906
|
+
*/
|
|
907
|
+
async skip(device, press) {
|
|
908
|
+
const p = (0, stagehand_1.makeStagehandTransportPacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), 0x18, press, __classPrivateFieldGet(this, _Control_correlationByte, "f"));
|
|
909
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.BEAT_PORT, device.ip.address);
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Send Stagehand preference write command (0x6b packet) to port 50002
|
|
913
|
+
*/
|
|
914
|
+
async setPreference(device, options) {
|
|
915
|
+
const p = (0, stagehand_1.makeStagehandPrefWritePacket)(__classPrivateFieldGet(this, _Control_hostDevice, "f"), options);
|
|
916
|
+
await (0, udp_1.udpSend)(__classPrivateFieldGet(this, _Control_beatSocket, "f"), p, constants_1.STATUS_PORT, device.ip.address);
|
|
917
|
+
}
|
|
796
918
|
}
|
|
797
|
-
_Control_hostDevice = new WeakMap(), _Control_beatSocket = new WeakMap();
|
|
919
|
+
_Control_hostDevice = new WeakMap(), _Control_beatSocket = new WeakMap(), _Control_correlationByte = new WeakMap();
|
|
798
920
|
exports["default"] = Control;
|
|
799
921
|
|
|
800
922
|
|
|
923
|
+
/***/ },
|
|
924
|
+
|
|
925
|
+
/***/ "./src/control/stagehand.ts"
|
|
926
|
+
/*!**********************************!*\
|
|
927
|
+
!*** ./src/control/stagehand.ts ***!
|
|
928
|
+
\**********************************/
|
|
929
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
930
|
+
|
|
931
|
+
"use strict";
|
|
932
|
+
|
|
933
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
934
|
+
exports.makeStagehandTransportPacket = makeStagehandTransportPacket;
|
|
935
|
+
exports.makeStagehandPrefWritePacket = makeStagehandPrefWritePacket;
|
|
936
|
+
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
937
|
+
const utils_1 = __webpack_require__(/*! src/utils */ "./src/utils/index.ts");
|
|
938
|
+
/**
|
|
939
|
+
* Generates a Stagehand transport control packet (0x07, 56 bytes)
|
|
940
|
+
*
|
|
941
|
+
* @param hostDevice - The Stagehand device posing as sender
|
|
942
|
+
* @param op - The command opcode (e.g. 0x0f, 0x14, 0x18, 0x1a, 0x1b)
|
|
943
|
+
* @param press - Whether the action is press (true) or release (false)
|
|
944
|
+
* @param correlationByte - The randomized per-session correlation byte
|
|
945
|
+
*/
|
|
946
|
+
function makeStagehandTransportPacket(hostDevice, op, press, correlationByte) {
|
|
947
|
+
const packet = new Uint8Array(56);
|
|
948
|
+
// 0-9: magic header
|
|
949
|
+
packet.set(constants_1.PROLINK_HEADER, 0);
|
|
950
|
+
// 10: opcode 0x07
|
|
951
|
+
packet[10] = 0x07;
|
|
952
|
+
// 11-30: device name
|
|
953
|
+
packet.set((0, utils_1.buildName)(hostDevice), 11);
|
|
954
|
+
// 31: 0x01
|
|
955
|
+
packet[31] = 0x01;
|
|
956
|
+
// 32: 0x03
|
|
957
|
+
packet[32] = 0x03;
|
|
958
|
+
// 33: per-session correlation byte
|
|
959
|
+
packet[33] = correlationByte;
|
|
960
|
+
// 34-35: remaining length 0x0030 (48 bytes)
|
|
961
|
+
packet[34] = 0x00;
|
|
962
|
+
packet[35] = 0x30;
|
|
963
|
+
// 40: Stagehand sub-id 0x3a
|
|
964
|
+
packet[40] = 0x3a;
|
|
965
|
+
// 44: command opcode
|
|
966
|
+
packet[44] = op;
|
|
967
|
+
// 46: press/release flag
|
|
968
|
+
packet[46] = press ? 0x01 : 0x00;
|
|
969
|
+
return packet;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Generates a Stagehand preference write packet (0x6b, 124 bytes)
|
|
973
|
+
*
|
|
974
|
+
* @param hostDevice - The Stagehand device posing as sender
|
|
975
|
+
* @param options - The preferences to write (onAir, quantize)
|
|
976
|
+
*/
|
|
977
|
+
function makeStagehandPrefWritePacket(hostDevice, options) {
|
|
978
|
+
const packet = new Uint8Array(124);
|
|
979
|
+
// 0-9: magic header
|
|
980
|
+
packet.set(constants_1.PROLINK_HEADER, 0);
|
|
981
|
+
// 10: opcode 0x6b
|
|
982
|
+
packet[10] = 0x6b;
|
|
983
|
+
// 11-30: device name
|
|
984
|
+
const name = (0, utils_1.buildName)(hostDevice);
|
|
985
|
+
// Trailing byte 30 (which is offset 30, meaning index 19 of name) is set to 0x03
|
|
986
|
+
name[19] = 0x03;
|
|
987
|
+
packet.set(name, 11);
|
|
988
|
+
// 31: 0x01 (subscription-id-a constant)
|
|
989
|
+
packet[31] = 0x01;
|
|
990
|
+
// 32: 0x03 (constant)
|
|
991
|
+
packet[32] = 0x03;
|
|
992
|
+
// 33: Stagehand sub-id constant 0x3a
|
|
993
|
+
packet[33] = 0x3a;
|
|
994
|
+
// 34-35: body length 0x0050 (80 bytes)
|
|
995
|
+
packet[34] = 0x00;
|
|
996
|
+
packet[35] = 0x50;
|
|
997
|
+
// 36: transaction flag (0x01 = write)
|
|
998
|
+
packet[36] = 0x01;
|
|
999
|
+
// 44: on_air slot (0x80 = OFF, 0x81 = ON, 0x00 = untouched)
|
|
1000
|
+
if (options.onAir === 'on') {
|
|
1001
|
+
packet[44] = 0x81;
|
|
1002
|
+
}
|
|
1003
|
+
else if (options.onAir === 'off') {
|
|
1004
|
+
packet[44] = 0x80;
|
|
1005
|
+
}
|
|
1006
|
+
// 60: quantize slot (0x80 | enum_index, e.g. 0x81, 0x82 etc.)
|
|
1007
|
+
if (options.quantize !== undefined) {
|
|
1008
|
+
packet[60] = 0x80 | options.quantize;
|
|
1009
|
+
}
|
|
1010
|
+
return packet;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
|
|
801
1014
|
/***/ },
|
|
802
1015
|
|
|
803
1016
|
/***/ "./src/db/getArtworkFromFile.ts"
|
|
@@ -6577,14 +6790,15 @@ var _ProlinkNetwork_state, _ProlinkNetwork_announceSocket, _ProlinkNetwork_beatS
|
|
|
6577
6790
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6578
6791
|
exports.ProlinkNetwork = void 0;
|
|
6579
6792
|
exports.bringOnline = bringOnline;
|
|
6793
|
+
exports.bringOnlineStagehand = bringOnlineStagehand;
|
|
6580
6794
|
const crypto_1 = __webpack_require__(/*! crypto */ "crypto");
|
|
6581
6795
|
const dgram_1 = __importDefault(__webpack_require__(/*! dgram */ "dgram"));
|
|
6582
6796
|
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
6583
6797
|
const control_1 = __importDefault(__webpack_require__(/*! src/control */ "./src/control/index.ts"));
|
|
6584
6798
|
const db_1 = __importDefault(__webpack_require__(/*! src/db */ "./src/db/index.ts"));
|
|
6585
6799
|
const devices_1 = __importDefault(__webpack_require__(/*! src/devices */ "./src/devices/index.ts"));
|
|
6586
|
-
const logger_1 = __webpack_require__(/*! src/logger */ "./src/logger.ts");
|
|
6587
6800
|
const localdb_1 = __importDefault(__webpack_require__(/*! src/localdb */ "./src/localdb/index.ts"));
|
|
6801
|
+
const logger_1 = __webpack_require__(/*! src/logger */ "./src/logger.ts");
|
|
6588
6802
|
const mixstatus_1 = __webpack_require__(/*! src/mixstatus */ "./src/mixstatus/index.ts");
|
|
6589
6803
|
const remotedb_1 = __importDefault(__webpack_require__(/*! src/remotedb */ "./src/remotedb/index.ts"));
|
|
6590
6804
|
const status_1 = __importDefault(__webpack_require__(/*! src/status */ "./src/status/index.ts"));
|
|
@@ -6639,6 +6853,17 @@ async function bringOnline(config) {
|
|
|
6639
6853
|
});
|
|
6640
6854
|
return network;
|
|
6641
6855
|
}
|
|
6856
|
+
/**
|
|
6857
|
+
* Brings the Prolink network online using the Pioneer Stagehand connection method.
|
|
6858
|
+
*
|
|
6859
|
+
* This connects to the network as a non-player Stagehand device using its abbreviated handshake.
|
|
6860
|
+
*/
|
|
6861
|
+
async function bringOnlineStagehand(config) {
|
|
6862
|
+
return bringOnline({
|
|
6863
|
+
...config,
|
|
6864
|
+
connectMethod: 'stagehand',
|
|
6865
|
+
});
|
|
6866
|
+
}
|
|
6642
6867
|
class ProlinkNetwork {
|
|
6643
6868
|
/**
|
|
6644
6869
|
* @internal
|
|
@@ -6688,6 +6913,7 @@ class ProlinkNetwork {
|
|
|
6688
6913
|
* Defaults the Virtual CDJ ID to 7.
|
|
6689
6914
|
*/
|
|
6690
6915
|
async autoconfigFromPeers() {
|
|
6916
|
+
var _a;
|
|
6691
6917
|
const tx = Telemetry.startTransaction({ name: 'autoConfigure' });
|
|
6692
6918
|
// wait for first device to appear on the network
|
|
6693
6919
|
const firstDevice = await new Promise(resolve => __classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f").once('connected', resolve));
|
|
@@ -6703,7 +6929,10 @@ class ProlinkNetwork {
|
|
|
6703
6929
|
tx.finish();
|
|
6704
6930
|
throw new Error('Unable to determine network interface');
|
|
6705
6931
|
}
|
|
6706
|
-
|
|
6932
|
+
const defaultId = ((_a = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f")) === null || _a === void 0 ? void 0 : _a.connectMethod) === 'stagehand'
|
|
6933
|
+
? (0, virtualcdj_1.generateStagehandDeviceId)()
|
|
6934
|
+
: constants_1.DEFAULT_VCDJ_ID;
|
|
6935
|
+
__classPrivateFieldSet(this, _ProlinkNetwork_config, { ...__classPrivateFieldGet(this, _ProlinkNetwork_config, "f"), vcdjId: defaultId, iface }, "f");
|
|
6707
6936
|
tx.finish();
|
|
6708
6937
|
}
|
|
6709
6938
|
/**
|
|
@@ -6713,23 +6942,34 @@ class ProlinkNetwork {
|
|
|
6713
6942
|
* or manual configuration). This will then initialize all the network services.
|
|
6714
6943
|
*/
|
|
6715
6944
|
connect() {
|
|
6716
|
-
var _a, _b, _c;
|
|
6945
|
+
var _a, _b, _c, _d, _e, _f;
|
|
6717
6946
|
if (__classPrivateFieldGet(this, _ProlinkNetwork_config, "f") === null) {
|
|
6718
6947
|
throw new Error(connectErrorHelp);
|
|
6719
6948
|
}
|
|
6720
6949
|
const tx = Telemetry.startTransaction({ name: 'connect' });
|
|
6721
|
-
|
|
6722
|
-
const
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6950
|
+
const connectMethod = (_a = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").connectMethod) !== null && _a !== void 0 ? _a : 'active';
|
|
6951
|
+
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);
|
|
6952
|
+
const vcdjName = (_c = __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").vcdjName) !== null && _c !== void 0 ? _c : (connectMethod === 'stagehand' ? 'Stagehand' : undefined);
|
|
6953
|
+
// Create VCDJ or Stagehand device
|
|
6954
|
+
const vcdj = connectMethod === 'stagehand'
|
|
6955
|
+
? (0, virtualcdj_1.getVirtualStagehand)(__classPrivateFieldGet(this, _ProlinkNetwork_config, "f").iface, vcdjId, vcdjName)
|
|
6956
|
+
: (0, virtualcdj_1.getVirtualCDJ)(__classPrivateFieldGet(this, _ProlinkNetwork_config, "f").iface, vcdjId, vcdjName);
|
|
6957
|
+
// Update device manager to filter out our device name
|
|
6958
|
+
if (vcdjName !== undefined) {
|
|
6959
|
+
__classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f").reconfigure({ vcdjName });
|
|
6726
6960
|
}
|
|
6727
6961
|
// Start announcing
|
|
6728
|
-
|
|
6962
|
+
let announcer;
|
|
6963
|
+
if (connectMethod === 'stagehand') {
|
|
6964
|
+
announcer = new virtualcdj_1.StagehandAnnouncer(vcdj, __classPrivateFieldGet(this, _ProlinkNetwork_announceSocket, "f"), this.deviceManager, __classPrivateFieldGet(this, _ProlinkNetwork_config, "f").iface, __classPrivateFieldGet(this, _ProlinkNetwork_logger, "f"));
|
|
6965
|
+
}
|
|
6966
|
+
else {
|
|
6967
|
+
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"));
|
|
6968
|
+
}
|
|
6729
6969
|
announcer.start();
|
|
6730
6970
|
// Create remote and local databases
|
|
6731
6971
|
const remotedb = new remotedb_1.default(__classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f"), vcdj);
|
|
6732
|
-
const localdb = new localdb_1.default(vcdj, __classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f"), __classPrivateFieldGet(this, _ProlinkNetwork_statusEmitter, "f"), (
|
|
6972
|
+
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');
|
|
6733
6973
|
// Create unified database
|
|
6734
6974
|
const database = new db_1.default(localdb, remotedb, __classPrivateFieldGet(this, _ProlinkNetwork_deviceManager, "f"));
|
|
6735
6975
|
// Create controller service
|
|
@@ -8459,11 +8699,11 @@ exports["default"] = RemoteDatabase;
|
|
|
8459
8699
|
|
|
8460
8700
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
8461
8701
|
exports.Message = void 0;
|
|
8462
|
-
const telemetry_1 = __webpack_require__(/*! src/utils/telemetry */ "./src/utils/telemetry.ts");
|
|
8463
8702
|
const constants_1 = __webpack_require__(/*! src/remotedb/constants */ "./src/remotedb/constants.ts");
|
|
8464
8703
|
const fields_1 = __webpack_require__(/*! src/remotedb/fields */ "./src/remotedb/fields.ts");
|
|
8465
8704
|
const response_1 = __webpack_require__(/*! src/remotedb/message/response */ "./src/remotedb/message/response.ts");
|
|
8466
8705
|
const types_1 = __webpack_require__(/*! src/remotedb/message/types */ "./src/remotedb/message/types.ts");
|
|
8706
|
+
const telemetry_1 = __webpack_require__(/*! src/utils/telemetry */ "./src/utils/telemetry.ts");
|
|
8467
8707
|
/**
|
|
8468
8708
|
* Argument types are used in argument list fields. This is essentially
|
|
8469
8709
|
* duplicating the field type, but has different values for whatever reason.
|
|
@@ -9538,11 +9778,22 @@ class StatusEmitter {
|
|
|
9538
9778
|
* Lock used to avoid media slot query races
|
|
9539
9779
|
*/
|
|
9540
9780
|
_StatusEmitter_mediaSlotQueryLock.set(this, new async_mutex_1.Mutex());
|
|
9541
|
-
// Bind public event emitter interface
|
|
9781
|
+
// Bind public event emitter interface. Use explicit generic signatures keyed
|
|
9782
|
+
// on StatusEvents rather than `Emitter['on']`: extracting the indexed `on`
|
|
9783
|
+
// type out of strict-event-emitter-types degrades to its unique-symbol
|
|
9784
|
+
// compatibility overload under newer TypeScript, so consumers calling
|
|
9785
|
+
// `.on('status', …)` would fail to typecheck. The runtime is unchanged.
|
|
9542
9786
|
this.on = __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").addListener.bind(__classPrivateFieldGet(this, _StatusEmitter_emitter, "f"));
|
|
9543
9787
|
this.off = __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").removeListener.bind(__classPrivateFieldGet(this, _StatusEmitter_emitter, "f"));
|
|
9544
9788
|
this.once = __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").once.bind(__classPrivateFieldGet(this, _StatusEmitter_emitter, "f"));
|
|
9545
9789
|
_StatusEmitter_handleStatus.set(this, (message) => {
|
|
9790
|
+
// Stagehand mixer state (type 0x39)
|
|
9791
|
+
if (message.length >= 11 && message[10] === 0x39) {
|
|
9792
|
+
const mixerState = (0, utils_1.mixerStateFromPacket)(message);
|
|
9793
|
+
if (mixerState !== undefined) {
|
|
9794
|
+
return __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").emit('mixerState', mixerState);
|
|
9795
|
+
}
|
|
9796
|
+
}
|
|
9546
9797
|
const status = (0, utils_1.statusFromPacket)(message);
|
|
9547
9798
|
if (status !== undefined) {
|
|
9548
9799
|
return __classPrivateFieldGet(this, _StatusEmitter_emitter, "f").emit('status', status);
|
|
@@ -9666,6 +9917,14 @@ class PositionEmitter {
|
|
|
9666
9917
|
this.off = __classPrivateFieldGet(this, _PositionEmitter_emitter, "f").removeListener.bind(__classPrivateFieldGet(this, _PositionEmitter_emitter, "f"));
|
|
9667
9918
|
this.once = __classPrivateFieldGet(this, _PositionEmitter_emitter, "f").once.bind(__classPrivateFieldGet(this, _PositionEmitter_emitter, "f"));
|
|
9668
9919
|
_PositionEmitter_handlePosition.set(this, (message) => {
|
|
9920
|
+
// Stagehand VU meter (type 0x58)
|
|
9921
|
+
if (message.length >= 11 && message[10] === 0x58) {
|
|
9922
|
+
const vu = (0, utils_1.vuFromPacket)(message);
|
|
9923
|
+
if (vu !== undefined) {
|
|
9924
|
+
__classPrivateFieldGet(this, _PositionEmitter_emitter, "f").emit('vu', vu);
|
|
9925
|
+
return;
|
|
9926
|
+
}
|
|
9927
|
+
}
|
|
9669
9928
|
const position = (0, utils_1.positionFromPacket)(message);
|
|
9670
9929
|
if (position !== undefined) {
|
|
9671
9930
|
__classPrivateFieldGet(this, _PositionEmitter_emitter, "f").emit('position', position);
|
|
@@ -9734,6 +9993,8 @@ exports.statusFromPacket = statusFromPacket;
|
|
|
9734
9993
|
exports.mediaSlotFromPacket = mediaSlotFromPacket;
|
|
9735
9994
|
exports.positionFromPacket = positionFromPacket;
|
|
9736
9995
|
exports.onAirFromPacket = onAirFromPacket;
|
|
9996
|
+
exports.mixerStateFromPacket = mixerStateFromPacket;
|
|
9997
|
+
exports.vuFromPacket = vuFromPacket;
|
|
9737
9998
|
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
9738
9999
|
const types_1 = __webpack_require__(/*! src/types */ "./src/types.ts");
|
|
9739
10000
|
const MAX_INT32 = Math.pow(2, 32) - 1;
|
|
@@ -9916,6 +10177,83 @@ function onAirFromPacket(packet) {
|
|
|
9916
10177
|
}
|
|
9917
10178
|
return undefined;
|
|
9918
10179
|
}
|
|
10180
|
+
/**
|
|
10181
|
+
* Parse unicast mixer state packet from DJM-A9 (packet type 0x39 on port 50002).
|
|
10182
|
+
*/
|
|
10183
|
+
function mixerStateFromPacket(packet) {
|
|
10184
|
+
if (packet.indexOf(constants_1.PROLINK_HEADER) !== 0) {
|
|
10185
|
+
return undefined;
|
|
10186
|
+
}
|
|
10187
|
+
// Verify packet type 0x39
|
|
10188
|
+
if (packet[10] !== 0x39) {
|
|
10189
|
+
return undefined;
|
|
10190
|
+
}
|
|
10191
|
+
if (packet.length < 266) {
|
|
10192
|
+
return undefined;
|
|
10193
|
+
}
|
|
10194
|
+
const deviceName = packet.slice(11, 30).toString().replace(/\0/g, '').trim();
|
|
10195
|
+
const crossfader = packet[180];
|
|
10196
|
+
const channels = {};
|
|
10197
|
+
for (let ch = 1; ch <= 4; ch++) {
|
|
10198
|
+
const offset = 36 + (ch - 1) * 24;
|
|
10199
|
+
let crossfaderAssign = 'thru';
|
|
10200
|
+
const assignVal = packet[offset + 12];
|
|
10201
|
+
if (assignVal === 0x01) {
|
|
10202
|
+
crossfaderAssign = 'A';
|
|
10203
|
+
}
|
|
10204
|
+
else if (assignVal === 0x02) {
|
|
10205
|
+
crossfaderAssign = 'B';
|
|
10206
|
+
}
|
|
10207
|
+
channels[ch] = {
|
|
10208
|
+
trim: packet[offset + 1],
|
|
10209
|
+
eqHi: packet[offset + 3],
|
|
10210
|
+
eqMid: packet[offset + 4],
|
|
10211
|
+
eqLow: packet[offset + 6],
|
|
10212
|
+
colorFx: packet[offset + 7],
|
|
10213
|
+
fader: packet[offset + 11],
|
|
10214
|
+
crossfaderAssign,
|
|
10215
|
+
};
|
|
10216
|
+
}
|
|
10217
|
+
return {
|
|
10218
|
+
deviceId: 33, // Mixers are typically device 33 on ProDJLink
|
|
10219
|
+
deviceName,
|
|
10220
|
+
channels,
|
|
10221
|
+
crossfader,
|
|
10222
|
+
};
|
|
10223
|
+
}
|
|
10224
|
+
/**
|
|
10225
|
+
* Parse unicast VU meter packet from DJM-A9 (packet type 0x58 on port 50001).
|
|
10226
|
+
* Contains 15 sample-tuples (16-bit BE left/right levels) per channel.
|
|
10227
|
+
*/
|
|
10228
|
+
function vuFromPacket(packet) {
|
|
10229
|
+
if (packet.indexOf(constants_1.PROLINK_HEADER) !== 0) {
|
|
10230
|
+
return undefined;
|
|
10231
|
+
}
|
|
10232
|
+
// Verify packet type 0x58
|
|
10233
|
+
if (packet[10] !== 0x58) {
|
|
10234
|
+
return undefined;
|
|
10235
|
+
}
|
|
10236
|
+
if (packet.length < 584) {
|
|
10237
|
+
return undefined;
|
|
10238
|
+
}
|
|
10239
|
+
const channels = {};
|
|
10240
|
+
for (let ch = 1; ch <= 4; ch++) {
|
|
10241
|
+
const chOffset = 44 + (ch - 1) * 60; // 15 frames * 4 bytes per frame = 60 bytes
|
|
10242
|
+
const frames = [];
|
|
10243
|
+
for (let i = 0; i < 15; i++) {
|
|
10244
|
+
const frameOffset = chOffset + i * 4;
|
|
10245
|
+
frames.push({
|
|
10246
|
+
left: packet.readUInt16BE(frameOffset),
|
|
10247
|
+
right: packet.readUInt16BE(frameOffset + 2),
|
|
10248
|
+
});
|
|
10249
|
+
}
|
|
10250
|
+
channels[ch] = frames;
|
|
10251
|
+
}
|
|
10252
|
+
return {
|
|
10253
|
+
deviceId: 33, // Mixers are typically device 33 on ProDJLink
|
|
10254
|
+
channels,
|
|
10255
|
+
};
|
|
10256
|
+
}
|
|
9919
10257
|
|
|
9920
10258
|
|
|
9921
10259
|
/***/ },
|
|
@@ -9972,6 +10310,7 @@ var DeviceType;
|
|
|
9972
10310
|
DeviceType[DeviceType["CDJ"] = 1] = "CDJ";
|
|
9973
10311
|
DeviceType[DeviceType["Mixer"] = 3] = "Mixer";
|
|
9974
10312
|
DeviceType[DeviceType["Rekordbox"] = 4] = "Rekordbox";
|
|
10313
|
+
DeviceType[DeviceType["Stagehand"] = 5] = "Stagehand";
|
|
9975
10314
|
})(DeviceType || (exports.DeviceType = DeviceType = {}));
|
|
9976
10315
|
var MediaColor;
|
|
9977
10316
|
(function (MediaColor) {
|
|
@@ -10012,9 +10351,6 @@ var TrackType;
|
|
|
10012
10351
|
TrackType[TrackType["AudioCD"] = 5] = "AudioCD";
|
|
10013
10352
|
TrackType[TrackType["Streaming"] = 6] = "Streaming";
|
|
10014
10353
|
})(TrackType || (exports.TrackType = TrackType = {}));
|
|
10015
|
-
/**
|
|
10016
|
-
* Re-export cue types from onelibrary-connect
|
|
10017
|
-
*/
|
|
10018
10354
|
var onelibrary_connect_1 = __webpack_require__(/*! onelibrary-connect */ "onelibrary-connect");
|
|
10019
10355
|
Object.defineProperty(exports, "CueColor", ({ enumerable: true, get: function () { return onelibrary_connect_1.CueColor; } }));
|
|
10020
10356
|
Object.defineProperty(exports, "HotcueButton", ({ enumerable: true, get: function () { return onelibrary_connect_1.HotcueButton; } }));
|
|
@@ -10471,6 +10807,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
10471
10807
|
return result;
|
|
10472
10808
|
};
|
|
10473
10809
|
})();
|
|
10810
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10811
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
10812
|
+
};
|
|
10474
10813
|
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
10475
10814
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
10476
10815
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
@@ -10963,6 +11302,271 @@ _Announcer_announceSocket = new WeakMap(), _Announcer_deviceManager = new WeakMa
|
|
|
10963
11302
|
// Then schedule regular keep-alives
|
|
10964
11303
|
__classPrivateFieldSet(this, _Announcer_intervalHandle, setInterval(sendKeepAlive, constants_1.ANNOUNCE_INTERVAL), "f");
|
|
10965
11304
|
};
|
|
11305
|
+
__exportStar(__webpack_require__(/*! ./stagehand */ "./src/virtualcdj/stagehand.ts"), exports);
|
|
11306
|
+
|
|
11307
|
+
|
|
11308
|
+
/***/ },
|
|
11309
|
+
|
|
11310
|
+
/***/ "./src/virtualcdj/stagehand.ts"
|
|
11311
|
+
/*!*************************************!*\
|
|
11312
|
+
!*** ./src/virtualcdj/stagehand.ts ***!
|
|
11313
|
+
\*************************************/
|
|
11314
|
+
(__unused_webpack_module, exports, __webpack_require__) {
|
|
11315
|
+
|
|
11316
|
+
"use strict";
|
|
11317
|
+
|
|
11318
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11319
|
+
if (k2 === undefined) k2 = k;
|
|
11320
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11321
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11322
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11323
|
+
}
|
|
11324
|
+
Object.defineProperty(o, k2, desc);
|
|
11325
|
+
}) : (function(o, m, k, k2) {
|
|
11326
|
+
if (k2 === undefined) k2 = k;
|
|
11327
|
+
o[k2] = m[k];
|
|
11328
|
+
}));
|
|
11329
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
11330
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11331
|
+
}) : function(o, v) {
|
|
11332
|
+
o["default"] = v;
|
|
11333
|
+
});
|
|
11334
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
11335
|
+
var ownKeys = function(o) {
|
|
11336
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
11337
|
+
var ar = [];
|
|
11338
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
11339
|
+
return ar;
|
|
11340
|
+
};
|
|
11341
|
+
return ownKeys(o);
|
|
11342
|
+
};
|
|
11343
|
+
return function (mod) {
|
|
11344
|
+
if (mod && mod.__esModule) return mod;
|
|
11345
|
+
var result = {};
|
|
11346
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
11347
|
+
__setModuleDefault(result, mod);
|
|
11348
|
+
return result;
|
|
11349
|
+
};
|
|
11350
|
+
})();
|
|
11351
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
11352
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
11353
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
11354
|
+
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");
|
|
11355
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11356
|
+
};
|
|
11357
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
11358
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
11359
|
+
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");
|
|
11360
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11361
|
+
};
|
|
11362
|
+
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;
|
|
11363
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
11364
|
+
exports.StagehandAnnouncer = exports.getVirtualStagehand = exports.StagehandStartupStage = exports.STAGEHAND_KEEP_ALIVE_INTERVAL = exports.STAGEHAND_STARTUP_INTERVAL = void 0;
|
|
11365
|
+
exports.generateStagehandMac = generateStagehandMac;
|
|
11366
|
+
exports.generateStagehandDeviceId = generateStagehandDeviceId;
|
|
11367
|
+
exports.makeStagehand0aPacket = makeStagehand0aPacket;
|
|
11368
|
+
exports.makeStagehand02Packet = makeStagehand02Packet;
|
|
11369
|
+
exports.makeStagehand06Packet = makeStagehand06Packet;
|
|
11370
|
+
const ip = __importStar(__webpack_require__(/*! ip-address */ "ip-address"));
|
|
11371
|
+
const constants_1 = __webpack_require__(/*! src/constants */ "./src/constants.ts");
|
|
11372
|
+
const logger_1 = __webpack_require__(/*! src/logger */ "./src/logger.ts");
|
|
11373
|
+
const types_1 = __webpack_require__(/*! src/types */ "./src/types.ts");
|
|
11374
|
+
const utils_1 = __webpack_require__(/*! src/utils */ "./src/utils/index.ts");
|
|
11375
|
+
exports.STAGEHAND_STARTUP_INTERVAL = 305;
|
|
11376
|
+
exports.STAGEHAND_KEEP_ALIVE_INTERVAL = 2000;
|
|
11377
|
+
var StagehandStartupStage;
|
|
11378
|
+
(function (StagehandStartupStage) {
|
|
11379
|
+
StagehandStartupStage[StagehandStartupStage["InitialAnnounce"] = 10] = "InitialAnnounce";
|
|
11380
|
+
StagehandStartupStage[StagehandStartupStage["SecondStageClaim"] = 2] = "SecondStageClaim";
|
|
11381
|
+
StagehandStartupStage[StagehandStartupStage["KeepAlive"] = 6] = "KeepAlive";
|
|
11382
|
+
})(StagehandStartupStage || (exports.StagehandStartupStage = StagehandStartupStage = {}));
|
|
11383
|
+
/**
|
|
11384
|
+
* Generates a randomized MAC address with the AlphaTheta OUI (c8:3d:fc).
|
|
11385
|
+
*/
|
|
11386
|
+
function generateStagehandMac() {
|
|
11387
|
+
const mac = new Uint8Array(6);
|
|
11388
|
+
mac[0] = 0xc8;
|
|
11389
|
+
mac[1] = 0x3d;
|
|
11390
|
+
mac[2] = 0xfc;
|
|
11391
|
+
mac[3] = Math.floor(Math.random() * 256);
|
|
11392
|
+
mac[4] = Math.floor(Math.random() * 256);
|
|
11393
|
+
mac[5] = Math.floor(Math.random() * 256);
|
|
11394
|
+
return mac;
|
|
11395
|
+
}
|
|
11396
|
+
/**
|
|
11397
|
+
* Generates a random Stagehand device ID in the observed range of 141 to 211.
|
|
11398
|
+
*/
|
|
11399
|
+
function generateStagehandDeviceId() {
|
|
11400
|
+
return Math.floor(Math.random() * (211 - 141 + 1)) + 141;
|
|
11401
|
+
}
|
|
11402
|
+
/**
|
|
11403
|
+
* Constructs a virtual Stagehand Device.
|
|
11404
|
+
*
|
|
11405
|
+
* @param iface - The network interface to use
|
|
11406
|
+
* @param id - The device ID to use (defaults to random Stagehand ID)
|
|
11407
|
+
* @param name - The device name (defaults to 'Stagehand')
|
|
11408
|
+
* @param macAddr - The optional randomized MAC address
|
|
11409
|
+
*/
|
|
11410
|
+
const getVirtualStagehand = (iface, id = generateStagehandDeviceId(), name = 'Stagehand', macAddr = generateStagehandMac()) => ({
|
|
11411
|
+
id,
|
|
11412
|
+
name,
|
|
11413
|
+
type: types_1.DeviceType.Stagehand,
|
|
11414
|
+
ip: new ip.Address4(iface.address),
|
|
11415
|
+
macAddr,
|
|
11416
|
+
});
|
|
11417
|
+
exports.getVirtualStagehand = getVirtualStagehand;
|
|
11418
|
+
/**
|
|
11419
|
+
* Build Stagehand stage 0x0a packet: Initial announcement.
|
|
11420
|
+
* Sent 3 times at 305ms intervals.
|
|
11421
|
+
*/
|
|
11422
|
+
function makeStagehand0aPacket(device) {
|
|
11423
|
+
const parts = [
|
|
11424
|
+
...constants_1.PROLINK_HEADER, // 10 bytes
|
|
11425
|
+
...[0x0a, 0x00], // 2 bytes packet type (0x0a)
|
|
11426
|
+
...(0, utils_1.buildName)(device), // 20 bytes device name
|
|
11427
|
+
...[0x01, 0x03], // 2 bytes protocol / structure bytes
|
|
11428
|
+
...[0x00, 0x25], // 2 bytes packet length (37)
|
|
11429
|
+
...[types_1.DeviceType.Stagehand], // 1 byte device type (0x05)
|
|
11430
|
+
];
|
|
11431
|
+
return Uint8Array.from(parts);
|
|
11432
|
+
}
|
|
11433
|
+
/**
|
|
11434
|
+
* Build Stagehand stage 0x02 packet: Second-stage device number claim.
|
|
11435
|
+
* Sent 3 times at 305ms intervals with counter N (1, 2, 3).
|
|
11436
|
+
*/
|
|
11437
|
+
function makeStagehand02Packet(device, mac, counter) {
|
|
11438
|
+
const parts = [
|
|
11439
|
+
...constants_1.PROLINK_HEADER, // 10 bytes
|
|
11440
|
+
...[0x02, 0x00], // 2 bytes packet type (0x02)
|
|
11441
|
+
...(0, utils_1.buildName)(device), // 20 bytes device name
|
|
11442
|
+
...[0x01, 0x03], // 2 bytes protocol / structure bytes
|
|
11443
|
+
...[0x00, 0x32], // 2 bytes packet length (50)
|
|
11444
|
+
...device.ip.toArray(), // 4 bytes IP
|
|
11445
|
+
...mac, // 6 bytes identifier
|
|
11446
|
+
...[0x3a], // 1 byte constant
|
|
11447
|
+
...[counter], // 1 byte counter
|
|
11448
|
+
...[types_1.DeviceType.Stagehand], // 1 byte device type (0x05)
|
|
11449
|
+
...[0x01], // 1 byte constant
|
|
11450
|
+
];
|
|
11451
|
+
return Uint8Array.from(parts);
|
|
11452
|
+
}
|
|
11453
|
+
/**
|
|
11454
|
+
* Build Stagehand stage 0x06 packet: Keep-alive.
|
|
11455
|
+
* Sent every 2.0s after startup complete.
|
|
11456
|
+
*/
|
|
11457
|
+
function makeStagehand06Packet(device, mac) {
|
|
11458
|
+
const parts = [
|
|
11459
|
+
...constants_1.PROLINK_HEADER, // 10 bytes
|
|
11460
|
+
...[0x06, 0x00], // 2 bytes packet type (0x06)
|
|
11461
|
+
...(0, utils_1.buildName)(device), // 20 bytes device name
|
|
11462
|
+
...[0x01, 0x03], // 2 bytes protocol / structure bytes
|
|
11463
|
+
...[0x00, 0x36], // 2 bytes packet length (54)
|
|
11464
|
+
...[device.id], // 1 byte device number
|
|
11465
|
+
...[0x01], // 1 byte constant
|
|
11466
|
+
...mac, // 6 bytes identifier
|
|
11467
|
+
...device.ip.toArray(), // 4 bytes IP
|
|
11468
|
+
...[0x01, 0x00, 0x00, 0x00], // 4 bytes constant
|
|
11469
|
+
...[types_1.DeviceType.Stagehand], // 1 byte device-type (0x05)
|
|
11470
|
+
...[0x20], // 1 byte trailing byte
|
|
11471
|
+
];
|
|
11472
|
+
return Uint8Array.from(parts);
|
|
11473
|
+
}
|
|
11474
|
+
class StagehandAnnouncer {
|
|
11475
|
+
constructor(vcdj, announceSocket, deviceManager, iface, logger = logger_1.noopLogger) {
|
|
11476
|
+
_StagehandAnnouncer_instances.add(this);
|
|
11477
|
+
_StagehandAnnouncer_announceSocket.set(this, void 0);
|
|
11478
|
+
_StagehandAnnouncer_vcdj.set(this, void 0);
|
|
11479
|
+
_StagehandAnnouncer_intervalHandle.set(this, void 0);
|
|
11480
|
+
_StagehandAnnouncer_currentStage.set(this, StagehandStartupStage.InitialAnnounce);
|
|
11481
|
+
_StagehandAnnouncer_stageCounter.set(this, 0);
|
|
11482
|
+
_StagehandAnnouncer_iface.set(this, void 0);
|
|
11483
|
+
_StagehandAnnouncer_logger.set(this, void 0);
|
|
11484
|
+
_StagehandAnnouncer_onStartupComplete.set(this, void 0);
|
|
11485
|
+
_StagehandAnnouncer_mac.set(this, void 0);
|
|
11486
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_vcdj, vcdj, "f");
|
|
11487
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_announceSocket, announceSocket, "f");
|
|
11488
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_iface, iface, "f");
|
|
11489
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_logger, logger, "f");
|
|
11490
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_mac, vcdj.macAddr, "f");
|
|
11491
|
+
}
|
|
11492
|
+
get ready() {
|
|
11493
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_currentStage, "f") === StagehandStartupStage.KeepAlive) {
|
|
11494
|
+
return Promise.resolve();
|
|
11495
|
+
}
|
|
11496
|
+
return new Promise(resolve => {
|
|
11497
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_onStartupComplete, resolve, "f");
|
|
11498
|
+
});
|
|
11499
|
+
}
|
|
11500
|
+
start() {
|
|
11501
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").info(`Starting Stagehand announcer: device name "${__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f").name}", ID ${__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f").id}`);
|
|
11502
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_startStartup).call(this);
|
|
11503
|
+
}
|
|
11504
|
+
stop() {
|
|
11505
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").info('Stopping Stagehand announcer');
|
|
11506
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f") !== undefined) {
|
|
11507
|
+
clearInterval(__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f"));
|
|
11508
|
+
clearTimeout(__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f"));
|
|
11509
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, undefined, "f");
|
|
11510
|
+
}
|
|
11511
|
+
}
|
|
11512
|
+
}
|
|
11513
|
+
exports.StagehandAnnouncer = StagehandAnnouncer;
|
|
11514
|
+
_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() {
|
|
11515
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_currentStage, StagehandStartupStage.InitialAnnounce, "f");
|
|
11516
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_stageCounter, 0, "f");
|
|
11517
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendStagePackets).call(this);
|
|
11518
|
+
}, _StagehandAnnouncer_sendPacket = function _StagehandAnnouncer_sendPacket(packet) {
|
|
11519
|
+
const broadcastAddr = (0, utils_1.getBroadcastAddress)(__classPrivateFieldGet(this, _StagehandAnnouncer_iface, "f"));
|
|
11520
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_announceSocket, "f").send(packet, constants_1.ANNOUNCE_PORT, broadcastAddr);
|
|
11521
|
+
}, _StagehandAnnouncer_sendStagePackets = function _StagehandAnnouncer_sendStagePackets() {
|
|
11522
|
+
var _a;
|
|
11523
|
+
var _b;
|
|
11524
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_stageCounter, (_b = __classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f"), _b++, _b), "f");
|
|
11525
|
+
let packet;
|
|
11526
|
+
switch (__classPrivateFieldGet(this, _StagehandAnnouncer_currentStage, "f")) {
|
|
11527
|
+
case StagehandStartupStage.InitialAnnounce:
|
|
11528
|
+
packet = makeStagehand0aPacket(__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f"));
|
|
11529
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").debug(`Stagehand sending stage 0x0a (announce) packet ${__classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f")}/3`);
|
|
11530
|
+
break;
|
|
11531
|
+
case StagehandStartupStage.SecondStageClaim:
|
|
11532
|
+
packet = makeStagehand02Packet(__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f"), __classPrivateFieldGet(this, _StagehandAnnouncer_mac, "f"), __classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f"));
|
|
11533
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").debug(`Stagehand sending stage 0x02 (claim) packet ${__classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f")}/3`);
|
|
11534
|
+
break;
|
|
11535
|
+
case StagehandStartupStage.KeepAlive:
|
|
11536
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").info('Stagehand join sequence complete, transitioning to keep-alive');
|
|
11537
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_startKeepAlive).call(this);
|
|
11538
|
+
(_a = __classPrivateFieldGet(this, _StagehandAnnouncer_onStartupComplete, "f")) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
11539
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_onStartupComplete, undefined, "f");
|
|
11540
|
+
return;
|
|
11541
|
+
}
|
|
11542
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendPacket).call(this, packet);
|
|
11543
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_stageCounter, "f") >= 3) {
|
|
11544
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_advanceStage).call(this);
|
|
11545
|
+
}
|
|
11546
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, setTimeout(() => __classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendStagePackets).call(this), exports.STAGEHAND_STARTUP_INTERVAL), "f");
|
|
11547
|
+
}, _StagehandAnnouncer_advanceStage = function _StagehandAnnouncer_advanceStage() {
|
|
11548
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_stageCounter, 0, "f");
|
|
11549
|
+
switch (__classPrivateFieldGet(this, _StagehandAnnouncer_currentStage, "f")) {
|
|
11550
|
+
case StagehandStartupStage.InitialAnnounce:
|
|
11551
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_currentStage, StagehandStartupStage.SecondStageClaim, "f");
|
|
11552
|
+
break;
|
|
11553
|
+
case StagehandStartupStage.SecondStageClaim:
|
|
11554
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_currentStage, StagehandStartupStage.KeepAlive, "f");
|
|
11555
|
+
break;
|
|
11556
|
+
}
|
|
11557
|
+
}, _StagehandAnnouncer_startKeepAlive = function _StagehandAnnouncer_startKeepAlive() {
|
|
11558
|
+
if (__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f")) {
|
|
11559
|
+
clearTimeout(__classPrivateFieldGet(this, _StagehandAnnouncer_intervalHandle, "f"));
|
|
11560
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, undefined, "f");
|
|
11561
|
+
}
|
|
11562
|
+
const sendKeepAlive = () => {
|
|
11563
|
+
const packet = makeStagehand06Packet(__classPrivateFieldGet(this, _StagehandAnnouncer_vcdj, "f"), __classPrivateFieldGet(this, _StagehandAnnouncer_mac, "f"));
|
|
11564
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_logger, "f").debug('Stagehand sending keep-alive packet');
|
|
11565
|
+
__classPrivateFieldGet(this, _StagehandAnnouncer_instances, "m", _StagehandAnnouncer_sendPacket).call(this, packet);
|
|
11566
|
+
};
|
|
11567
|
+
sendKeepAlive();
|
|
11568
|
+
__classPrivateFieldSet(this, _StagehandAnnouncer_intervalHandle, setInterval(sendKeepAlive, exports.STAGEHAND_KEEP_ALIVE_INTERVAL), "f");
|
|
11569
|
+
};
|
|
10966
11570
|
|
|
10967
11571
|
|
|
10968
11572
|
/***/ },
|