alphatheta-connect 0.15.0 → 0.18.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.
Files changed (44) hide show
  1. package/README.md +29 -3
  2. package/lib/artwork/index.d.ts +2 -1
  3. package/lib/cli.js +1122 -1332
  4. package/lib/cli.js.map +1 -1
  5. package/lib/constants.d.ts +7 -1
  6. package/lib/db/getArtworkFromFile.d.ts +2 -0
  7. package/lib/db/getFile.d.ts +7 -2
  8. package/lib/db/getMetadata.d.ts +3 -2
  9. package/lib/db/getTrackAnalysis.d.ts +28 -0
  10. package/lib/db/index.d.ts +8 -8
  11. package/lib/entities.d.ts +13 -111
  12. package/lib/index.d.ts +10 -2
  13. package/lib/index.js +1356 -1352
  14. package/lib/index.js.map +1 -1
  15. package/lib/localdb/database-adapter.d.ts +2 -47
  16. package/lib/localdb/index.d.ts +1 -1
  17. package/lib/localdb/onelibrary/adapter.d.ts +110 -0
  18. package/lib/localdb/onelibrary/connection.d.ts +8 -0
  19. package/lib/localdb/onelibrary/encryption.d.ts +10 -0
  20. package/lib/localdb/onelibrary/index.d.ts +5 -0
  21. package/lib/localdb/onelibrary/types.d.ts +67 -0
  22. package/lib/localdb/onelibrary.d.ts +3 -181
  23. package/lib/localdb/rekordbox/anlz-parsers.d.ts +37 -0
  24. package/lib/localdb/rekordbox/entity-creators.d.ts +27 -0
  25. package/lib/localdb/rekordbox/hydrator.d.ts +20 -0
  26. package/lib/localdb/rekordbox/index.d.ts +13 -0
  27. package/lib/localdb/rekordbox/table-mappings.d.ts +10 -0
  28. package/lib/localdb/rekordbox/types.d.ts +118 -0
  29. package/lib/localdb/rekordbox.d.ts +6 -110
  30. package/lib/logger.d.ts +13 -0
  31. package/lib/metadata.d.ts +45 -0
  32. package/lib/network.d.ts +25 -0
  33. package/lib/nfs/index.d.ts +35 -10
  34. package/lib/nfs/index.test.d.ts +1 -0
  35. package/lib/nfs/programs.d.ts +10 -1
  36. package/lib/passive/index.d.ts +1 -1
  37. package/lib/passive/remotedb.d.ts +12 -1
  38. package/lib/remotedb/queries.d.ts +2 -2
  39. package/lib/types.d.ts +55 -78
  40. package/lib/types.js +21 -38
  41. package/lib/types.js.map +1 -1
  42. package/lib/utils/index.d.ts +9 -0
  43. package/lib/virtualcdj/index.d.ts +7 -1
  44. package/package.json +23 -2
@@ -1,112 +1,8 @@
1
- import { Track } from "../entities";
2
- import { MetadataORM } from "./orm";
3
- import { BeatGrid, CueAndLoop, ExtendedCue, SongStructure, WaveformHD, WaveformPreviewData } from "../types";
4
- import { TelemetrySpan as Span } from "../utils/telemetry";
5
1
  /**
6
- * The provided function should resolve ANLZ files into buffers. Typically
7
- * you would just read the file, but in the case of the prolink network, this
8
- * would handle loading the file over NFS.
2
+ * Rekordbox Database Utilities
3
+ *
4
+ * Re-exports from the rekordbox/ folder for backward compatibility.
5
+ * @see ./rekordbox/index.ts for the implementation
9
6
  */
10
- type AnlzResolver = (path: string) => Promise<Buffer>;
11
- /**
12
- * Data returned from loading DAT anlz files
13
- */
14
- interface AnlzResponseDAT {
15
- /**
16
- * Embedded beat grid information
17
- */
18
- beatGrid: BeatGrid | null;
19
- /**
20
- * Embedded cue and loop information
21
- */
22
- cueAndLoops: CueAndLoop[] | null;
23
- /**
24
- * Standard waveform preview (400 bytes, PWAV tag)
25
- */
26
- waveformPreview: WaveformPreviewData | null;
27
- /**
28
- * Tiny waveform preview (100 bytes, PWV2 tag)
29
- */
30
- waveformTiny: WaveformPreviewData | null;
31
- }
32
- /**
33
- * Data returned from loading EXT anlz files
34
- */
35
- interface AnlzResponseEXT {
36
- /**
37
- * HD Waveform information (PWV5 tag)
38
- */
39
- waveformHd: WaveformHD | null;
40
- /**
41
- * Extended cues with colors and comments (PCO2 tag)
42
- */
43
- extendedCues: ExtendedCue[] | null;
44
- /**
45
- * Song structure / phrase analysis (PSSI tag)
46
- */
47
- songStructure: SongStructure | null;
48
- /**
49
- * Monochrome detailed waveform (PWV3 tag)
50
- */
51
- waveformDetail: Uint8Array | null;
52
- /**
53
- * Color waveform preview (PWV4 tag, 7200 bytes = 1200 columns × 6 bytes)
54
- */
55
- waveformColorPreview: Uint8Array | null;
56
- }
57
- interface AnlzResponse {
58
- DAT: AnlzResponseDAT;
59
- EXT: AnlzResponseEXT;
60
- }
61
- /**
62
- * Details about the current state of the hydtration task
63
- */
64
- export interface HydrationProgress {
65
- /**
66
- * The specific table that progress is being reported for
67
- */
68
- table: string;
69
- /**
70
- * The total progress steps for this table
71
- */
72
- total: number;
73
- /**
74
- * The completed number of progress steps
75
- */
76
- complete: number;
77
- }
78
- /**
79
- * Options to hydrate the database
80
- */
81
- interface Options {
82
- /**
83
- * The metadata ORM of which the tables will be hydrated
84
- */
85
- orm: MetadataORM;
86
- /**
87
- * This buffer should contain the Rekordbox pdb file contents. It will be
88
- * used to do the hydration
89
- */
90
- pdbData: Buffer;
91
- /**
92
- * Sentry tracing span for the parent transaction
93
- */
94
- span?: Span;
95
- /**
96
- * For larger music collections, it may take some time to load everything,
97
- * especially when limited by IO. When hydration progresses this function
98
- * will be called.
99
- */
100
- onProgress?: (progress: HydrationProgress) => void;
101
- }
102
- /**
103
- * Given a rekordbox pdb file contents. This function will hydrate the provided
104
- * database with all entities from the Rekordbox database. This includes all
105
- * track metadata, including analyzed metadata (such as beatgrids and waveforms).
106
- */
107
- export declare function hydrateDatabase({ pdbData, span, ...options }: Options): Promise<void>;
108
- /**
109
- * Loads the ANLZ data of a Track entity from the analyzePath.
110
- */
111
- export declare function loadAnlz<T extends keyof AnlzResponse>(track: Track, type: T, anlzResolver: AnlzResolver): Promise<AnlzResponse[T]>;
112
- export {};
7
+ export type { AnlzResolver, AnlzResponse, AnlzResponse2EX, AnlzResponseDAT, AnlzResponseEXT, HydrationOptions, HydrationProgress, } from './rekordbox/index';
8
+ export { hydrateDatabase, loadAnlz } from './rekordbox/index';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Logger interface for alphatheta-connect package.
3
+ * Consumers can supply their own logger implementation.
4
+ * If no logger is provided, a no-op logger is used (silent).
5
+ */
6
+ export interface Logger {
7
+ trace(msg: string, ...args: unknown[]): void;
8
+ debug(msg: string, ...args: unknown[]): void;
9
+ info(msg: string, ...args: unknown[]): void;
10
+ warn(msg: string, ...args: unknown[]): void;
11
+ error(msg: string, ...args: unknown[]): void;
12
+ }
13
+ export declare const noopLogger: Logger;
@@ -0,0 +1,45 @@
1
+ import type { ExtractedMetadata, FileReader } from 'metadata-connect';
2
+ import { NfsMediaSlot } from './nfs';
3
+ import { Device } from './types';
4
+ export type { ExtractedMetadata } from 'metadata-connect';
5
+ /**
6
+ * Extract full metadata from an audio file using a FileReader.
7
+ *
8
+ * This is the low-level API that works with any FileReader implementation.
9
+ * For extracting from a Pro DJ Link device, use extractMetadataFromDevice.
10
+ *
11
+ * @param reader - FileReader interface for reading file data
12
+ * @returns Extracted metadata, or null if extraction fails
13
+ */
14
+ export declare function extractFullMetadata(reader: FileReader): Promise<ExtractedMetadata | null>;
15
+ /**
16
+ * Check if metadata extraction is supported for a file extension.
17
+ *
18
+ * @param extension - File extension (with or without leading dot)
19
+ * @returns true if the extension is supported
20
+ */
21
+ export declare function isMetadataExtractionSupported(extension: string): boolean;
22
+ /**
23
+ * Extract full metadata from an audio file on a Pro DJ Link device.
24
+ *
25
+ * This function reads only the necessary bytes from the file header,
26
+ * avoiding the need to transfer entire audio files over the network.
27
+ *
28
+ * @param device - The Pro DJ Link device
29
+ * @param slot - The media slot containing the file (USB, SD, etc.)
30
+ * @param filePath - The file path on the device
31
+ * @returns Extracted metadata, or null if extraction fails
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // Extract metadata when a track is loaded
36
+ * const metadata = await extractMetadataFromDevice(device, slot, filePath);
37
+ * if (metadata) {
38
+ * console.log(metadata.title, metadata.artist, metadata.bpm);
39
+ * if (metadata.artwork) {
40
+ * // Display artwork
41
+ * }
42
+ * }
43
+ * ```
44
+ */
45
+ export declare function extractMetadataFromDevice(device: Device, slot: NfsMediaSlot, filePath: string): Promise<ExtractedMetadata | null>;
package/lib/network.d.ts CHANGED
@@ -3,6 +3,7 @@ import { NetworkInterfaceInfoIPv4 } from 'os';
3
3
  import Control from "./control";
4
4
  import Database from "./db";
5
5
  import DeviceManager from "./devices";
6
+ import { type Logger } from "./logger";
6
7
  import LocalDatabase from "./localdb";
7
8
  import { DatabasePreference } from "./localdb/database-adapter";
8
9
  import { MixstatusProcessor } from "./mixstatus";
@@ -52,6 +53,20 @@ export interface NetworkConfig {
52
53
  * hardware to ensure proper device discovery and network stability.
53
54
  */
54
55
  fullStartup?: boolean;
56
+ /**
57
+ * Send announcer packets to Pioneer Stagehand devices.
58
+ *
59
+ * Stagehand is excluded from announcer packets by default because it has
60
+ * been observed to crash when it receives them. Enabling this also turns on
61
+ * the cold-start subnet broadcast, which would otherwise reach Stagehand the
62
+ * same way.
63
+ *
64
+ * Enable this only for diagnostic work (e.g. reproducing that crash), never
65
+ * in production.
66
+ *
67
+ * @default false
68
+ */
69
+ announceToStagehand?: boolean;
55
70
  /**
56
71
  * Database format preference for loading rekordbox databases.
57
72
  *
@@ -62,6 +77,11 @@ export interface NetworkConfig {
62
77
  * @default 'auto'
63
78
  */
64
79
  databasePreference?: DatabasePreference;
80
+ /**
81
+ * Logger instance for diagnostic output.
82
+ * If not provided, logging is silently discarded.
83
+ */
84
+ logger?: Logger;
65
85
  }
66
86
  interface ConstructOpts {
67
87
  config?: NetworkConfig;
@@ -192,6 +212,11 @@ export declare class ProlinkNetwork {
192
212
  * remote database.
193
213
  */
194
214
  get remotedb(): RemoteDatabase | null;
215
+ /**
216
+ * Returns a promise that resolves when the full startup protocol completes.
217
+ * Resolves immediately if fullStartup is disabled or not connected.
218
+ */
219
+ get startupReady(): Promise<void>;
195
220
  /**
196
221
  * Get (and initialize) the {@link MixstatusProcessor} service. This service can
197
222
  * be used to monitor the 'status' of devices on the network as a whole.
@@ -1,4 +1,4 @@
1
- import { Device } from "../types";
1
+ import { Device, MediaSlot } from "../types";
2
2
  import { TelemetrySpan as Span } from "../utils/telemetry";
3
3
  import { fetchFile as fetchFileCall, FileInfo } from './programs';
4
4
  export type { FileInfo } from './programs';
@@ -8,20 +8,45 @@ export interface FetchProgress {
8
8
  total: number;
9
9
  }
10
10
  /**
11
- * The slot <-> mount name mapping is well known.
11
+ * Media slots that support NFS access.
12
+ */
13
+ export type NfsMediaSlot = MediaSlot.USB | MediaSlot.SD | MediaSlot.RB;
14
+ /**
15
+ * Parse a Windows absolute path (e.g. `C:\Users\chris\Music\track.mp3`)
16
+ * into the NFS mount path and relative file path.
17
+ *
18
+ * @internal Exported for testing
19
+ */
20
+ export declare function parseWindowsPath(filePath: string): {
21
+ mountPath: string;
22
+ nfsPath: string;
23
+ } | null;
24
+ /**
25
+ * Resolve the NFS mount path and file path for a given slot.
26
+ *
27
+ * For USB/SD slots, the mount path is well-known (/C/ and /B/).
28
+ * For the RB slot, the mount path is extracted from the file path returned
29
+ * by remotedb:
30
+ * - Windows: `C:\Users\chris\Music\track.mp3` → mount `/C/`, path `Users/chris/Music/track.mp3`
31
+ * - macOS: `/Users/chris/Music/track.mp3` → mount `/`, path `Users/chris/Music/track.mp3`
32
+ *
33
+ * @internal Exported for testing
12
34
  */
13
- declare const slotMountMapping: {
14
- readonly 3: "/C/";
15
- readonly 2: "/B/";
16
- readonly 4: "/";
35
+ export declare function resolveNfsPath(slot: NfsMediaSlot, filePath: string): {
36
+ mountPath: string;
37
+ nfsPath: string;
17
38
  };
18
39
  /**
19
- * Media slots that support NFS access.
40
+ * Get the portmapper port for the given device. Rekordbox software uses a
41
+ * non-standard port (50111) while CDJs and other hardware use the standard
42
+ * port (111).
43
+ *
44
+ * @internal Exported for testing
20
45
  */
21
- export type NfsMediaSlot = keyof typeof slotMountMapping;
46
+ export declare function getPortmapPort(device: Device): number;
22
47
  interface FetchFileOptions {
23
48
  device: Device;
24
- slot: keyof typeof slotMountMapping;
49
+ slot: NfsMediaSlot;
25
50
  path: string;
26
51
  onProgress?: Parameters<typeof fetchFileCall>[2];
27
52
  span?: Span;
@@ -29,7 +54,7 @@ interface FetchFileOptions {
29
54
  }
30
55
  interface FetchFileRangeOptions {
31
56
  device: Device;
32
- slot: keyof typeof slotMountMapping;
57
+ slot: NfsMediaSlot;
33
58
  path: string;
34
59
  offset: number;
35
60
  length: number;
@@ -0,0 +1 @@
1
+ export {};
@@ -5,10 +5,19 @@ interface Program {
5
5
  id: number;
6
6
  version: number;
7
7
  }
8
+ /**
9
+ * Standard portmapper port used by CDJs and other hardware.
10
+ */
11
+ export declare const STANDARD_PORTMAP_PORT = 111;
12
+ /**
13
+ * Non-standard portmapper port used by rekordbox software.
14
+ * Rekordbox registers its RPC services on this port instead of 111.
15
+ */
16
+ export declare const REKORDBOX_PORTMAP_PORT = 50111;
8
17
  /**
9
18
  * Queries for the listening port of a RPC program
10
19
  */
11
- export declare function makeProgramClient(conn: RpcConnection, program: Program): Promise<RpcProgram>;
20
+ export declare function makeProgramClient(conn: RpcConnection, program: Program, portmapPort?: number): Promise<RpcProgram>;
12
21
  /**
13
22
  * Export represents a NFS export on a remote system
14
23
  */
@@ -6,7 +6,7 @@ import { PcapAdapter } from './pcap-adapter';
6
6
  import { PassivePositionEmitter } from './position';
7
7
  import { PassiveRemoteDatabase } from './remotedb';
8
8
  import { PassiveStatusEmitter } from './status';
9
- export { AlphaThetaInterface, findAlphaThetaInterface, findAllAlphaThetaInterfaces, getArpCacheForInterface, } from './alphatheta';
9
+ export { AlphaThetaInterface, findAllAlphaThetaInterfaces, findAlphaThetaInterface, getArpCacheForInterface, } from './alphatheta';
10
10
  export { PassiveDeviceManager } from './devices';
11
11
  export { PassiveLocalDatabase } from './localdb';
12
12
  export { PacketInfo, PcapAdapter, PcapAdapterConfig } from './pcap-adapter';
@@ -40,7 +40,18 @@ export declare class PassiveRemoteDatabase {
40
40
  * @param trackType - The track type (e.g., TrackType.RB)
41
41
  * @param trackId - The track ID to look up
42
42
  */
43
- getTrackMetadata(deviceId: DeviceID, trackSlot: MediaSlot, trackType: TrackType, trackId: number): Promise<import("../types").Track<import("..").EntityFK.WithRelations> | null>;
43
+ getTrackMetadata(deviceId: DeviceID, trackSlot: MediaSlot, trackType: TrackType, trackId: number): Promise<import("../types").Track<import("onelibrary-connect").EntityFK.WithRelations> | null>;
44
+ /**
45
+ * Query metadata for an unanalyzed track (loaded directly from USB without
46
+ * Rekordbox analysis). Uses GetGenericMetadata which reads ID3 tags from the
47
+ * audio file via the CDJ.
48
+ *
49
+ * @param deviceId - The CDJ device to query
50
+ * @param trackSlot - The media slot (USB or SD)
51
+ * @param trackType - Should be TrackType.Unanalyzed
52
+ * @param trackId - The track ID to look up
53
+ */
54
+ getGenericTrackMetadata(deviceId: DeviceID, trackSlot: MediaSlot, trackType: TrackType, trackId: number): Promise<import("../types").Track<import("onelibrary-connect").EntityFK.WithRelations> | null>;
44
55
  /**
45
56
  * Stop all connections
46
57
  */
@@ -52,11 +52,11 @@ declare function getWaveformHD(opts: TrackQueryOpts): Promise<import("..").Wavef
52
52
  /**
53
53
  * Lookup the [hot]cue points and [hot]loops for a track
54
54
  */
55
- declare function getCueAndLoops(opts: TrackQueryOpts): Promise<import("..").CueAndLoop[]>;
55
+ declare function getCueAndLoops(opts: TrackQueryOpts): Promise<import("onelibrary-connect").CueAndLoop[]>;
56
56
  /**
57
57
  * Lookup the "advanced" (nexus2) [hot]cue points and [hot]loops for a track
58
58
  */
59
- declare function getCueAndLoopsAdv(opts: TrackQueryOpts): Promise<import("..").CueAndLoop[]>;
59
+ declare function getCueAndLoopsAdv(opts: TrackQueryOpts): Promise<import("onelibrary-connect").CueAndLoop[]>;
60
60
  /**
61
61
  * Lookup the track information, currently just returns the track path
62
62
  */
package/lib/types.d.ts CHANGED
@@ -5,6 +5,7 @@ export * as CDJStatus from "./status/types";
5
5
  * Re-export various types for the types only compile target
6
6
  */
7
7
  export type { Album, Artist, Artwork, Color, Genre, Key, Label, Playlist, Track, } from './entities';
8
+ export type { TrackAnalysis } from './db/getTrackAnalysis';
8
9
  export type { HydrationProgress } from './localdb/rekordbox';
9
10
  export type { MixstatusConfig, MixstatusProcessor } from './mixstatus';
10
11
  export type { ConnectedProlinkNetwork, NetworkConfig } from './network';
@@ -101,7 +102,12 @@ export declare enum MediaSlot {
101
102
  CD = 1,
102
103
  SD = 2,
103
104
  USB = 3,
104
- RB = 4
105
+ RB = 4,
106
+ Unknown05 = 5,// Possibly TIDAL, Apple Music, or other streaming
107
+ StreamingDirectPlay = 6,
108
+ Unknown07 = 7,// Possibly TIDAL, Apple Music, or other streaming
109
+ Unknown08 = 8,// Possibly TIDAL, Apple Music, or other streaming
110
+ Beatport = 9
105
111
  }
106
112
  /**
107
113
  * Track type flags
@@ -110,7 +116,8 @@ export declare enum TrackType {
110
116
  None = 0,
111
117
  RB = 1,
112
118
  Unanalyzed = 2,
113
- AudioCD = 5
119
+ AudioCD = 5,
120
+ Streaming = 6
114
121
  }
115
122
  /**
116
123
  * A beat grid is a series of offsets from the start of the track. Each offset
@@ -180,91 +187,25 @@ export interface Waveforms {
180
187
  * The full-size and full-color waveform
181
188
  */
182
189
  waveformHd: WaveformHD;
183
- }
184
- /**
185
- * A hotcue button label
186
- */
187
- export declare enum HotcueButton {
188
- A = 1,
189
- B = 2,
190
- C = 3,
191
- D = 4,
192
- E = 5,
193
- F = 6,
194
- G = 7,
195
- H = 8
196
- }
197
- /**
198
- * When a custom color is not configured the cue point will be one of these
199
- * colors.
200
- */
201
- export declare enum CueColor {
202
- None = 0,
203
- Blank = 21,
204
- Magenta = 49,
205
- Violet = 56,
206
- Fuchsia = 60,
207
- LightSlateBlue = 62,
208
- Blue = 1,
209
- SteelBlue = 5,
210
- Aqua = 9,
211
- SeaGreen = 14,
212
- Teal = 18,
213
- Green = 22,
214
- Lime = 26,
215
- Olive = 30,
216
- Yellow = 32,
217
- Orange = 38,
218
- Red = 42,
219
- Pink = 45
220
- }
221
- /**
222
- * Represents a single cue point. On older exports the label and color may be
223
- * undefined.
224
- */
225
- export interface CuePoint {
226
- type: 'cue_point';
227
190
  /**
228
- * Number of milliseconds from the start of the track.
191
+ * Color waveform preview (PWV4 tag).
192
+ * Raw bytes: 1200 columns × 6 bytes per column (3 frequency bands × 2 bytes each).
229
193
  */
230
- offset: number;
194
+ waveformColorPreview?: Uint8Array;
231
195
  /**
232
- * The comment associated to the cue point
196
+ * Standard waveform preview (400 entries). Available for streaming tracks.
233
197
  */
234
- label?: string;
198
+ waveformPreview?: WaveformPreview;
235
199
  /**
236
- * RGB values of the hotcue color
200
+ * Full detailed waveform. Available for streaming tracks.
237
201
  */
238
- color?: CueColor;
202
+ waveformDetailed?: WaveformDetailed;
239
203
  }
240
- type BareCuePoint = Omit<CuePoint, 'type'>;
241
- /**
242
- * A loop, similar to a cue point, but includes a length.
243
- */
244
- export type Loop = BareCuePoint & {
245
- type: 'loop';
246
- /**
247
- * The length in milliseconds of the loop
248
- */
249
- length: number;
250
- };
251
204
  /**
252
- * A hotcue is like a cue point, but also includes the button it is assigned to.
205
+ * Re-export cue types from onelibrary-connect
253
206
  */
254
- export type Hotcue = BareCuePoint & {
255
- type: 'hot_cue';
256
- /**
257
- * Which hotcue button this hotcue is assigned to.
258
- */
259
- button: HotcueButton;
260
- };
261
- /**
262
- * A hot loop, this is the union of a hotcue and a loop.
263
- */
264
- export type Hotloop = {
265
- type: 'hot_loop';
266
- } & (Omit<Hotcue, 'type'> & Omit<Loop, 'type'>);
267
- export type CueAndLoop = CuePoint | Loop | Hotcue | Hotloop;
207
+ export { CueColor, HotcueButton } from 'onelibrary-connect';
208
+ export type { CueAndLoop, CuePoint, Hotcue, Hotloop, Loop } from 'onelibrary-connect';
268
209
  /**
269
210
  * Extended cue with color and comment support (PCO2 tag from rekordbox).
270
211
  * Includes additional metadata like RGB colors, comments, and quantized loop information.
@@ -366,6 +307,42 @@ export interface SongStructure {
366
307
  */
367
308
  phrases: Phrase[];
368
309
  }
310
+ /**
311
+ * 3-band color waveform preview (PWV6 tag from .2EX files).
312
+ * Same resolution as PWV4 (typically 1200 entries) but with separate
313
+ * low, mid, and high frequency band amplitudes.
314
+ *
315
+ * @see https://djl-analysis.deepsymmetry.org/djl-analysis/track-metadata.html#color-3band-preview-waveform
316
+ */
317
+ export interface Waveform3BandPreview {
318
+ numEntries: number;
319
+ /** Raw interleaved bytes: numEntries × 3 (low, mid, high per entry) */
320
+ data: Uint8Array;
321
+ }
322
+ /**
323
+ * 3-band color detail waveform (PWV7 tag from .2EX files).
324
+ * Higher resolution than PWV6, approximately 150 entries per second.
325
+ *
326
+ * @see https://djl-analysis.deepsymmetry.org/djl-analysis/track-metadata.html#color-3band-detail-waveform
327
+ */
328
+ export interface Waveform3BandDetail {
329
+ numEntries: number;
330
+ /** Raw interleaved bytes: numEntries × 3 (low, mid, high per entry) */
331
+ data: Uint8Array;
332
+ }
333
+ /**
334
+ * Vocal detection configuration (PWVC tag from .2EX files).
335
+ * Threshold values used to classify frequency content as vocal or non-vocal.
336
+ *
337
+ * Values are u16 but observed range across 192 real files is 80-159,
338
+ * matching the 0-255 byte scale used by waveform band values.
339
+ * Observed ranges: low 80-114, mid 80-146, high 98-159.
340
+ */
341
+ export interface VocalConfig {
342
+ thresholdLow: number;
343
+ thresholdMid: number;
344
+ thresholdHigh: number;
345
+ }
369
346
  /**
370
347
  * Monochrome waveform preview data (PWAV/PWV2 tags).
371
348
  * PWAV contains 400 bytes, PWV2 contains 100 bytes.
package/lib/types.js CHANGED
@@ -83,7 +83,7 @@ var __importStar = (this && this.__importStar) || (function () {
83
83
  };
84
84
  })();
85
85
  Object.defineProperty(exports, "__esModule", ({ value: true }));
86
- exports.MixstatusMode = exports.NetworkState = exports.CueColor = exports.HotcueButton = exports.TrackType = exports.MediaSlot = exports.MediaColor = exports.DeviceType = exports.CDJStatus = void 0;
86
+ exports.MixstatusMode = exports.NetworkState = exports.HotcueButton = exports.CueColor = exports.TrackType = exports.MediaSlot = exports.MediaColor = exports.DeviceType = exports.CDJStatus = void 0;
87
87
  exports.CDJStatus = __importStar(__webpack_require__(/*! src/status/types */ "./src/status/types.ts"));
88
88
  /**
89
89
  * Known device types on the network
@@ -116,6 +116,11 @@ var MediaSlot;
116
116
  MediaSlot[MediaSlot["SD"] = 2] = "SD";
117
117
  MediaSlot[MediaSlot["USB"] = 3] = "USB";
118
118
  MediaSlot[MediaSlot["RB"] = 4] = "RB";
119
+ MediaSlot[MediaSlot["Unknown05"] = 5] = "Unknown05";
120
+ MediaSlot[MediaSlot["StreamingDirectPlay"] = 6] = "StreamingDirectPlay";
121
+ MediaSlot[MediaSlot["Unknown07"] = 7] = "Unknown07";
122
+ MediaSlot[MediaSlot["Unknown08"] = 8] = "Unknown08";
123
+ MediaSlot[MediaSlot["Beatport"] = 9] = "Beatport";
119
124
  })(MediaSlot || (exports.MediaSlot = MediaSlot = {}));
120
125
  /**
121
126
  * Track type flags
@@ -126,46 +131,14 @@ var TrackType;
126
131
  TrackType[TrackType["RB"] = 1] = "RB";
127
132
  TrackType[TrackType["Unanalyzed"] = 2] = "Unanalyzed";
128
133
  TrackType[TrackType["AudioCD"] = 5] = "AudioCD";
134
+ TrackType[TrackType["Streaming"] = 6] = "Streaming";
129
135
  })(TrackType || (exports.TrackType = TrackType = {}));
130
136
  /**
131
- * A hotcue button label
137
+ * Re-export cue types from onelibrary-connect
132
138
  */
133
- var HotcueButton;
134
- (function (HotcueButton) {
135
- HotcueButton[HotcueButton["A"] = 1] = "A";
136
- HotcueButton[HotcueButton["B"] = 2] = "B";
137
- HotcueButton[HotcueButton["C"] = 3] = "C";
138
- HotcueButton[HotcueButton["D"] = 4] = "D";
139
- HotcueButton[HotcueButton["E"] = 5] = "E";
140
- HotcueButton[HotcueButton["F"] = 6] = "F";
141
- HotcueButton[HotcueButton["G"] = 7] = "G";
142
- HotcueButton[HotcueButton["H"] = 8] = "H";
143
- })(HotcueButton || (exports.HotcueButton = HotcueButton = {}));
144
- /**
145
- * When a custom color is not configured the cue point will be one of these
146
- * colors.
147
- */
148
- var CueColor;
149
- (function (CueColor) {
150
- CueColor[CueColor["None"] = 0] = "None";
151
- CueColor[CueColor["Blank"] = 21] = "Blank";
152
- CueColor[CueColor["Magenta"] = 49] = "Magenta";
153
- CueColor[CueColor["Violet"] = 56] = "Violet";
154
- CueColor[CueColor["Fuchsia"] = 60] = "Fuchsia";
155
- CueColor[CueColor["LightSlateBlue"] = 62] = "LightSlateBlue";
156
- CueColor[CueColor["Blue"] = 1] = "Blue";
157
- CueColor[CueColor["SteelBlue"] = 5] = "SteelBlue";
158
- CueColor[CueColor["Aqua"] = 9] = "Aqua";
159
- CueColor[CueColor["SeaGreen"] = 14] = "SeaGreen";
160
- CueColor[CueColor["Teal"] = 18] = "Teal";
161
- CueColor[CueColor["Green"] = 22] = "Green";
162
- CueColor[CueColor["Lime"] = 26] = "Lime";
163
- CueColor[CueColor["Olive"] = 30] = "Olive";
164
- CueColor[CueColor["Yellow"] = 32] = "Yellow";
165
- CueColor[CueColor["Orange"] = 38] = "Orange";
166
- CueColor[CueColor["Red"] = 42] = "Red";
167
- CueColor[CueColor["Pink"] = 45] = "Pink";
168
- })(CueColor || (exports.CueColor = CueColor = {}));
139
+ var onelibrary_connect_1 = __webpack_require__(/*! onelibrary-connect */ "onelibrary-connect");
140
+ Object.defineProperty(exports, "CueColor", ({ enumerable: true, get: function () { return onelibrary_connect_1.CueColor; } }));
141
+ Object.defineProperty(exports, "HotcueButton", ({ enumerable: true, get: function () { return onelibrary_connect_1.HotcueButton; } }));
169
142
  var NetworkState;
170
143
  (function (NetworkState) {
171
144
  /**
@@ -227,6 +200,16 @@ var MixstatusMode;
227
200
  })(MixstatusMode || (exports.MixstatusMode = MixstatusMode = {}));
228
201
 
229
202
 
203
+ /***/ },
204
+
205
+ /***/ "onelibrary-connect"
206
+ /*!*************************************!*\
207
+ !*** external "onelibrary-connect" ***!
208
+ \*************************************/
209
+ (module) {
210
+
211
+ module.exports = require("onelibrary-connect");
212
+
230
213
  /***/ }
231
214
 
232
215
  /******/ });