alphatheta-connect 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli.js CHANGED
@@ -10806,7 +10806,8 @@ function udpClose(conn) {
10806
10806
  "use strict";
10807
10807
 
10808
10808
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10809
- exports.MAX_DEVICE_ID = exports.REMOTEDB_MAX_DEVICE_ID = void 0;
10809
+ exports.DEFAULT_MIXER_PLAYER_CEILING = exports.MIXER_PLAYER_CEILING = exports.MAX_DEVICE_ID = exports.REMOTEDB_MAX_DEVICE_ID = void 0;
10810
+ exports.playerNumberCeiling = playerNumberCeiling;
10810
10811
  exports.pickAvailableDeviceId = pickAvailableDeviceId;
10811
10812
  /**
10812
10813
  * The highest device ID a CDJ will answer remotedb queries from.
@@ -10819,6 +10820,100 @@ exports.REMOTEDB_MAX_DEVICE_ID = 6;
10819
10820
  * The highest device ID the prolink protocol allows.
10820
10821
  */
10821
10822
  exports.MAX_DEVICE_ID = 32;
10823
+ /**
10824
+ * `DeviceType.Mixer`, inlined so this module stays free of runtime imports —
10825
+ * it is re-exported into consumers' test environments, where pulling in the
10826
+ * whole type module (and its ip-address dependency) is dead weight.
10827
+ */
10828
+ const MIXER_DEVICE_TYPE = 0x03;
10829
+ /**
10830
+ * How many player numbers each mixer can hand out.
10831
+ *
10832
+ * Players take their number from the mixer channel they are plugged into, so
10833
+ * an N-channel mixer only ever produces players 1..N — and N+1 is the lowest
10834
+ * number that no player on that rig can claim.
10835
+ *
10836
+ * These are physical channel counts, deliberately NOT the `channelCount` in
10837
+ * the app's own capability table, which caps the DJM-V10 at 4 for its mixer
10838
+ * signal model. Capping here would put us on player 5 of a 6-channel rig,
10839
+ * which is the collision this table exists to avoid.
10840
+ */
10841
+ exports.MIXER_PLAYER_CEILING = {
10842
+ // 6-channel flagships — no player number in 1-6 is safe on these
10843
+ 'DJM-V10': 6,
10844
+ 'DJM-V10-LF': 6,
10845
+ // 4-channel
10846
+ 'DJM-A9': 4,
10847
+ 'DJM-900NXS2': 4,
10848
+ 'DJM-900NXS': 4,
10849
+ 'DJM-900SRT': 4,
10850
+ 'DJM-850': 4,
10851
+ 'DJM-800': 4,
10852
+ 'DJM-750MK2': 4,
10853
+ 'DJM-750': 4,
10854
+ 'DJM-TOUR1': 4,
10855
+ 'DJM-2000NXS': 4,
10856
+ 'DJM-2000': 4,
10857
+ EUPHONIA: 4,
10858
+ // 3-channel (2026)
10859
+ 'DJM-V5': 3,
10860
+ // 2-channel
10861
+ 'DJM-450': 2,
10862
+ 'DJM-350': 2,
10863
+ 'DJM-250MK2': 2,
10864
+ // All-in-ones: their built-in players occupy numbers too, so the ceiling is
10865
+ // however many decks the unit announces rather than its mixer channel count
10866
+ 'XDJ-XZ': 4,
10867
+ 'XDJ-AZ': 4,
10868
+ 'XDJ-RX3': 2,
10869
+ 'XDJ-RX2': 2,
10870
+ 'XDJ-RX': 2,
10871
+ 'XDJ-AN': 2,
10872
+ 'OPUS-QUAD': 4,
10873
+ };
10874
+ /**
10875
+ * What to assume about a mixer whose model we do not recognise.
10876
+ *
10877
+ * Four is both the most common layout and the choice that keeps remotedb
10878
+ * metadata working: assuming six would push us to player 7 on every mixer
10879
+ * released after this table was written, silently losing metadata for
10880
+ * unanalyzed and streaming tracks. A six-channel unit we failed to recognise
10881
+ * may later claim the number we took, which the announcer's conflict handling
10882
+ * resolves by moving us.
10883
+ */
10884
+ exports.DEFAULT_MIXER_PLAYER_CEILING = 4;
10885
+ /**
10886
+ * The highest player number the discovered gear can hand out, or undefined
10887
+ * when nothing on the network implies one.
10888
+ *
10889
+ * Undefined means we have no mixer to reason from — players may have been
10890
+ * numbered by hand anywhere in 1-6, and there is no better guess available.
10891
+ */
10892
+ function playerNumberCeiling(devices) {
10893
+ let ceiling;
10894
+ for (const device of devices) {
10895
+ const known = exports.MIXER_PLAYER_CEILING[device.name.trim().toUpperCase()];
10896
+ const value = known !== null && known !== void 0 ? known : (device.type === MIXER_DEVICE_TYPE ? exports.DEFAULT_MIXER_PLAYER_CEILING : undefined);
10897
+ if (value !== undefined && (ceiling === undefined || value > ceiling)) {
10898
+ ceiling = value;
10899
+ }
10900
+ }
10901
+ return ceiling;
10902
+ }
10903
+ const descending = (from, to) => {
10904
+ const ids = [];
10905
+ for (let id = from; id >= to; id--) {
10906
+ ids.push(id);
10907
+ }
10908
+ return ids;
10909
+ };
10910
+ const ascending = (from, to) => {
10911
+ const ids = [];
10912
+ for (let id = from; id <= to; id++) {
10913
+ ids.push(id);
10914
+ }
10915
+ return ids;
10916
+ };
10822
10917
  /**
10823
10918
  * Pick a device ID that no device on the network is currently using.
10824
10919
  *
@@ -10829,20 +10924,22 @@ exports.MAX_DEVICE_ID = 32;
10829
10924
  * Returns null when every ID from 1 to 32 is occupied, in which case there is
10830
10925
  * no safe ID and the caller must not join the network.
10831
10926
  */
10832
- function pickAvailableDeviceId(usedIds, { preferRemoteDb = false } = {}) {
10927
+ function pickAvailableDeviceId(usedIds, { preferRemoteDb = false, playerCeiling } = {}) {
10833
10928
  var _a;
10834
10929
  const used = new Set(usedIds);
10835
- const remoteDbRange = [];
10836
- for (let id = exports.REMOTEDB_MAX_DEVICE_ID; id >= 1; id--) {
10837
- remoteDbRange.push(id);
10838
- }
10839
- const highRange = [];
10840
- for (let id = exports.REMOTEDB_MAX_DEVICE_ID + 1; id <= exports.MAX_DEVICE_ID; id++) {
10841
- highRange.push(id);
10842
- }
10930
+ const aboveThePlayers = playerCeiling === undefined
10931
+ ? descending(exports.REMOTEDB_MAX_DEVICE_ID, 1)
10932
+ : ascending(playerCeiling + 1, exports.REMOTEDB_MAX_DEVICE_ID);
10933
+ const outsideRemoteDb = ascending(exports.REMOTEDB_MAX_DEVICE_ID + 1, exports.MAX_DEVICE_ID);
10934
+ // Numbers a player on this rig could be assigned. Last resort: better to
10935
+ // contend for a slot than not to join at all, and the announcer moves us if
10936
+ // the player that owns it shows up.
10937
+ const amongThePlayers = playerCeiling === undefined
10938
+ ? []
10939
+ : descending(Math.min(playerCeiling, exports.REMOTEDB_MAX_DEVICE_ID), 1);
10843
10940
  const search = preferRemoteDb
10844
- ? [...remoteDbRange, ...highRange]
10845
- : [...highRange, ...remoteDbRange];
10941
+ ? [...aboveThePlayers, ...outsideRemoteDb, ...amongThePlayers]
10942
+ : [...outsideRemoteDb, ...aboveThePlayers, ...amongThePlayers];
10846
10943
  return (_a = search.find(id => !used.has(id))) !== null && _a !== void 0 ? _a : null;
10847
10944
  }
10848
10945
 
@@ -11276,9 +11373,14 @@ _Announcer_announceSocket = new WeakMap(), _Announcer_deviceManager = new WeakMa
11276
11373
  // Stay in whichever range we were already in. Dropping out of 1-6 would
11277
11374
  // silently lose remotedb metadata for unanalyzed and streaming tracks, so
11278
11375
  // a conflict on player 5 looks for another free player number first.
11279
- const usedIds = [...__classPrivateFieldGet(this, _Announcer_deviceManager, "f").devices.values()].map(d => d.id);
11280
- const newId = (0, device_id_1.pickAvailableDeviceId)(usedIds, {
11376
+ //
11377
+ // The mixer decides which of those numbers are actually safe: a player can
11378
+ // only be assigned a number its mixer has a channel for, so anything above
11379
+ // that is out of reach of the rig that just contested us.
11380
+ const devices = [...__classPrivateFieldGet(this, _Announcer_deviceManager, "f").devices.values()];
11381
+ const newId = (0, device_id_1.pickAvailableDeviceId)(devices.map(d => d.id), {
11281
11382
  preferRemoteDb: __classPrivateFieldGet(this, _Announcer_vcdj, "f").id <= device_id_1.REMOTEDB_MAX_DEVICE_ID,
11383
+ playerCeiling: (0, device_id_1.playerNumberCeiling)(devices),
11282
11384
  });
11283
11385
  if (newId === null) {
11284
11386
  __classPrivateFieldGet(this, _Announcer_logger, "f").error('No available device IDs. All 32 slots are occupied.');