@basmilius/apple-raop 0.9.18 → 0.10.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/dist/index.d.mts CHANGED
@@ -4,186 +4,662 @@ import { AudioSource, Context, DiscoveryResult, TimingServer } from "@basmilius/
4
4
  import { RtspClient } from "@basmilius/apple-rtsp";
5
5
 
6
6
  //#region src/types.d.ts
7
+ /**
8
+ * Metadata describing the currently streaming media track.
9
+ */
7
10
  type MediaMetadata = {
8
- readonly title: string;
9
- readonly artist: string;
10
- readonly album: string;
11
- readonly duration: number;
11
+ /** Track title. */readonly title: string; /** Artist or performer name. */
12
+ readonly artist: string; /** Album name. */
13
+ readonly album: string; /** Total duration of the track in seconds. */
14
+ readonly duration: number; /** Optional album artwork image data (JPEG or PNG). */
12
15
  readonly artwork?: Buffer;
13
16
  };
17
+ /**
18
+ * Snapshot of the current playback state, combining metadata
19
+ * with the stream position.
20
+ */
14
21
  type PlaybackInfo = {
15
- readonly metadata: MediaMetadata;
22
+ /** Metadata for the currently playing track. */readonly metadata: MediaMetadata; /** Current playback position in audio frames. */
16
23
  readonly position: number;
17
24
  };
25
+ /**
26
+ * Mutable state shared across all RAOP streaming components.
27
+ * Holds RTP sequence numbers, timestamps, audio format details,
28
+ * and connection ports negotiated during RTSP SETUP.
29
+ */
18
30
  type StreamContext = {
19
- sampleRate: number;
20
- channels: number;
21
- bytesPerChannel: number;
22
- rtpseq: number;
23
- rtptime: number;
24
- headTs: number;
25
- latency: number;
26
- serverPort: number;
27
- controlPort: number;
28
- rtspSession: string;
29
- volume: number;
30
- position: number;
31
- packetSize: number;
32
- frameSize: number;
31
+ /** Audio sample rate in Hz (e.g. 44100). */sampleRate: number; /** Number of audio channels (e.g. 2 for stereo). */
32
+ channels: number; /** Bytes per channel sample (e.g. 2 for 16-bit). */
33
+ bytesPerChannel: number; /** Current RTP sequence number (wraps at 16 bits). */
34
+ rtpseq: number; /** Initial RTP timestamp used in RECORD/FLUSH headers. */
35
+ rtptime: number; /** Current head timestamp tracking the latest sent audio frame. */
36
+ headTs: number; /** Latency in audio frames (typically 2 seconds worth). */
37
+ latency: number; /** Remote server audio data port assigned during SETUP. */
38
+ serverPort: number; /** Remote control port for sync and retransmit communication. */
39
+ controlPort: number; /** RTSP session identifier string. */
40
+ rtspSession: string; /** Current volume level in dBFS. */
41
+ volume: number; /** Current playback position in audio frames. */
42
+ position: number; /** Size of a single audio packet payload in bytes. */
43
+ packetSize: number; /** Size of a single audio frame in bytes (channels * bytesPerChannel). */
44
+ frameSize: number; /** Number of silence padding frames sent after source exhaustion. */
33
45
  paddingSent: number;
46
+ /**
47
+ * Resets RTP sequence number, timestamp, head timestamp,
48
+ * padding counter, and position for a new stream session.
49
+ */
34
50
  reset(): void;
35
51
  };
52
+ /**
53
+ * Abstraction over the transport-level protocol operations for
54
+ * setting up and tearing down an audio stream. Allows different
55
+ * protocol backends (e.g. RAOP over RTSP).
56
+ */
36
57
  interface StreamProtocol {
58
+ /**
59
+ * Performs RTSP ANNOUNCE and SETUP, negotiating ports with the receiver.
60
+ *
61
+ * @param timingPort - Local NTP timing server port.
62
+ * @param controlPort - Local control channel port.
63
+ */
37
64
  setup(timingPort: number, controlPort: number): Promise<void>;
65
+ /**
66
+ * Starts sending periodic feedback requests to maintain the session.
67
+ */
38
68
  startFeedback(): Promise<void>;
69
+ /**
70
+ * Sends a single audio packet over the UDP transport.
71
+ *
72
+ * @param transport - UDP socket connected to the receiver.
73
+ * @param header - RTP header for the audio packet.
74
+ * @param audio - Raw audio payload data.
75
+ * @returns A tuple of [sequence number, full packet buffer] for backlog storage.
76
+ */
39
77
  sendAudioPacket(transport: Socket, header: Buffer, audio: Buffer): Promise<[number, Buffer]>;
78
+ /**
79
+ * Tears down the protocol session, stopping feedback and releasing resources.
80
+ */
40
81
  teardown(): void;
41
82
  }
83
+ /**
84
+ * Configuration for RAOP protocol port bindings.
85
+ */
42
86
  interface Settings {
87
+ /** Protocol-specific port configuration. */
43
88
  protocols: {
44
- raop: {
45
- controlPort: number;
89
+ /** RAOP control and timing port settings. */raop: {
90
+ /** Control channel port (0 for auto-assign). */controlPort: number; /** NTP timing server port (0 for auto-assign). */
46
91
  timingPort: number;
47
92
  };
48
93
  };
49
94
  }
95
+ /**
96
+ * Bitmask enum for encryption types supported by the RAOP receiver.
97
+ * Values are parsed from the `et` mDNS TXT record field.
98
+ */
50
99
  declare enum EncryptionType {
100
+ /** No encryption information available. */
51
101
  Unknown = 0,
102
+ /** Receiver supports unencrypted streams. */
52
103
  Unencrypted = 1,
104
+ /** Receiver supports MFi-SAP encryption (AirPort Express). */
53
105
  MFiSAP = 2
54
106
  }
107
+ /**
108
+ * Bitmask enum for metadata types supported by the RAOP receiver.
109
+ * Values are parsed from the `md` mDNS TXT record field.
110
+ */
55
111
  declare enum MetadataType {
112
+ /** Receiver does not support metadata. */
56
113
  NotSupported = 0,
114
+ /** Receiver supports text metadata (title, artist, album). */
57
115
  Text = 1,
116
+ /** Receiver supports album artwork. */
58
117
  Artwork = 2,
118
+ /** Receiver supports progress/duration information. */
59
119
  Progress = 4
60
120
  }
121
+ /**
122
+ * Listener interface for RAOP playback lifecycle events.
123
+ */
61
124
  interface RaopListener {
125
+ /**
126
+ * Called when audio playback starts or metadata changes.
127
+ *
128
+ * @param playbackInfo - Current playback state information.
129
+ */
62
130
  playing(playbackInfo: PlaybackInfo): void;
131
+ /**
132
+ * Called when audio playback stops.
133
+ */
63
134
  stopped(): void;
64
135
  }
65
136
  //#endregion
66
137
  //#region src/packets.d.ts
138
+ /**
139
+ * Fixed-size FIFO buffer for recently sent RTP audio packets.
140
+ * Used to fulfill retransmission requests from the receiver when
141
+ * packets are lost in transit.
142
+ */
67
143
  declare class PacketFifo {
68
144
  #private;
145
+ /**
146
+ * Creates a new packet FIFO with the given capacity.
147
+ *
148
+ * @param maxSize - Maximum number of packets to store before evicting the oldest.
149
+ */
69
150
  constructor(maxSize: number);
151
+ /**
152
+ * Retrieves a packet by its RTP sequence number.
153
+ *
154
+ * @param seqno - RTP sequence number to look up.
155
+ * @returns The packet buffer, or undefined if not in the backlog.
156
+ */
70
157
  get(seqno: number): Buffer | undefined;
158
+ /**
159
+ * Stores a packet in the backlog. If the sequence number already
160
+ * exists, the call is ignored. When the backlog exceeds its maximum
161
+ * size, the oldest packets are evicted.
162
+ *
163
+ * @param seqno - RTP sequence number of the packet.
164
+ * @param packet - Full RTP packet data including header.
165
+ */
71
166
  set(seqno: number, packet: Buffer): void;
167
+ /**
168
+ * Checks whether a packet with the given sequence number is in the backlog.
169
+ *
170
+ * @param seqno - RTP sequence number to check.
171
+ * @returns True if the packet exists in the backlog.
172
+ */
72
173
  has(seqno: number): boolean;
174
+ /**
175
+ * Removes all packets from the backlog.
176
+ */
73
177
  clear(): void;
74
178
  }
179
+ /**
180
+ * Encoder for RTP audio packet headers (12 bytes).
181
+ * Produces the standard RTP fixed header used for RAOP audio data packets.
182
+ */
75
183
  declare const AudioPacketHeader: {
184
+ /**
185
+ * Encodes a 12-byte RTP audio packet header.
186
+ *
187
+ * @param header - First byte containing version, padding, and extension flags (typically 0x80).
188
+ * @param payloadType - RTP payload type (0xE0 for first packet, 0x60 for subsequent).
189
+ * @param seqno - 16-bit RTP sequence number.
190
+ * @param timestamp - 32-bit RTP timestamp in audio frames.
191
+ * @param ssrc - Synchronization source identifier (session ID).
192
+ * @returns A 12-byte buffer containing the encoded RTP header.
193
+ */
76
194
  encode(header: number, payloadType: number, seqno: number, timestamp: number, ssrc: number): Buffer;
77
195
  };
196
+ /**
197
+ * Encoder for RAOP timing synchronization packets (20 bytes).
198
+ * Sent periodically over the control channel to synchronize
199
+ * the receiver's playback clock with the sender's RTP timestamps.
200
+ */
78
201
  declare const SyncPacket: {
202
+ /**
203
+ * Encodes a 20-byte sync packet.
204
+ *
205
+ * @param header - First byte (0x90 for first sync, 0x80 for subsequent).
206
+ * @param payloadType - Payload type identifier (0xD4 for sync).
207
+ * @param seqno - 16-bit sequence number (typically 0x0007).
208
+ * @param rtpTimestamp - RTP timestamp of the next audio packet to play, minus latency.
209
+ * @param ntpSec - NTP seconds component of the current wall-clock time.
210
+ * @param ntpFrac - NTP fractional seconds component of the current wall-clock time.
211
+ * @param rtpTimestampNow - RTP timestamp corresponding to the current head position.
212
+ * @returns A 20-byte buffer containing the encoded sync packet.
213
+ */
79
214
  encode(header: number, payloadType: number, seqno: number, rtpTimestamp: number, ntpSec: number, ntpFrac: number, rtpTimestampNow: number): Buffer;
80
215
  };
216
+ /**
217
+ * Decoded retransmit request received from the RAOP receiver,
218
+ * indicating which packets need to be resent.
219
+ */
81
220
  type RetransmitRequest = {
82
- readonly lostSeqno: number;
221
+ /** Starting RTP sequence number of the lost range. */readonly lostSeqno: number; /** Number of consecutive lost packets starting from lostSeqno. */
83
222
  readonly lostPackets: number;
84
223
  };
224
+ /**
225
+ * Decodes a retransmit request packet received on the control channel.
226
+ * The request contains the starting sequence number and count of lost packets.
227
+ *
228
+ * @param data - Raw UDP packet data from the receiver.
229
+ * @returns Parsed retransmit request with sequence number and packet count.
230
+ */
85
231
  declare function decodeRetransmitRequest(data: Buffer): RetransmitRequest;
86
232
  //#endregion
87
233
  //#region src/utils.d.ts
234
+ /**
235
+ * Converts a linear volume percentage (0-100) to a dBFS value
236
+ * suitable for the RAOP `volume` SET_PARAMETER command.
237
+ *
238
+ * @param volume - Volume as a percentage (0 = silent, 100 = full).
239
+ * @returns Volume in dBFS (-144 for mute, 0 for full volume).
240
+ */
88
241
  declare function pctToDbfs(volume: number): number;
242
+ /**
243
+ * Parses the `et` (encryption types) field from mDNS TXT record
244
+ * properties into an EncryptionType bitmask.
245
+ *
246
+ * @param properties - mDNS TXT record key-value pairs.
247
+ * @returns Bitmask of supported encryption types.
248
+ */
89
249
  declare function getEncryptionTypes(properties: Map<string, string>): EncryptionType;
250
+ /**
251
+ * Parses the `md` (metadata types) field from mDNS TXT record
252
+ * properties into a MetadataType bitmask.
253
+ *
254
+ * @param properties - mDNS TXT record key-value pairs.
255
+ * @returns Bitmask of supported metadata types.
256
+ */
90
257
  declare function getMetadataTypes(properties: Map<string, string>): MetadataType;
258
+ /**
259
+ * Extracts audio format properties from mDNS TXT record fields.
260
+ * Falls back to CD-quality defaults (44100 Hz, 2 channels, 16-bit)
261
+ * when properties are missing.
262
+ *
263
+ * @param properties - mDNS TXT record key-value pairs.
264
+ * @returns A tuple of [sampleRate, channels, bytesPerChannel].
265
+ */
91
266
  declare function getAudioProperties(properties: Map<string, string>): [number, number, number];
92
267
  //#endregion
93
268
  //#region src/controlClient.d.ts
269
+ /**
270
+ * UDP control channel client for RAOP streaming. Responsible for two tasks:
271
+ * 1. Sending periodic timing sync packets to the receiver so it can
272
+ * synchronize its playback clock with our RTP timestamps.
273
+ * 2. Handling retransmit requests from the receiver by resending lost
274
+ * packets from the packet backlog.
275
+ */
94
276
  declare class ControlClient extends EventEmitter {
95
277
  #private;
96
- constructor(context: StreamContext, packetBacklog: PacketFifo);
278
+ /**
279
+ * Creates a new control client.
280
+ *
281
+ * @param appContext - Application context for logging.
282
+ * @param context - Shared stream context with RTP state.
283
+ * @param packetBacklog - Packet FIFO for retransmit lookups.
284
+ */
285
+ constructor(appContext: Context, context: StreamContext, packetBacklog: PacketFifo);
286
+ /** Local UDP port the control channel is bound to, or 0 if not yet bound. */
97
287
  get port(): number;
288
+ /**
289
+ * Binds the control channel UDP socket to a local address and port.
290
+ * Resolves once the socket is listening and the assigned port is known.
291
+ *
292
+ * @param localIp - Local IP address to bind to.
293
+ * @param port - Desired port number (0 for auto-assign).
294
+ * @throws When the UDP socket encounters a bind error.
295
+ */
98
296
  bind(localIp: string, port: number): Promise<void>;
297
+ /**
298
+ * Stops the sync task and closes the UDP socket, releasing all resources.
299
+ */
99
300
  close(): void;
301
+ /**
302
+ * Starts sending periodic sync packets to the receiver. Sync packets
303
+ * are sent immediately and then every second to keep the receiver's
304
+ * playback clock aligned.
305
+ *
306
+ * @param remoteAddr - IP address of the RAOP receiver.
307
+ * @throws When the sync task is already running.
308
+ */
100
309
  start(remoteAddr: string): void;
310
+ /**
311
+ * Stops the periodic sync task without closing the UDP socket.
312
+ */
101
313
  stop(): void;
102
314
  }
103
315
  //#endregion
104
316
  //#region src/rtspClient.d.ts
317
+ /**
318
+ * RAOP-specific RTSP client that extends the base RTSP client with
319
+ * Apple audio streaming commands. Handles the full RAOP RTSP lifecycle:
320
+ * ANNOUNCE, SETUP, RECORD, SET_PARAMETER, FLUSH, TEARDOWN, as well as
321
+ * authentication (auth-setup, digest) and metadata/artwork publishing.
322
+ */
105
323
  declare class RaopRtspClient extends RtspClient {
106
324
  #private;
325
+ /** Active-Remote identifier used for DACP remote control pairing. */
107
326
  get activeRemoteId(): string;
327
+ /** DACP identifier used for remote control discovery. */
108
328
  get dacpId(): string;
329
+ /** RTSP session identifier string included in session-scoped requests. */
109
330
  get rtspSessionId(): string;
331
+ /** Numeric session identifier used in the RTSP URI path. */
110
332
  get sessionId(): number;
333
+ /** RTSP URI for this session, formatted as `rtsp://<localIp>/<sessionId>`. */
111
334
  get uri(): string;
335
+ /** Local and remote IP addresses of the RTSP connection. */
112
336
  get connection(): {
113
337
  localIp: string;
114
338
  remoteIp: string;
115
339
  };
340
+ /**
341
+ * Creates a new RAOP RTSP client and generates unique session identifiers.
342
+ *
343
+ * @param context - Application context for logging and device identity.
344
+ * @param address - IP address of the RAOP receiver.
345
+ * @param port - RTSP port of the RAOP receiver.
346
+ */
116
347
  constructor(context: Context, address: string, port: number);
348
+ /**
349
+ * Returns default headers included with every RTSP request, including
350
+ * DACP identifiers, user-agent, and digest authorization if available.
351
+ *
352
+ * @returns Header key-value pairs.
353
+ */
117
354
  protected getDefaultHeaders(): Record<string, string | number>;
355
+ /**
356
+ * Fetches device information from the `/info` endpoint. Returns the
357
+ * parsed plist response as a dictionary, or an empty object on failure.
358
+ *
359
+ * @returns Device info dictionary, or empty object if unavailable.
360
+ */
118
361
  info(): Promise<Record<string, unknown>>;
362
+ /**
363
+ * Performs MFi-SAP authentication setup by sending a Curve25519 public
364
+ * key to `/auth-setup`. Required for AirPort Express devices that use
365
+ * MFi-SAP encryption.
366
+ */
119
367
  authSetup(): Promise<void>;
368
+ /**
369
+ * Sends an RTSP ANNOUNCE request with an SDP body describing the audio
370
+ * format. If the receiver responds with a 401 challenge and a password
371
+ * is provided, retries with HTTP Digest authentication.
372
+ *
373
+ * @param bytesPerChannel - Bytes per audio channel sample (e.g. 2 for 16-bit).
374
+ * @param channels - Number of audio channels.
375
+ * @param sampleRate - Audio sample rate in Hz.
376
+ * @param password - Optional password for digest authentication.
377
+ * @returns The RTSP response.
378
+ */
120
379
  announce(bytesPerChannel: number, channels: number, sampleRate: number, password?: string): Promise<Response>;
380
+ /**
381
+ * Sends an RTSP SETUP request to negotiate transport parameters
382
+ * (ports, protocol) with the receiver.
383
+ *
384
+ * @param headers - Optional additional headers (e.g. Transport).
385
+ * @param body - Optional request body.
386
+ * @returns The RTSP response containing server-assigned ports in the Transport header.
387
+ */
121
388
  setup(headers?: Record<string, string>, body?: Buffer | string | Record<string, unknown>): Promise<Response>;
389
+ /**
390
+ * Sends an RTSP RECORD request to begin audio playback on the receiver.
391
+ * Includes RTP-Info and Range headers for stream positioning.
392
+ *
393
+ * @param headers - Optional headers (typically Range, Session, RTP-Info).
394
+ */
122
395
  record(headers?: Record<string, string>): Promise<void>;
396
+ /**
397
+ * Sends an RTSP FLUSH request to clear the receiver's audio buffer
398
+ * and reset playback to the specified RTP position.
399
+ *
400
+ * @param options - Headers including Session and RTP-Info for flush positioning.
401
+ */
123
402
  flush(options: {
124
403
  headers: Record<string, string>;
125
404
  }): Promise<void>;
405
+ /**
406
+ * Sends a SET_PARAMETER request with a text/parameters content type.
407
+ * Used for setting volume, progress, and other scalar parameters.
408
+ *
409
+ * @param name - Parameter name (e.g. "volume", "progress").
410
+ * @param value - Parameter value as a string.
411
+ */
126
412
  setParameter(name: string, value: string): Promise<void>;
413
+ /**
414
+ * Sends track metadata (title, artist, album, duration) to the receiver
415
+ * as DAAP-tagged data via SET_PARAMETER.
416
+ *
417
+ * @param session - RTSP session identifier.
418
+ * @param rtpseq - Current RTP sequence number for the RTP-Info header.
419
+ * @param rtptime - Current RTP timestamp for the RTP-Info header.
420
+ * @param metadata - Track metadata to send.
421
+ */
127
422
  setMetadata(session: string, rtpseq: number, rtptime: number, metadata: MediaMetadata): Promise<void>;
423
+ /**
424
+ * Sends album artwork to the receiver via SET_PARAMETER. Automatically
425
+ * detects PNG images by magic bytes, defaulting to JPEG otherwise.
426
+ *
427
+ * @param session - RTSP session identifier.
428
+ * @param rtpseq - Current RTP sequence number for the RTP-Info header.
429
+ * @param rtptime - Current RTP timestamp for the RTP-Info header.
430
+ * @param artwork - Image data buffer (JPEG or PNG).
431
+ */
128
432
  setArtwork(session: string, rtpseq: number, rtptime: number, artwork: Buffer): Promise<void>;
433
+ /**
434
+ * Sends a feedback request to `/feedback` to keep the session alive.
435
+ * Typically called periodically during active streaming.
436
+ *
437
+ * @param allowError - Whether to suppress HTTP error responses.
438
+ * @returns The feedback response.
439
+ */
129
440
  feedback(allowError?: boolean): Promise<Response>;
441
+ /**
442
+ * Sends an RTSP TEARDOWN request to end the streaming session
443
+ * and release server-side resources.
444
+ *
445
+ * @param session - RTSP session identifier to tear down.
446
+ */
130
447
  teardown(session: string): Promise<void>;
131
448
  }
132
449
  //#endregion
133
450
  //#region src/statistics.d.ts
451
+ /**
452
+ * Tracks real-time streaming statistics to detect when audio packet
453
+ * sending falls behind wall-clock time. Uses high-resolution monotonic
454
+ * timers to compare actual frames sent against expected frame count.
455
+ */
134
456
  declare class Statistics {
457
+ /** Audio sample rate in Hz, used to compute expected frame counts. */
135
458
  readonly sampleRate: number;
459
+ /** High-resolution monotonic timestamp (nanoseconds) captured at construction. */
136
460
  readonly startTimeNs: bigint;
461
+ /** Millisecond timestamp marking the start of the current reporting interval. */
137
462
  intervalTime: number;
463
+ /** Total number of audio frames sent since streaming began. */
138
464
  totalFrames: number;
465
+ /** Number of audio frames sent within the current reporting interval. */
139
466
  intervalFrames: number;
467
+ /**
468
+ * Creates a new Statistics tracker, capturing the current time as baseline.
469
+ *
470
+ * @param sampleRate - Audio sample rate in Hz (e.g. 44100).
471
+ */
140
472
  constructor(sampleRate: number);
473
+ /**
474
+ * Computes how many audio frames should have been sent by now,
475
+ * based on elapsed wall-clock time since streaming started.
476
+ */
141
477
  get expectedFrameCount(): number;
478
+ /**
479
+ * Number of frames the sender is lagging behind real-time.
480
+ * A positive value means packets need to be sent faster.
481
+ */
142
482
  get framesBehind(): number;
483
+ /**
484
+ * Whether the current interval has accumulated at least one second
485
+ * worth of frames, indicating it is time to log and reset.
486
+ */
143
487
  get intervalCompleted(): boolean;
488
+ /**
489
+ * Records that additional audio frames have been sent.
490
+ *
491
+ * @param sentFrames - Number of frames just sent.
492
+ */
144
493
  tick(sentFrames: number): void;
494
+ /**
495
+ * Completes the current reporting interval, resetting the interval
496
+ * frame counter and returning timing information for logging.
497
+ *
498
+ * @returns A tuple of [elapsed seconds, frames sent] for the completed interval.
499
+ */
145
500
  newInterval(): [number, number];
146
501
  }
147
502
  //#endregion
148
503
  //#region src/streamClient.d.ts
504
+ /**
505
+ * Event map for the StreamClient, emitted during the audio streaming lifecycle.
506
+ */
149
507
  type EventMap$1 = {
150
- readonly playing: [playbackInfo: PlaybackInfo];
508
+ /** Emitted when audio playback starts, providing current playback info. */readonly playing: [playbackInfo: PlaybackInfo]; /** Emitted when audio playback stops (either naturally or via stop()). */
151
509
  readonly stopped: [];
152
510
  };
511
+ /**
512
+ * Core streaming engine for RAOP audio. Manages the complete audio streaming
513
+ * lifecycle: initialization (encryption/metadata negotiation, control channel
514
+ * setup), real-time PCM packet sending with timing compensation, metadata
515
+ * and artwork publishing, and teardown.
516
+ *
517
+ * Uses a Statistics tracker to maintain real-time pacing and compensates
518
+ * for slow packet sending by bursting additional packets when falling behind.
519
+ */
153
520
  declare class StreamClient extends EventEmitter<EventMap$1> {
154
521
  #private;
522
+ /** Device info dictionary fetched from the receiver during initialization. */
155
523
  get info(): Record<string, unknown>;
524
+ /**
525
+ * Current playback info snapshot, substituting fallback metadata
526
+ * if the caller provided no metadata.
527
+ */
156
528
  get playbackInfo(): PlaybackInfo;
529
+ /**
530
+ * Creates a new stream client.
531
+ *
532
+ * @param context - Application context for logging.
533
+ * @param rtsp - Connected RAOP RTSP client.
534
+ * @param streamContext - Shared mutable streaming state.
535
+ * @param protocol - Protocol handler for transport operations.
536
+ * @param settings - Port configuration settings.
537
+ * @param timingServer - NTP timing server.
538
+ */
157
539
  constructor(context: Context, rtsp: RaopRtspClient, streamContext: StreamContext, protocol: StreamProtocol, settings: Settings, timingServer: TimingServer);
540
+ /**
541
+ * Closes the control channel, releasing its UDP socket.
542
+ */
158
543
  close(): void;
544
+ /**
545
+ * Initializes the streaming session by parsing device capabilities,
546
+ * binding the control channel, fetching device info, performing
547
+ * auth-setup if required, and running the protocol SETUP handshake.
548
+ *
549
+ * @param properties - mDNS TXT record key-value pairs for the device.
550
+ */
159
551
  initialize(properties: Map<string, string>): Promise<void>;
552
+ /**
553
+ * Signals the streaming loop to stop after the current packet.
554
+ * The `sendAudio()` call will return after teardown completes.
555
+ */
160
556
  stop(): void;
557
+ /**
558
+ * Changes the playback volume on the receiver via RTSP SET_PARAMETER.
559
+ *
560
+ * @param volume - Volume level in dBFS.
561
+ */
161
562
  setVolume(volume: number): Promise<void>;
563
+ /**
564
+ * Main entry point for streaming audio. Resets the stream context,
565
+ * connects the UDP audio transport, publishes metadata/artwork/progress,
566
+ * starts the RTSP RECORD session, and enters the real-time streaming loop.
567
+ *
568
+ * On completion or error, performs full teardown: clears the packet backlog,
569
+ * sends RTSP TEARDOWN, closes the UDP transport, and emits 'stopped'.
570
+ *
571
+ * @param source - Audio source providing PCM frames to stream.
572
+ * @param metadata - Track metadata to display on the receiver.
573
+ * @param volume - Optional initial volume as a percentage (0-100), converted to dBFS.
574
+ * @throws When streaming encounters an unrecoverable error.
575
+ */
162
576
  sendAudio(source: AudioSource, metadata?: MediaMetadata, volume?: number): Promise<void>;
163
577
  }
164
578
  //#endregion
165
579
  //#region src/raop.d.ts
580
+ /**
581
+ * Event map for the RaopClient, emitted during the streaming lifecycle.
582
+ */
166
583
  type EventMap = {
167
- readonly playing: [playbackInfo: PlaybackInfo];
584
+ /** Emitted when audio playback starts, providing current playback info. */readonly playing: [playbackInfo: PlaybackInfo]; /** Emitted when audio playback stops. */
168
585
  readonly stopped: [];
169
586
  };
587
+ /**
588
+ * Options for configuring an audio stream session.
589
+ */
170
590
  type StreamOptions = {
171
- readonly metadata?: MediaMetadata;
591
+ /** Optional track metadata to display on the receiver. */readonly metadata?: MediaMetadata; /** Optional initial volume as a percentage (0-100). */
172
592
  readonly volume?: number;
173
593
  };
594
+ /**
595
+ * High-level RAOP client for streaming audio to AirPlay receivers.
596
+ * Wraps the RTSP handshake, UDP audio transport, control channel,
597
+ * and metadata publishing into a simple stream/stop/close API.
598
+ *
599
+ * Instances are created via the static `create()` or `discover()` methods.
600
+ */
174
601
  declare class RaopClient extends EventEmitter<EventMap> {
175
602
  #private;
603
+ /** Application context providing logger and device identity. */
176
604
  get context(): Context;
605
+ /** Unique identifier of the discovered RAOP device. */
177
606
  get deviceId(): string;
607
+ /** IP address of the RAOP receiver. */
178
608
  get address(): string;
609
+ /** Model name of the RAOP receiver (e.g. "AirPort Express"). */
179
610
  get modelName(): string;
611
+ /** Device info dictionary fetched during initialization. */
180
612
  get info(): Record<string, unknown>;
613
+ /**
614
+ * Private constructor — use `RaopClient.create()` or `RaopClient.discover()` instead.
615
+ *
616
+ * @param context - Application context.
617
+ * @param rtsp - Connected RTSP client.
618
+ * @param streamClient - Initialized stream client.
619
+ * @param discoveryResult - mDNS discovery result for the device.
620
+ */
181
621
  private constructor();
622
+ /**
623
+ * Streams audio from a source to the RAOP receiver. Starts the source,
624
+ * sends audio data over RTP, and stops the source when finished or on error.
625
+ *
626
+ * @param source - Audio source providing PCM frames.
627
+ * @param options - Optional metadata and volume settings.
628
+ */
182
629
  stream(source: AudioSource, options?: StreamOptions): Promise<void>;
630
+ /**
631
+ * Signals the stream client to stop sending audio. The current
632
+ * `stream()` call will complete after flushing remaining data.
633
+ */
183
634
  stop(): void;
635
+ /**
636
+ * Changes the playback volume on the receiver.
637
+ *
638
+ * @param volume - Volume level in dBFS.
639
+ */
184
640
  setVolume(volume: number): Promise<void>;
641
+ /**
642
+ * Closes all connections and releases resources. Disconnects the
643
+ * RTSP session and shuts down the control channel.
644
+ */
185
645
  close(): Promise<void>;
646
+ /**
647
+ * Creates a new RaopClient from a pre-discovered device. Connects
648
+ * via RTSP, initializes the stream context, and negotiates transport.
649
+ *
650
+ * @param discoveryResult - mDNS discovery result for the target device.
651
+ * @param timingServer - NTP timing server for clock synchronization.
652
+ * @returns A fully initialized and connected RaopClient.
653
+ */
186
654
  static create(discoveryResult: DiscoveryResult, timingServer: TimingServer): Promise<RaopClient>;
655
+ /**
656
+ * Discovers a RAOP device by its device ID via mDNS, then creates
657
+ * and returns a connected RaopClient.
658
+ *
659
+ * @param deviceId - Unique device identifier to search for.
660
+ * @param timingServer - NTP timing server for clock synchronization.
661
+ * @returns A fully initialized and connected RaopClient.
662
+ */
187
663
  static discover(deviceId: string, timingServer: TimingServer): Promise<RaopClient>;
188
664
  }
189
665
  //#endregion