@basmilius/apple-devices 0.9.11 → 0.9.13
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 +48 -4
- package/dist/index.mjs +216 -19
- package/package.json +5 -5
package/dist/index.d.mts
CHANGED
|
@@ -5,11 +5,12 @@ import { EventEmitter } from "node:events";
|
|
|
5
5
|
import { AccessoryCredentials, AudioSource, DiscoveryResult, TimingServer } from "@basmilius/apple-common";
|
|
6
6
|
import { AttentionState, ButtonPressType, HidCommandKey, LaunchableApp, MediaControlCommandKey, Protocol as Protocol$1, UserAccount } from "@basmilius/apple-companion-link";
|
|
7
7
|
|
|
8
|
-
//#region src/airplay/
|
|
9
|
-
declare class
|
|
8
|
+
//#region src/airplay/player.d.ts
|
|
9
|
+
declare class Player {
|
|
10
10
|
#private;
|
|
11
|
-
get
|
|
11
|
+
get identifier(): string;
|
|
12
12
|
get displayName(): string;
|
|
13
|
+
get isDefaultPlayer(): boolean;
|
|
13
14
|
get nowPlayingInfo(): Proto.NowPlayingInfo | null;
|
|
14
15
|
get playbackQueue(): Proto.PlaybackQueue | null;
|
|
15
16
|
get playbackState(): Proto.PlaybackState_Enum;
|
|
@@ -35,7 +36,7 @@ declare class Client {
|
|
|
35
36
|
get currentItemArtwork(): Uint8Array | null;
|
|
36
37
|
get currentItemArtworkUrl(): string | null;
|
|
37
38
|
get currentItemLyrics(): Proto.LyricsItem | null;
|
|
38
|
-
constructor(
|
|
39
|
+
constructor(identifier: string, displayName: string);
|
|
39
40
|
isCommandSupported(command: Proto.Command): boolean;
|
|
40
41
|
setNowPlayingInfo(nowPlayingInfo: Proto.NowPlayingInfo): void;
|
|
41
42
|
setPlaybackQueue(playbackQueue: Proto.PlaybackQueue): void;
|
|
@@ -44,6 +45,46 @@ declare class Client {
|
|
|
44
45
|
updateContentItem(item: Proto.ContentItem): void;
|
|
45
46
|
}
|
|
46
47
|
//#endregion
|
|
48
|
+
//#region src/airplay/client.d.ts
|
|
49
|
+
declare class Client {
|
|
50
|
+
#private;
|
|
51
|
+
get bundleIdentifier(): string;
|
|
52
|
+
get displayName(): string;
|
|
53
|
+
get players(): Map<string, Player>;
|
|
54
|
+
get activePlayer(): Player | null;
|
|
55
|
+
get nowPlayingInfo(): Proto.NowPlayingInfo | null;
|
|
56
|
+
get playbackQueue(): Proto.PlaybackQueue | null;
|
|
57
|
+
get playbackState(): Proto.PlaybackState_Enum;
|
|
58
|
+
get playbackStateTimestamp(): number;
|
|
59
|
+
get supportedCommands(): Proto.CommandInfo[];
|
|
60
|
+
get title(): string;
|
|
61
|
+
get artist(): string;
|
|
62
|
+
get album(): string;
|
|
63
|
+
get genre(): string;
|
|
64
|
+
get seriesName(): string;
|
|
65
|
+
get seasonNumber(): number;
|
|
66
|
+
get episodeNumber(): number;
|
|
67
|
+
get mediaType(): Proto.ContentItemMetadata_MediaType;
|
|
68
|
+
get contentIdentifier(): string;
|
|
69
|
+
get duration(): number;
|
|
70
|
+
get playbackRate(): number;
|
|
71
|
+
get isPlaying(): boolean;
|
|
72
|
+
get shuffleMode(): Proto.ShuffleMode_Enum;
|
|
73
|
+
get repeatMode(): Proto.RepeatMode_Enum;
|
|
74
|
+
get elapsedTime(): number;
|
|
75
|
+
get currentItem(): Proto.ContentItem | null;
|
|
76
|
+
get currentItemMetadata(): Proto.ContentItemMetadata | null;
|
|
77
|
+
get currentItemArtwork(): Uint8Array | null;
|
|
78
|
+
get currentItemArtworkUrl(): string | null;
|
|
79
|
+
get currentItemLyrics(): Proto.LyricsItem | null;
|
|
80
|
+
constructor(bundleIdentifier: string, displayName: string);
|
|
81
|
+
getOrCreatePlayer(identifier: string, displayName?: string): Player;
|
|
82
|
+
setActivePlayer(identifier: string): void;
|
|
83
|
+
removePlayer(identifier: string): void;
|
|
84
|
+
setDefaultSupportedCommands(supportedCommands: Proto.CommandInfo[]): void;
|
|
85
|
+
isCommandSupported(command: Proto.Command): boolean;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
47
88
|
//#region src/airplay/const.d.ts
|
|
48
89
|
declare const PROTOCOL: unique symbol;
|
|
49
90
|
declare const STATE_SUBSCRIBE_SYMBOL: unique symbol;
|
|
@@ -99,9 +140,11 @@ type EventMap$4 = {
|
|
|
99
140
|
readonly clients: [Record<string, Client>];
|
|
100
141
|
readonly deviceInfo: [Proto.DeviceInfoMessage];
|
|
101
142
|
readonly deviceInfoUpdate: [Proto.DeviceInfoMessage];
|
|
143
|
+
readonly nowPlayingChanged: [client: Client | null, player: Player | null];
|
|
102
144
|
readonly originClientProperties: [Proto.OriginClientPropertiesMessage];
|
|
103
145
|
readonly playerClientProperties: [Proto.PlayerClientPropertiesMessage];
|
|
104
146
|
readonly removeClient: [Proto.RemoveClientMessage];
|
|
147
|
+
readonly removePlayer: [Proto.RemovePlayerMessage];
|
|
105
148
|
readonly sendCommandResult: [Proto.SendCommandResultMessage];
|
|
106
149
|
readonly setArtwork: [Proto.SetArtworkMessage];
|
|
107
150
|
readonly setDefaultSupportedCommands: [Proto.SetDefaultSupportedCommandsMessage];
|
|
@@ -144,6 +187,7 @@ declare class export_default$7 extends EventEmitter<EventMap$4> {
|
|
|
144
187
|
onUpdateContentItem(message: Proto.UpdateContentItemMessage): void;
|
|
145
188
|
onUpdateContentItemArtwork(message: Proto.UpdateContentItemArtworkMessage): void;
|
|
146
189
|
onUpdatePlayer(message: Proto.UpdatePlayerMessage): void;
|
|
190
|
+
onRemovePlayer(message: Proto.RemovePlayerMessage): void;
|
|
147
191
|
onUpdateClient(message: Proto.UpdateClientMessage): void;
|
|
148
192
|
onUpdateOutputDevice(message: Proto.UpdateOutputDeviceMessage): void;
|
|
149
193
|
onVolumeControlAvailability(message: Proto.VolumeControlAvailabilityMessage): void;
|
package/dist/index.mjs
CHANGED
|
@@ -4,21 +4,25 @@ import { EventEmitter } from "node:events";
|
|
|
4
4
|
import { waitFor } from "@basmilius/apple-common";
|
|
5
5
|
import { Protocol as Protocol$1, convertAttentionState } from "@basmilius/apple-companion-link";
|
|
6
6
|
|
|
7
|
-
//#region src/airplay/
|
|
7
|
+
//#region src/airplay/player.ts
|
|
8
8
|
const COCOA_EPOCH_OFFSET = 978307200;
|
|
9
|
+
const DEFAULT_PLAYER_ID = "MediaRemote-DefaultPlayer";
|
|
9
10
|
const extrapolateElapsed = (elapsed, cocoaTimestamp, rate) => {
|
|
10
11
|
if (!rate) return elapsed;
|
|
11
12
|
const timestampUnix = cocoaTimestamp + COCOA_EPOCH_OFFSET;
|
|
12
13
|
const delta = (Date.now() / 1e3 - timestampUnix) * rate;
|
|
13
14
|
return Math.max(0, elapsed + delta);
|
|
14
15
|
};
|
|
15
|
-
var
|
|
16
|
-
get
|
|
17
|
-
return this.#
|
|
16
|
+
var Player = class {
|
|
17
|
+
get identifier() {
|
|
18
|
+
return this.#identifier;
|
|
18
19
|
}
|
|
19
20
|
get displayName() {
|
|
20
21
|
return this.#displayName;
|
|
21
22
|
}
|
|
23
|
+
get isDefaultPlayer() {
|
|
24
|
+
return this.#identifier === DEFAULT_PLAYER_ID;
|
|
25
|
+
}
|
|
22
26
|
get nowPlayingInfo() {
|
|
23
27
|
return this.#nowPlayingInfo;
|
|
24
28
|
}
|
|
@@ -79,8 +83,14 @@ var Client = class {
|
|
|
79
83
|
get elapsedTime() {
|
|
80
84
|
const npi = this.#nowPlayingInfo;
|
|
81
85
|
const meta = this.currentItemMetadata;
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
const npiValid = npi?.elapsedTime != null && npi.timestamp;
|
|
87
|
+
const metaValid = meta?.elapsedTime != null && meta.elapsedTimeTimestamp;
|
|
88
|
+
if (npiValid && metaValid) {
|
|
89
|
+
if (meta.elapsedTimeTimestamp > npi.timestamp) return extrapolateElapsed(meta.elapsedTime, meta.elapsedTimeTimestamp, meta.playbackRate);
|
|
90
|
+
return extrapolateElapsed(npi.elapsedTime, npi.timestamp, npi.playbackRate);
|
|
91
|
+
}
|
|
92
|
+
if (npiValid) return extrapolateElapsed(npi.elapsedTime, npi.timestamp, npi.playbackRate);
|
|
93
|
+
if (metaValid) return extrapolateElapsed(meta.elapsedTime, meta.elapsedTimeTimestamp, meta.playbackRate);
|
|
84
94
|
return npi?.elapsedTime || meta?.elapsedTime || 0;
|
|
85
95
|
}
|
|
86
96
|
get currentItem() {
|
|
@@ -107,18 +117,17 @@ var Client = class {
|
|
|
107
117
|
get currentItemLyrics() {
|
|
108
118
|
return this.currentItem?.lyrics ?? null;
|
|
109
119
|
}
|
|
110
|
-
#
|
|
120
|
+
#identifier;
|
|
111
121
|
#displayName;
|
|
112
122
|
#nowPlayingInfo = null;
|
|
113
123
|
#playbackQueue = null;
|
|
114
124
|
#playbackState;
|
|
115
|
-
#playbackStateTimestamp;
|
|
125
|
+
#playbackStateTimestamp = 0;
|
|
116
126
|
#supportedCommands = [];
|
|
117
|
-
constructor(
|
|
118
|
-
this.#
|
|
127
|
+
constructor(identifier, displayName) {
|
|
128
|
+
this.#identifier = identifier;
|
|
119
129
|
this.#displayName = displayName;
|
|
120
130
|
this.#playbackState = Proto.PlaybackState_Enum.Unknown;
|
|
121
|
-
this.#supportedCommands = [];
|
|
122
131
|
}
|
|
123
132
|
isCommandSupported(command) {
|
|
124
133
|
return this.#supportedCommands.some((c) => c.command === command);
|
|
@@ -150,6 +159,129 @@ var Client = class {
|
|
|
150
159
|
}
|
|
151
160
|
};
|
|
152
161
|
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/airplay/client.ts
|
|
164
|
+
var Client = class {
|
|
165
|
+
get bundleIdentifier() {
|
|
166
|
+
return this.#bundleIdentifier;
|
|
167
|
+
}
|
|
168
|
+
get displayName() {
|
|
169
|
+
return this.#displayName;
|
|
170
|
+
}
|
|
171
|
+
get players() {
|
|
172
|
+
return this.#players;
|
|
173
|
+
}
|
|
174
|
+
get activePlayer() {
|
|
175
|
+
if (this.#activePlayerId) return this.#players.get(this.#activePlayerId) ?? null;
|
|
176
|
+
return this.#players.get(DEFAULT_PLAYER_ID) ?? null;
|
|
177
|
+
}
|
|
178
|
+
get nowPlayingInfo() {
|
|
179
|
+
return this.activePlayer?.nowPlayingInfo ?? null;
|
|
180
|
+
}
|
|
181
|
+
get playbackQueue() {
|
|
182
|
+
return this.activePlayer?.playbackQueue ?? null;
|
|
183
|
+
}
|
|
184
|
+
get playbackState() {
|
|
185
|
+
return this.activePlayer?.playbackState ?? Proto.PlaybackState_Enum.Unknown;
|
|
186
|
+
}
|
|
187
|
+
get playbackStateTimestamp() {
|
|
188
|
+
return this.activePlayer?.playbackStateTimestamp ?? -1;
|
|
189
|
+
}
|
|
190
|
+
get supportedCommands() {
|
|
191
|
+
return this.activePlayer?.supportedCommands ?? this.#defaultSupportedCommands;
|
|
192
|
+
}
|
|
193
|
+
get title() {
|
|
194
|
+
return this.activePlayer?.title ?? "";
|
|
195
|
+
}
|
|
196
|
+
get artist() {
|
|
197
|
+
return this.activePlayer?.artist ?? "";
|
|
198
|
+
}
|
|
199
|
+
get album() {
|
|
200
|
+
return this.activePlayer?.album ?? "";
|
|
201
|
+
}
|
|
202
|
+
get genre() {
|
|
203
|
+
return this.activePlayer?.genre ?? "";
|
|
204
|
+
}
|
|
205
|
+
get seriesName() {
|
|
206
|
+
return this.activePlayer?.seriesName ?? "";
|
|
207
|
+
}
|
|
208
|
+
get seasonNumber() {
|
|
209
|
+
return this.activePlayer?.seasonNumber ?? 0;
|
|
210
|
+
}
|
|
211
|
+
get episodeNumber() {
|
|
212
|
+
return this.activePlayer?.episodeNumber ?? 0;
|
|
213
|
+
}
|
|
214
|
+
get mediaType() {
|
|
215
|
+
return this.activePlayer?.mediaType ?? Proto.ContentItemMetadata_MediaType.UnknownMediaType;
|
|
216
|
+
}
|
|
217
|
+
get contentIdentifier() {
|
|
218
|
+
return this.activePlayer?.contentIdentifier ?? "";
|
|
219
|
+
}
|
|
220
|
+
get duration() {
|
|
221
|
+
return this.activePlayer?.duration ?? 0;
|
|
222
|
+
}
|
|
223
|
+
get playbackRate() {
|
|
224
|
+
return this.activePlayer?.playbackRate ?? 0;
|
|
225
|
+
}
|
|
226
|
+
get isPlaying() {
|
|
227
|
+
return this.activePlayer?.isPlaying ?? false;
|
|
228
|
+
}
|
|
229
|
+
get shuffleMode() {
|
|
230
|
+
return this.activePlayer?.shuffleMode ?? Proto.ShuffleMode_Enum.Unknown;
|
|
231
|
+
}
|
|
232
|
+
get repeatMode() {
|
|
233
|
+
return this.activePlayer?.repeatMode ?? Proto.RepeatMode_Enum.Unknown;
|
|
234
|
+
}
|
|
235
|
+
get elapsedTime() {
|
|
236
|
+
return this.activePlayer?.elapsedTime ?? 0;
|
|
237
|
+
}
|
|
238
|
+
get currentItem() {
|
|
239
|
+
return this.activePlayer?.currentItem ?? null;
|
|
240
|
+
}
|
|
241
|
+
get currentItemMetadata() {
|
|
242
|
+
return this.activePlayer?.currentItemMetadata ?? null;
|
|
243
|
+
}
|
|
244
|
+
get currentItemArtwork() {
|
|
245
|
+
return this.activePlayer?.currentItemArtwork ?? null;
|
|
246
|
+
}
|
|
247
|
+
get currentItemArtworkUrl() {
|
|
248
|
+
return this.activePlayer?.currentItemArtworkUrl ?? null;
|
|
249
|
+
}
|
|
250
|
+
get currentItemLyrics() {
|
|
251
|
+
return this.activePlayer?.currentItemLyrics ?? null;
|
|
252
|
+
}
|
|
253
|
+
#bundleIdentifier;
|
|
254
|
+
#displayName;
|
|
255
|
+
#players = /* @__PURE__ */ new Map();
|
|
256
|
+
#activePlayerId = null;
|
|
257
|
+
#defaultSupportedCommands = [];
|
|
258
|
+
constructor(bundleIdentifier, displayName) {
|
|
259
|
+
this.#bundleIdentifier = bundleIdentifier;
|
|
260
|
+
this.#displayName = displayName;
|
|
261
|
+
}
|
|
262
|
+
getOrCreatePlayer(identifier, displayName) {
|
|
263
|
+
let player = this.#players.get(identifier);
|
|
264
|
+
if (!player) {
|
|
265
|
+
player = new Player(identifier, displayName ?? identifier);
|
|
266
|
+
this.#players.set(identifier, player);
|
|
267
|
+
}
|
|
268
|
+
return player;
|
|
269
|
+
}
|
|
270
|
+
setActivePlayer(identifier) {
|
|
271
|
+
this.#activePlayerId = identifier;
|
|
272
|
+
}
|
|
273
|
+
removePlayer(identifier) {
|
|
274
|
+
this.#players.delete(identifier);
|
|
275
|
+
if (this.#activePlayerId === identifier) this.#activePlayerId = null;
|
|
276
|
+
}
|
|
277
|
+
setDefaultSupportedCommands(supportedCommands) {
|
|
278
|
+
this.#defaultSupportedCommands = supportedCommands;
|
|
279
|
+
}
|
|
280
|
+
isCommandSupported(command) {
|
|
281
|
+
return this.activePlayer?.isCommandSupported(command) ?? false;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
153
285
|
//#endregion
|
|
154
286
|
//#region src/airplay/const.ts
|
|
155
287
|
const FEEDBACK_INTERVAL = 2e3;
|
|
@@ -350,6 +482,7 @@ var state_default = class extends EventEmitter {
|
|
|
350
482
|
#device;
|
|
351
483
|
#clients;
|
|
352
484
|
#nowPlayingClientBundleIdentifier;
|
|
485
|
+
#nowPlayingSnapshot;
|
|
353
486
|
#outputDeviceUID;
|
|
354
487
|
#outputDevices = [];
|
|
355
488
|
#volume;
|
|
@@ -364,6 +497,7 @@ var state_default = class extends EventEmitter {
|
|
|
364
497
|
this.onOriginClientProperties = this.onOriginClientProperties.bind(this);
|
|
365
498
|
this.onPlayerClientProperties = this.onPlayerClientProperties.bind(this);
|
|
366
499
|
this.onRemoveClient = this.onRemoveClient.bind(this);
|
|
500
|
+
this.onRemovePlayer = this.onRemovePlayer.bind(this);
|
|
367
501
|
this.onSendCommandResult = this.onSendCommandResult.bind(this);
|
|
368
502
|
this.onSetArtwork = this.onSetArtwork.bind(this);
|
|
369
503
|
this.onSetDefaultSupportedCommands = this.onSetDefaultSupportedCommands.bind(this);
|
|
@@ -385,6 +519,7 @@ var state_default = class extends EventEmitter {
|
|
|
385
519
|
this.#dataStream.on("originClientProperties", this.onOriginClientProperties);
|
|
386
520
|
this.#dataStream.on("playerClientProperties", this.onPlayerClientProperties);
|
|
387
521
|
this.#dataStream.on("removeClient", this.onRemoveClient);
|
|
522
|
+
this.#dataStream.on("removePlayer", this.onRemovePlayer);
|
|
388
523
|
this.#dataStream.on("sendCommandResult", this.onSendCommandResult);
|
|
389
524
|
this.#dataStream.on("setArtwork", this.onSetArtwork);
|
|
390
525
|
this.#dataStream.on("setDefaultSupportedCommands", this.onSetDefaultSupportedCommands);
|
|
@@ -408,6 +543,7 @@ var state_default = class extends EventEmitter {
|
|
|
408
543
|
dataStream.off("originClientProperties", this.onOriginClientProperties);
|
|
409
544
|
dataStream.off("playerClientProperties", this.onPlayerClientProperties);
|
|
410
545
|
dataStream.off("removeClient", this.onRemoveClient);
|
|
546
|
+
dataStream.off("removePlayer", this.onRemovePlayer);
|
|
411
547
|
dataStream.off("sendCommandResult", this.onSendCommandResult);
|
|
412
548
|
dataStream.off("setArtwork", this.onSetArtwork);
|
|
413
549
|
dataStream.off("setDefaultSupportedCommands", this.onSetDefaultSupportedCommands);
|
|
@@ -426,6 +562,7 @@ var state_default = class extends EventEmitter {
|
|
|
426
562
|
clear() {
|
|
427
563
|
this.#clients = {};
|
|
428
564
|
this.#nowPlayingClientBundleIdentifier = null;
|
|
565
|
+
this.#nowPlayingSnapshot = null;
|
|
429
566
|
this.#outputDeviceUID = null;
|
|
430
567
|
this.#outputDevices = [];
|
|
431
568
|
this.#volume = 0;
|
|
@@ -452,8 +589,12 @@ var state_default = class extends EventEmitter {
|
|
|
452
589
|
}
|
|
453
590
|
onRemoveClient(message) {
|
|
454
591
|
if (!(message.client.bundleIdentifier in this.#clients)) return;
|
|
592
|
+
const wasActive = this.#nowPlayingClientBundleIdentifier === message.client.bundleIdentifier;
|
|
455
593
|
delete this.#clients[message.client.bundleIdentifier];
|
|
594
|
+
if (wasActive) this.#nowPlayingClientBundleIdentifier = null;
|
|
595
|
+
this.emit("removeClient", message);
|
|
456
596
|
this.emit("clients", this.#clients);
|
|
597
|
+
if (wasActive) this.#emitNowPlayingChangedIfNeeded();
|
|
457
598
|
}
|
|
458
599
|
onSendCommandResult(message) {
|
|
459
600
|
this.emit("sendCommandResult", message);
|
|
@@ -462,35 +603,59 @@ var state_default = class extends EventEmitter {
|
|
|
462
603
|
this.emit("setArtwork", message);
|
|
463
604
|
}
|
|
464
605
|
onSetDefaultSupportedCommands(message) {
|
|
606
|
+
if (message.playerPath?.client?.bundleIdentifier && message.supportedCommands) this.#client(message.playerPath.client.bundleIdentifier, message.playerPath.client.displayName).setDefaultSupportedCommands(message.supportedCommands.supportedCommands);
|
|
465
607
|
this.emit("setDefaultSupportedCommands", message);
|
|
466
608
|
}
|
|
467
609
|
onSetNowPlayingClient(message) {
|
|
468
610
|
this.#nowPlayingClientBundleIdentifier = message.client?.bundleIdentifier ?? null;
|
|
469
611
|
this.emit("setNowPlayingClient", message);
|
|
612
|
+
this.#emitNowPlayingChangedIfNeeded();
|
|
470
613
|
}
|
|
471
614
|
onSetNowPlayingPlayer(message) {
|
|
615
|
+
if (message.playerPath?.client?.bundleIdentifier && message.playerPath?.player?.identifier) {
|
|
616
|
+
const client = this.#client(message.playerPath.client.bundleIdentifier, message.playerPath.client.displayName);
|
|
617
|
+
client.getOrCreatePlayer(message.playerPath.player.identifier, message.playerPath.player.displayName);
|
|
618
|
+
client.setActivePlayer(message.playerPath.player.identifier);
|
|
619
|
+
}
|
|
472
620
|
this.emit("setNowPlayingPlayer", message);
|
|
621
|
+
this.#emitNowPlayingChangedIfNeeded();
|
|
473
622
|
}
|
|
474
623
|
onSetState(message) {
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (message.
|
|
624
|
+
const bundleIdentifier = message.playerPath.client.bundleIdentifier;
|
|
625
|
+
const client = this.#client(bundleIdentifier, message.displayName);
|
|
626
|
+
const playerIdentifier = message.playerPath?.player?.identifier || "MediaRemote-DefaultPlayer";
|
|
627
|
+
const player = client.getOrCreatePlayer(playerIdentifier, message.playerPath?.player?.displayName);
|
|
628
|
+
if (message.nowPlayingInfo) player.setNowPlayingInfo(message.nowPlayingInfo);
|
|
629
|
+
if (message.playbackState) player.setPlaybackState(message.playbackState, message.playbackStateTimestamp);
|
|
630
|
+
if (message.supportedCommands) player.setSupportedCommands(message.supportedCommands.supportedCommands);
|
|
631
|
+
if (message.playbackQueue) player.setPlaybackQueue(message.playbackQueue);
|
|
480
632
|
this.emit("setState", message);
|
|
633
|
+
if (bundleIdentifier === this.#nowPlayingClientBundleIdentifier) this.#emitNowPlayingChangedIfNeeded();
|
|
481
634
|
}
|
|
482
635
|
onUpdateContentItem(message) {
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
636
|
+
const bundleIdentifier = message.playerPath.client.bundleIdentifier;
|
|
637
|
+
const client = this.#client(bundleIdentifier, message.playerPath.client.displayName);
|
|
638
|
+
const playerIdentifier = message.playerPath?.player?.identifier || "MediaRemote-DefaultPlayer";
|
|
639
|
+
const player = client.getOrCreatePlayer(playerIdentifier, message.playerPath?.player?.displayName);
|
|
640
|
+
for (const item of message.contentItems) player.updateContentItem(item);
|
|
486
641
|
this.emit("updateContentItem", message);
|
|
642
|
+
if (bundleIdentifier === this.#nowPlayingClientBundleIdentifier) this.#emitNowPlayingChangedIfNeeded();
|
|
487
643
|
}
|
|
488
644
|
onUpdateContentItemArtwork(message) {
|
|
489
645
|
this.emit("updateContentItemArtwork", message);
|
|
490
646
|
}
|
|
491
647
|
onUpdatePlayer(message) {
|
|
648
|
+
if (message.playerPath?.client?.bundleIdentifier && message.playerPath?.player?.identifier) this.#client(message.playerPath.client.bundleIdentifier, message.playerPath.client.displayName).getOrCreatePlayer(message.playerPath.player.identifier, message.playerPath.player.displayName);
|
|
492
649
|
this.emit("updatePlayer", message);
|
|
493
650
|
}
|
|
651
|
+
onRemovePlayer(message) {
|
|
652
|
+
if (message.playerPath?.client?.bundleIdentifier && message.playerPath?.player?.identifier) {
|
|
653
|
+
const client = this.#clients[message.playerPath.client.bundleIdentifier];
|
|
654
|
+
if (client) client.removePlayer(message.playerPath.player.identifier);
|
|
655
|
+
}
|
|
656
|
+
this.emit("removePlayer", message);
|
|
657
|
+
if (message.playerPath?.client?.bundleIdentifier === this.#nowPlayingClientBundleIdentifier) this.#emitNowPlayingChangedIfNeeded();
|
|
658
|
+
}
|
|
494
659
|
onUpdateClient(message) {
|
|
495
660
|
this.#client(message.client.bundleIdentifier, message.client.displayName);
|
|
496
661
|
this.emit("clients", this.#clients);
|
|
@@ -522,6 +687,38 @@ var state_default = class extends EventEmitter {
|
|
|
522
687
|
return client;
|
|
523
688
|
}
|
|
524
689
|
}
|
|
690
|
+
#createNowPlayingSnapshot() {
|
|
691
|
+
const client = this.nowPlayingClient;
|
|
692
|
+
const player = client?.activePlayer ?? null;
|
|
693
|
+
return {
|
|
694
|
+
bundleIdentifier: client?.bundleIdentifier ?? null,
|
|
695
|
+
playerIdentifier: player?.identifier ?? null,
|
|
696
|
+
playbackState: player?.playbackState ?? Proto.PlaybackState_Enum.Unknown,
|
|
697
|
+
title: player?.title ?? "",
|
|
698
|
+
artist: player?.artist ?? "",
|
|
699
|
+
album: player?.album ?? "",
|
|
700
|
+
genre: player?.genre ?? "",
|
|
701
|
+
duration: player?.duration ?? 0,
|
|
702
|
+
shuffleMode: player?.shuffleMode ?? Proto.ShuffleMode_Enum.Unknown,
|
|
703
|
+
repeatMode: player?.repeatMode ?? Proto.RepeatMode_Enum.Unknown,
|
|
704
|
+
mediaType: player?.mediaType ?? Proto.ContentItemMetadata_MediaType.UnknownMediaType,
|
|
705
|
+
seriesName: player?.seriesName ?? "",
|
|
706
|
+
seasonNumber: player?.seasonNumber ?? 0,
|
|
707
|
+
episodeNumber: player?.episodeNumber ?? 0,
|
|
708
|
+
contentIdentifier: player?.contentIdentifier ?? ""
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
#emitNowPlayingChangedIfNeeded() {
|
|
712
|
+
const snapshot = this.#createNowPlayingSnapshot();
|
|
713
|
+
const previous = this.#nowPlayingSnapshot;
|
|
714
|
+
if (previous && this.#snapshotsEqual(previous, snapshot)) return;
|
|
715
|
+
this.#nowPlayingSnapshot = snapshot;
|
|
716
|
+
const client = this.nowPlayingClient;
|
|
717
|
+
this.emit("nowPlayingChanged", client, client?.activePlayer ?? null);
|
|
718
|
+
}
|
|
719
|
+
#snapshotsEqual(a, b) {
|
|
720
|
+
return a.bundleIdentifier === b.bundleIdentifier && a.playerIdentifier === b.playerIdentifier && a.playbackState === b.playbackState && a.title === b.title && a.artist === b.artist && a.album === b.album && a.genre === b.genre && a.duration === b.duration && a.shuffleMode === b.shuffleMode && a.repeatMode === b.repeatMode && a.mediaType === b.mediaType && a.seriesName === b.seriesName && a.seasonNumber === b.seasonNumber && a.episodeNumber === b.episodeNumber && a.contentIdentifier === b.contentIdentifier;
|
|
721
|
+
}
|
|
525
722
|
};
|
|
526
723
|
|
|
527
724
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basmilius/apple-devices",
|
|
3
3
|
"description": "Exposes various Apple devices to connect with either AirPlay or Companion Link.",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.13",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": {
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
}
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@basmilius/apple-airplay": "0.9.
|
|
53
|
-
"@basmilius/apple-common": "0.9.
|
|
54
|
-
"@basmilius/apple-companion-link": "0.9.
|
|
55
|
-
"@basmilius/apple-encoding": "0.9.
|
|
52
|
+
"@basmilius/apple-airplay": "0.9.13",
|
|
53
|
+
"@basmilius/apple-common": "0.9.13",
|
|
54
|
+
"@basmilius/apple-companion-link": "0.9.13",
|
|
55
|
+
"@basmilius/apple-encoding": "0.9.13"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/bun": "^1.3.9",
|