@basmilius/apple-devices 0.8.2 → 0.9.2

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.mjs CHANGED
@@ -1,98 +1,9 @@
1
- import { EventEmitter } from "node:events";
2
1
  import * as AirPlay from "@basmilius/apple-airplay";
3
2
  import { DataStreamMessage, Proto, Protocol } from "@basmilius/apple-airplay";
3
+ 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/const.ts
8
- const FEEDBACK_INTERVAL = 2e3;
9
- const PROTOCOL = Symbol("com.basmilius.airplay:protocol");
10
- const STATE_SUBSCRIBE_SYMBOL = Symbol("com.basmilius.airplay:subscribe");
11
- const STATE_UNSUBSCRIBE_SYMBOL = Symbol("com.basmilius.airplay:unsubscribe");
12
-
13
- //#endregion
14
- //#region src/airplay/remote.ts
15
- var remote_default = class {
16
- get #dataStream() {
17
- return this.#protocol.dataStream;
18
- }
19
- get #protocol() {
20
- return this.#device[PROTOCOL];
21
- }
22
- #device;
23
- constructor(device) {
24
- this.#device = device;
25
- }
26
- async up() {
27
- await this.pressAndRelease(1, 140);
28
- }
29
- async down() {
30
- await this.pressAndRelease(1, 141);
31
- }
32
- async left() {
33
- await this.pressAndRelease(1, 139);
34
- }
35
- async right() {
36
- await this.pressAndRelease(1, 138);
37
- }
38
- async menu() {
39
- await this.pressAndRelease(1, 134);
40
- }
41
- async play() {
42
- await this.pressAndRelease(12, 176);
43
- }
44
- async playPause() {
45
- if (this.#device.state.nowPlayingClient?.playbackState === Proto.PlaybackState_Enum.Playing) await this.pause();
46
- else await this.play();
47
- }
48
- async pause() {
49
- await this.pressAndRelease(12, 177);
50
- }
51
- async next() {
52
- await this.pressAndRelease(12, 181);
53
- }
54
- async previous() {
55
- await this.pressAndRelease(12, 182);
56
- }
57
- async suspend() {
58
- await this.pressAndRelease(1, 130);
59
- }
60
- async select() {
61
- await this.pressAndRelease(1, 137);
62
- }
63
- async wake() {
64
- await this.pressAndRelease(1, 131);
65
- }
66
- async home() {
67
- await this.pressAndRelease(12, 64);
68
- }
69
- async volumeUp() {
70
- await this.pressAndRelease(12, 233);
71
- }
72
- async volumeDown() {
73
- await this.pressAndRelease(12, 234);
74
- }
75
- async mute() {
76
- await this.pressAndRelease(12, 226);
77
- }
78
- async doublePress(usePage, usage) {
79
- await this.pressAndRelease(usePage, usage);
80
- await waitFor(150);
81
- await this.pressAndRelease(usePage, usage);
82
- }
83
- async longPress(usePage, usage, duration = 1e3) {
84
- await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, true));
85
- await waitFor(duration);
86
- await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, false));
87
- }
88
- async pressAndRelease(usePage, usage) {
89
- await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, true));
90
- await waitFor(25);
91
- await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, false));
92
- }
93
- };
94
-
95
- //#endregion
96
7
  //#region ../../node_modules/.bun/lodash-es@4.17.23/node_modules/lodash-es/_freeGlobal.js
97
8
  /** Detect free variable `global` from Node.js. */
98
9
  var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
@@ -2022,6 +1933,9 @@ var Client = class {
2022
1933
  get displayName() {
2023
1934
  return this.#displayName;
2024
1935
  }
1936
+ get nowPlayingInfo() {
1937
+ return this.#nowPlayingInfo;
1938
+ }
2025
1939
  get playbackQueue() {
2026
1940
  return this.#playbackQueue;
2027
1941
  }
@@ -2034,8 +1948,60 @@ var Client = class {
2034
1948
  get supportedCommands() {
2035
1949
  return this.#supportedCommands;
2036
1950
  }
1951
+ get title() {
1952
+ return this.#nowPlayingInfo?.title || this.currentItemMetadata?.title || "";
1953
+ }
1954
+ get artist() {
1955
+ return this.#nowPlayingInfo?.artist || this.currentItemMetadata?.trackArtistName || "";
1956
+ }
1957
+ get album() {
1958
+ return this.#nowPlayingInfo?.album || this.currentItemMetadata?.albumName || "";
1959
+ }
1960
+ get duration() {
1961
+ return this.#nowPlayingInfo?.duration || this.currentItemMetadata?.duration || 0;
1962
+ }
1963
+ get playbackRate() {
1964
+ return this.#nowPlayingInfo?.playbackRate ?? this.currentItemMetadata?.playbackRate ?? 0;
1965
+ }
1966
+ get isPlaying() {
1967
+ return this.#playbackState === Proto.PlaybackState_Enum.Playing;
1968
+ }
1969
+ get elapsedTime() {
1970
+ const npi = this.#nowPlayingInfo;
1971
+ const meta = this.currentItemMetadata;
1972
+ const elapsed = npi?.elapsedTime || meta?.elapsedTime || 0;
1973
+ const rate = npi?.playbackRate ?? meta?.playbackRate ?? 0;
1974
+ const timestamp = npi?.timestamp || meta?.elapsedTimeTimestamp || 0;
1975
+ if (rate === 0 || timestamp === 0) return elapsed;
1976
+ return elapsed + (Date.now() / 1e3 - timestamp) * rate;
1977
+ }
1978
+ get currentItem() {
1979
+ if (!this.#playbackQueue || this.#playbackQueue.contentItems.length === 0) return null;
1980
+ return this.#playbackQueue.contentItems[this.#playbackQueue.location] ?? this.#playbackQueue.contentItems[0] ?? null;
1981
+ }
1982
+ get currentItemMetadata() {
1983
+ return this.currentItem?.metadata ?? null;
1984
+ }
1985
+ get currentItemArtwork() {
1986
+ const item = this.currentItem;
1987
+ if (!item) return null;
1988
+ if (item.artworkData?.byteLength > 0) return item.artworkData;
1989
+ if (item.dataArtworks.length > 0 && item.dataArtworks[0].imageData?.byteLength > 0) return item.dataArtworks[0].imageData;
1990
+ return null;
1991
+ }
1992
+ get currentItemArtworkUrl() {
1993
+ const metadata = this.currentItemMetadata;
1994
+ if (metadata?.artworkURL) return metadata.artworkURL;
1995
+ const item = this.currentItem;
1996
+ if (item?.remoteArtworks.length > 0 && item.remoteArtworks[0].artworkURLString) return item.remoteArtworks[0].artworkURLString;
1997
+ return null;
1998
+ }
1999
+ get currentItemLyrics() {
2000
+ return this.currentItem?.lyrics ?? null;
2001
+ }
2037
2002
  #bundleIdentifier;
2038
2003
  #displayName;
2004
+ #nowPlayingInfo = null;
2039
2005
  #playbackQueue = null;
2040
2006
  #playbackState;
2041
2007
  #playbackStateTimestamp;
@@ -2049,6 +2015,9 @@ var Client = class {
2049
2015
  isCommandSupported(command) {
2050
2016
  return this.#supportedCommands.some((c) => c.command === command);
2051
2017
  }
2018
+ setNowPlayingInfo(nowPlayingInfo) {
2019
+ this.#nowPlayingInfo = nowPlayingInfo;
2020
+ }
2052
2021
  setPlaybackQueue(playbackQueue) {
2053
2022
  this.#playbackQueue = playbackQueue;
2054
2023
  }
@@ -2068,6 +2037,173 @@ var Client = class {
2068
2037
  }
2069
2038
  };
2070
2039
 
2040
+ //#endregion
2041
+ //#region src/airplay/const.ts
2042
+ const FEEDBACK_INTERVAL = 2e3;
2043
+ const PROTOCOL = Symbol("com.basmilius.airplay:protocol");
2044
+ const STATE_SUBSCRIBE_SYMBOL = Symbol("com.basmilius.airplay:subscribe");
2045
+ const STATE_UNSUBSCRIBE_SYMBOL = Symbol("com.basmilius.airplay:unsubscribe");
2046
+
2047
+ //#endregion
2048
+ //#region src/airplay/remote.ts
2049
+ var remote_default = class {
2050
+ get #dataStream() {
2051
+ return this.#protocol.dataStream;
2052
+ }
2053
+ get #protocol() {
2054
+ return this.#device[PROTOCOL];
2055
+ }
2056
+ #device;
2057
+ constructor(device) {
2058
+ this.#device = device;
2059
+ }
2060
+ async up() {
2061
+ await this.pressAndRelease(1, 140);
2062
+ }
2063
+ async down() {
2064
+ await this.pressAndRelease(1, 141);
2065
+ }
2066
+ async left() {
2067
+ await this.pressAndRelease(1, 139);
2068
+ }
2069
+ async right() {
2070
+ await this.pressAndRelease(1, 138);
2071
+ }
2072
+ async menu() {
2073
+ await this.pressAndRelease(1, 134);
2074
+ }
2075
+ async select() {
2076
+ await this.pressAndRelease(1, 137);
2077
+ }
2078
+ async home() {
2079
+ await this.pressAndRelease(12, 64);
2080
+ }
2081
+ async suspend() {
2082
+ await this.pressAndRelease(1, 130);
2083
+ }
2084
+ async wake() {
2085
+ await this.pressAndRelease(1, 131);
2086
+ }
2087
+ async play() {
2088
+ await this.pressAndRelease(12, 176);
2089
+ }
2090
+ async pause() {
2091
+ await this.pressAndRelease(12, 177);
2092
+ }
2093
+ async playPause() {
2094
+ if (this.#device.state.nowPlayingClient?.isPlaying) await this.pause();
2095
+ else await this.play();
2096
+ }
2097
+ async next() {
2098
+ await this.pressAndRelease(12, 181);
2099
+ }
2100
+ async previous() {
2101
+ await this.pressAndRelease(12, 182);
2102
+ }
2103
+ async volumeUp() {
2104
+ await this.pressAndRelease(12, 233);
2105
+ }
2106
+ async volumeDown() {
2107
+ await this.pressAndRelease(12, 234);
2108
+ }
2109
+ async mute() {
2110
+ await this.pressAndRelease(12, 226);
2111
+ }
2112
+ async commandPlay() {
2113
+ await this.#sendCommand(Proto.Command.Play);
2114
+ }
2115
+ async commandPause() {
2116
+ await this.#sendCommand(Proto.Command.Pause);
2117
+ }
2118
+ async commandTogglePlayPause() {
2119
+ await this.#sendCommand(Proto.Command.TogglePlayPause);
2120
+ }
2121
+ async commandStop() {
2122
+ await this.#sendCommand(Proto.Command.Stop);
2123
+ }
2124
+ async commandNextTrack() {
2125
+ await this.#sendCommand(Proto.Command.NextTrack);
2126
+ }
2127
+ async commandPreviousTrack() {
2128
+ await this.#sendCommand(Proto.Command.PreviousTrack);
2129
+ }
2130
+ async commandSkipForward(interval = 15) {
2131
+ await this.#dataStream.exchange(DataStreamMessage.sendCommandWithSkipInterval(Proto.Command.SkipForward, interval));
2132
+ }
2133
+ async commandSkipBackward(interval = 15) {
2134
+ await this.#dataStream.exchange(DataStreamMessage.sendCommandWithSkipInterval(Proto.Command.SkipBackward, interval));
2135
+ }
2136
+ async commandSeekToPosition(position) {
2137
+ await this.#dataStream.exchange(DataStreamMessage.sendCommandWithPlaybackPosition(Proto.Command.SeekToPlaybackPosition, position));
2138
+ }
2139
+ async commandSetShuffleMode(mode) {
2140
+ await this.#dataStream.exchange(DataStreamMessage.sendCommandWithShuffleMode(Proto.Command.ChangeShuffleMode, mode));
2141
+ }
2142
+ async commandSetRepeatMode(mode) {
2143
+ await this.#dataStream.exchange(DataStreamMessage.sendCommandWithRepeatMode(Proto.Command.ChangeRepeatMode, mode));
2144
+ }
2145
+ async commandChangePlaybackRate(rate) {
2146
+ await this.#dataStream.exchange(DataStreamMessage.sendCommandWithPlaybackRate(Proto.Command.ChangePlaybackRate, rate));
2147
+ }
2148
+ async commandNextChapter() {
2149
+ await this.#sendCommand(Proto.Command.NextChapter);
2150
+ }
2151
+ async commandPreviousChapter() {
2152
+ await this.#sendCommand(Proto.Command.PreviousChapter);
2153
+ }
2154
+ async tap(x, y, finger = 1) {
2155
+ await this.#sendTouch(x, y, 1, finger);
2156
+ await waitFor(50);
2157
+ await this.#sendTouch(x, y, 4, finger);
2158
+ }
2159
+ async swipeUp(duration = 200) {
2160
+ await this.#swipe(200, 400, 200, 100, duration);
2161
+ }
2162
+ async swipeDown(duration = 200) {
2163
+ await this.#swipe(200, 100, 200, 400, duration);
2164
+ }
2165
+ async swipeLeft(duration = 200) {
2166
+ await this.#swipe(400, 200, 100, 200, duration);
2167
+ }
2168
+ async swipeRight(duration = 200) {
2169
+ await this.#swipe(100, 200, 400, 200, duration);
2170
+ }
2171
+ async doublePress(usePage, usage) {
2172
+ await this.pressAndRelease(usePage, usage);
2173
+ await waitFor(150);
2174
+ await this.pressAndRelease(usePage, usage);
2175
+ }
2176
+ async longPress(usePage, usage, duration = 1e3) {
2177
+ await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, true));
2178
+ await waitFor(duration);
2179
+ await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, false));
2180
+ }
2181
+ async pressAndRelease(usePage, usage) {
2182
+ await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, true));
2183
+ await waitFor(25);
2184
+ await this.#dataStream.exchange(DataStreamMessage.sendHIDEvent(usePage, usage, false));
2185
+ }
2186
+ async #sendCommand(command, options) {
2187
+ await this.#dataStream.exchange(DataStreamMessage.sendCommand(command, options));
2188
+ }
2189
+ async #sendTouch(x, y, phase, finger) {
2190
+ await this.#dataStream.exchange(DataStreamMessage.sendVirtualTouchEvent(x, y, phase, finger));
2191
+ }
2192
+ async #swipe(startX, startY, endX, endY, duration) {
2193
+ const steps = Math.max(4, Math.floor(duration / 50));
2194
+ const deltaX = (endX - startX) / steps;
2195
+ const deltaY = (endY - startY) / steps;
2196
+ const stepDuration = duration / steps;
2197
+ await this.#sendTouch(startX, startY, 1, 1);
2198
+ for (let i = 1; i < steps; i++) {
2199
+ await waitFor(stepDuration);
2200
+ await this.#sendTouch(Math.round(startX + deltaX * i), Math.round(startY + deltaY * i), 2, 1);
2201
+ }
2202
+ await waitFor(stepDuration);
2203
+ await this.#sendTouch(endX, endY, 4, 1);
2204
+ }
2205
+ };
2206
+
2071
2207
  //#endregion
2072
2208
  //#region src/airplay/state.ts
2073
2209
  var state_default = class extends EventEmitter {
@@ -2086,6 +2222,9 @@ var state_default = class extends EventEmitter {
2086
2222
  get outputDeviceUID() {
2087
2223
  return this.#outputDeviceUID;
2088
2224
  }
2225
+ get outputDevices() {
2226
+ return this.#outputDevices;
2227
+ }
2089
2228
  get volume() {
2090
2229
  return this.#volume;
2091
2230
  }
@@ -2099,6 +2238,7 @@ var state_default = class extends EventEmitter {
2099
2238
  #clients;
2100
2239
  #nowPlayingClientBundleIdentifier;
2101
2240
  #outputDeviceUID;
2241
+ #outputDevices = [];
2102
2242
  #volume;
2103
2243
  #volumeAvailable;
2104
2244
  #volumeCapabilities;
@@ -2174,6 +2314,7 @@ var state_default = class extends EventEmitter {
2174
2314
  this.#clients = {};
2175
2315
  this.#nowPlayingClientBundleIdentifier = null;
2176
2316
  this.#outputDeviceUID = null;
2317
+ this.#outputDevices = [];
2177
2318
  this.#volume = 0;
2178
2319
  this.#volumeAvailable = false;
2179
2320
  this.#volumeCapabilities = Proto.VolumeCapabilities_Enum.None;
@@ -2219,6 +2360,7 @@ var state_default = class extends EventEmitter {
2219
2360
  }
2220
2361
  onSetState(message) {
2221
2362
  const client = this.#client(message.playerPath.client.bundleIdentifier, message.displayName);
2363
+ if (message.nowPlayingInfo) client.setNowPlayingInfo(message.nowPlayingInfo);
2222
2364
  if (message.playbackState) client.setPlaybackState(message.playbackState, message.playbackStateTimestamp);
2223
2365
  if (message.supportedCommands) client.setSupportedCommands(message.supportedCommands.supportedCommands);
2224
2366
  if (message.playbackQueue) client.setPlaybackQueue(message.playbackQueue);
@@ -2241,6 +2383,7 @@ var state_default = class extends EventEmitter {
2241
2383
  this.emit("clients", this.#clients);
2242
2384
  }
2243
2385
  onUpdateOutputDevice(message) {
2386
+ this.#outputDevices = message.outputDevices;
2244
2387
  this.emit("updateOutputDevice", message);
2245
2388
  }
2246
2389
  onVolumeControlAvailability(message) {
@@ -2400,6 +2543,18 @@ var device_default = class extends EventEmitter {
2400
2543
  this.disconnect();
2401
2544
  } catch (_) {}
2402
2545
  }
2546
+ async addOutputDevices(deviceUIDs) {
2547
+ await this.#protocol.dataStream.exchange(DataStreamMessage.modifyOutputContext(deviceUIDs));
2548
+ }
2549
+ async removeOutputDevices(deviceUIDs) {
2550
+ await this.#protocol.dataStream.exchange(DataStreamMessage.modifyOutputContext([], deviceUIDs));
2551
+ }
2552
+ async setOutputDevices(deviceUIDs) {
2553
+ await this.#protocol.dataStream.exchange(DataStreamMessage.modifyOutputContext([], [], deviceUIDs));
2554
+ }
2555
+ async streamAudio(source) {
2556
+ await this.#protocol.setupAudioStream(source);
2557
+ }
2403
2558
  async requestPlaybackQueue(length) {
2404
2559
  await this.#protocol.dataStream.exchange(DataStreamMessage.playbackQueueRequest(0, length));
2405
2560
  }
@@ -2631,26 +2786,56 @@ var apple_tv_default = class extends EventEmitter {
2631
2786
  get companionLink() {
2632
2787
  return this.#companionLink;
2633
2788
  }
2789
+ get remote() {
2790
+ return this.#airplay.remote;
2791
+ }
2792
+ get state() {
2793
+ return this.#airplay.state;
2794
+ }
2795
+ get volumeControl() {
2796
+ return this.#airplay.volume;
2797
+ }
2634
2798
  get bundleIdentifier() {
2635
- return this.#airplay.state.nowPlayingClient?.bundleIdentifier ?? null;
2799
+ return this.#nowPlayingClient?.bundleIdentifier ?? null;
2636
2800
  }
2637
2801
  get displayName() {
2638
- return this.#airplay.state.nowPlayingClient?.displayName ?? null;
2802
+ return this.#nowPlayingClient?.displayName ?? null;
2639
2803
  }
2640
2804
  get isConnected() {
2641
2805
  return this.#airplay.isConnected && this.#companionLink.isConnected;
2642
2806
  }
2643
2807
  get isPlaying() {
2644
- return this.playbackState === AirPlay.Proto.PlaybackState_Enum.Playing;
2808
+ return this.#nowPlayingClient?.isPlaying ?? false;
2809
+ }
2810
+ get title() {
2811
+ return this.#nowPlayingClient?.title ?? "";
2812
+ }
2813
+ get artist() {
2814
+ return this.#nowPlayingClient?.artist ?? "";
2815
+ }
2816
+ get album() {
2817
+ return this.#nowPlayingClient?.album ?? "";
2818
+ }
2819
+ get duration() {
2820
+ return this.#nowPlayingClient?.duration ?? 0;
2821
+ }
2822
+ get elapsedTime() {
2823
+ return this.#nowPlayingClient?.elapsedTime ?? 0;
2645
2824
  }
2646
2825
  get playbackQueue() {
2647
- return this.#airplay.state.nowPlayingClient?.playbackQueue ?? null;
2826
+ return this.#nowPlayingClient?.playbackQueue ?? null;
2648
2827
  }
2649
2828
  get playbackState() {
2650
- return this.#airplay.state.nowPlayingClient?.playbackState ?? AirPlay.Proto.PlaybackState_Enum.Unknown;
2829
+ return this.#nowPlayingClient?.playbackState ?? AirPlay.Proto.PlaybackState_Enum.Unknown;
2651
2830
  }
2652
2831
  get playbackStateTimestamp() {
2653
- return this.#airplay.state.nowPlayingClient?.playbackStateTimestamp ?? -1;
2832
+ return this.#nowPlayingClient?.playbackStateTimestamp ?? -1;
2833
+ }
2834
+ get volume() {
2835
+ return this.#airplay.state.volume ?? 0;
2836
+ }
2837
+ get #nowPlayingClient() {
2838
+ return this.#airplay.state.nowPlayingClient;
2654
2839
  }
2655
2840
  #airplay;
2656
2841
  #companionLink;
@@ -2663,10 +2848,11 @@ var apple_tv_default = class extends EventEmitter {
2663
2848
  this.#airplay.on("disconnected", (unexpected) => this.#onDisconnected(unexpected));
2664
2849
  this.#companionLink.on("connected", () => this.#onConnected());
2665
2850
  this.#companionLink.on("disconnected", (unexpected) => this.#onDisconnected(unexpected));
2851
+ this.#companionLink.on("power", (state) => this.emit("power", state));
2666
2852
  }
2667
- async connect(credentials) {
2668
- await this.#airplay.setCredentials(credentials);
2669
- await this.#companionLink.setCredentials(credentials);
2853
+ async connect(airplayCredentials, companionLinkCredentials) {
2854
+ this.#airplay.setCredentials(airplayCredentials);
2855
+ await this.#companionLink.setCredentials(companionLinkCredentials ?? airplayCredentials);
2670
2856
  await this.#airplay.connect();
2671
2857
  await this.#companionLink.connect();
2672
2858
  this.#disconnect = false;
@@ -2708,6 +2894,21 @@ var apple_tv_default = class extends EventEmitter {
2708
2894
  async volumeUp() {
2709
2895
  await this.#airplay.remote.volumeUp();
2710
2896
  }
2897
+ async getAttentionState() {
2898
+ return await this.#companionLink.getAttentionState();
2899
+ }
2900
+ async getLaunchableApps() {
2901
+ return await this.#companionLink.getLaunchableApps();
2902
+ }
2903
+ async getUserAccounts() {
2904
+ return await this.#companionLink.getUserAccounts();
2905
+ }
2906
+ async launchApp(bundleId) {
2907
+ await this.#companionLink.launchApp(bundleId);
2908
+ }
2909
+ async switchUserAccount(accountId) {
2910
+ await this.#companionLink.switchUserAccount(accountId);
2911
+ }
2711
2912
  async getCommandInfo(command) {
2712
2913
  const client = this.#airplay.state.nowPlayingClient;
2713
2914
  if (!client) return null;
@@ -2736,30 +2937,57 @@ var homepod_base_default = class extends EventEmitter {
2736
2937
  get airplay() {
2737
2938
  return this.#airplay;
2738
2939
  }
2940
+ get remote() {
2941
+ return this.#airplay.remote;
2942
+ }
2943
+ get state() {
2944
+ return this.#airplay.state;
2945
+ }
2946
+ get volumeControl() {
2947
+ return this.#airplay.volume;
2948
+ }
2739
2949
  get bundleIdentifier() {
2740
- return this.#airplay.state.nowPlayingClient?.bundleIdentifier ?? null;
2950
+ return this.#nowPlayingClient?.bundleIdentifier ?? null;
2741
2951
  }
2742
2952
  get displayName() {
2743
- return this.#airplay.state.nowPlayingClient?.displayName ?? null;
2953
+ return this.#nowPlayingClient?.displayName ?? null;
2744
2954
  }
2745
2955
  get isConnected() {
2746
2956
  return this.#airplay.isConnected;
2747
2957
  }
2748
2958
  get isPlaying() {
2749
- return this.playbackState === AirPlay.Proto.PlaybackState_Enum.Playing;
2959
+ return this.#nowPlayingClient?.isPlaying ?? false;
2960
+ }
2961
+ get title() {
2962
+ return this.#nowPlayingClient?.title ?? "";
2963
+ }
2964
+ get artist() {
2965
+ return this.#nowPlayingClient?.artist ?? "";
2966
+ }
2967
+ get album() {
2968
+ return this.#nowPlayingClient?.album ?? "";
2969
+ }
2970
+ get duration() {
2971
+ return this.#nowPlayingClient?.duration ?? 0;
2972
+ }
2973
+ get elapsedTime() {
2974
+ return this.#nowPlayingClient?.elapsedTime ?? 0;
2750
2975
  }
2751
2976
  get playbackQueue() {
2752
- return this.#airplay.state.nowPlayingClient?.playbackQueue ?? null;
2977
+ return this.#nowPlayingClient?.playbackQueue ?? null;
2753
2978
  }
2754
2979
  get playbackState() {
2755
- return this.#airplay.state.nowPlayingClient?.playbackState ?? AirPlay.Proto.PlaybackState_Enum.Unknown;
2980
+ return this.#nowPlayingClient?.playbackState ?? AirPlay.Proto.PlaybackState_Enum.Unknown;
2756
2981
  }
2757
2982
  get playbackStateTimestamp() {
2758
- return this.#airplay.state.nowPlayingClient?.playbackStateTimestamp ?? -1;
2983
+ return this.#nowPlayingClient?.playbackStateTimestamp ?? -1;
2759
2984
  }
2760
2985
  get volume() {
2761
2986
  return this.#airplay.state.volume ?? 0;
2762
2987
  }
2988
+ get #nowPlayingClient() {
2989
+ return this.#airplay.state.nowPlayingClient;
2990
+ }
2763
2991
  #airplay;
2764
2992
  #disconnect = false;
2765
2993
  constructor(discoveryResult) {
@@ -2793,6 +3021,9 @@ var homepod_base_default = class extends EventEmitter {
2793
3021
  async previous() {
2794
3022
  await this.#airplay.sendCommand(AirPlay.Proto.Command.PreviousInContext);
2795
3023
  }
3024
+ async streamAudio(source) {
3025
+ await this.#airplay.streamAudio(source);
3026
+ }
2796
3027
  async getCommandInfo(command) {
2797
3028
  const client = this.#airplay.state.nowPlayingClient;
2798
3029
  if (!client) return null;