@basmilius/apple-devices 0.9.7 → 0.9.9

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
@@ -18,6 +18,12 @@ declare class Client {
18
18
  get title(): string;
19
19
  get artist(): string;
20
20
  get album(): string;
21
+ get genre(): string;
22
+ get seriesName(): string;
23
+ get seasonNumber(): number;
24
+ get episodeNumber(): number;
25
+ get mediaType(): Proto.ContentItemMetadata_MediaType;
26
+ get contentIdentifier(): string;
21
27
  get duration(): number;
22
28
  get playbackRate(): number;
23
29
  get isPlaying(): boolean;
package/dist/index.mjs CHANGED
@@ -1926,6 +1926,13 @@ var merge = createAssigner(function(object, source, srcIndex) {
1926
1926
 
1927
1927
  //#endregion
1928
1928
  //#region src/airplay/client.ts
1929
+ const COCOA_EPOCH_OFFSET = 978307200;
1930
+ const extrapolateElapsed = (elapsed, cocoaTimestamp, rate, isPlaying) => {
1931
+ if (!rate || !isPlaying) return elapsed;
1932
+ const timestampUnix = cocoaTimestamp + COCOA_EPOCH_OFFSET;
1933
+ const delta = (Date.now() / 1e3 - timestampUnix) * rate;
1934
+ return Math.max(0, elapsed + delta);
1935
+ };
1929
1936
  var Client = class {
1930
1937
  get bundleIdentifier() {
1931
1938
  return this.#bundleIdentifier;
@@ -1957,6 +1964,24 @@ var Client = class {
1957
1964
  get album() {
1958
1965
  return this.#nowPlayingInfo?.album || this.currentItemMetadata?.albumName || "";
1959
1966
  }
1967
+ get genre() {
1968
+ return this.currentItemMetadata?.genre || "";
1969
+ }
1970
+ get seriesName() {
1971
+ return this.currentItemMetadata?.seriesName || "";
1972
+ }
1973
+ get seasonNumber() {
1974
+ return this.currentItemMetadata?.seasonNumber || 0;
1975
+ }
1976
+ get episodeNumber() {
1977
+ return this.currentItemMetadata?.episodeNumber || 0;
1978
+ }
1979
+ get mediaType() {
1980
+ return this.currentItemMetadata?.mediaType ?? Proto.ContentItemMetadata_MediaType.UnknownMediaType;
1981
+ }
1982
+ get contentIdentifier() {
1983
+ return this.currentItemMetadata?.contentIdentifier || "";
1984
+ }
1960
1985
  get duration() {
1961
1986
  return this.#nowPlayingInfo?.duration || this.currentItemMetadata?.duration || 0;
1962
1987
  }
@@ -1973,15 +1998,17 @@ var Client = class {
1973
1998
  return this.#supportedCommands.find((c) => c.command === Proto.Command.ChangeRepeatMode)?.repeatMode ?? Proto.RepeatMode_Enum.Unknown;
1974
1999
  }
1975
2000
  get elapsedTime() {
1976
- const meta = this.currentItemMetadata;
1977
2001
  const npi = this.#nowPlayingInfo;
1978
- const elapsedTimestamp = meta?.elapsedTimeTimestamp || 0;
1979
- const elapsed = meta?.elapsedTime || npi?.elapsedTime || 0;
1980
- if (!elapsedTimestamp) return elapsed;
1981
- if ((meta?.playbackRate ?? npi?.playbackRate ?? 0) === 0 || !this.isPlaying) return elapsed;
1982
- const timestampUnix = elapsedTimestamp + 978307200;
1983
- const diff = Date.now() / 1e3 - timestampUnix;
1984
- return Math.max(0, elapsed + diff);
2002
+ const meta = this.currentItemMetadata;
2003
+ const npiValid = npi?.elapsedTime != null && npi.timestamp;
2004
+ const metaValid = meta?.elapsedTime != null && meta.elapsedTimeTimestamp;
2005
+ if (npiValid && metaValid) {
2006
+ if (meta.elapsedTimeTimestamp > npi.timestamp) return extrapolateElapsed(meta.elapsedTime, meta.elapsedTimeTimestamp, meta.playbackRate ?? npi.playbackRate, this.isPlaying);
2007
+ return extrapolateElapsed(npi.elapsedTime, npi.timestamp, npi.playbackRate, this.isPlaying);
2008
+ }
2009
+ if (npiValid) return extrapolateElapsed(npi.elapsedTime, npi.timestamp, npi.playbackRate, this.isPlaying);
2010
+ if (metaValid) return extrapolateElapsed(meta.elapsedTime, meta.elapsedTimeTimestamp, meta.playbackRate, this.isPlaying);
2011
+ return npi?.elapsedTime || meta?.elapsedTime || 0;
1985
2012
  }
1986
2013
  get currentItem() {
1987
2014
  if (!this.#playbackQueue || this.#playbackQueue.contentItems.length === 0) return null;
@@ -2606,22 +2633,10 @@ var device_default = class extends EventEmitter {
2606
2633
  this.#protocol.eventStream.on("timeout", this.#onTimeout.bind(this));
2607
2634
  this.#feedbackInterval = setInterval(async () => await this.#feedback(), FEEDBACK_INTERVAL);
2608
2635
  try {
2609
- await this.#protocol.dataStream.exchange(DataStreamMessage.setConnectionState(Proto.SetConnectionStateMessage_ConnectionState.Connecting));
2610
- await waitFor(500);
2611
- const gid = this.#discoveryResult.txt.gid;
2612
- if (gid) await this.#protocol.dataStream.exchange(DataStreamMessage.configureConnection(gid));
2613
- if (!await Promise.race([new Promise(async (resolve) => {
2614
- this.#protocol.dataStream.once("deviceInfo", async () => {
2615
- await this.#protocol.dataStream.exchange(DataStreamMessage.setConnectionState());
2616
- await this.#protocol.dataStream.exchange(DataStreamMessage.clientUpdatesConfig());
2617
- resolve(true);
2618
- });
2619
- await this.#protocol.dataStream.exchange(DataStreamMessage.deviceInfo(keys.pairingId));
2620
- }), async () => {
2621
- await waitFor(3e3);
2622
- return false;
2623
- }])) this.#onError(/* @__PURE__ */ new Error("Device did not respond in time with its info."));
2624
- else this.#protocol.context.logger.info("Device info received successfully, protocol should be ready.");
2636
+ await this.#protocol.dataStream.exchange(DataStreamMessage.deviceInfo(keys.pairingId));
2637
+ await this.#protocol.dataStream.exchange(DataStreamMessage.setConnectionState());
2638
+ await this.#protocol.dataStream.exchange(DataStreamMessage.clientUpdatesConfig());
2639
+ this.#protocol.context.logger.info("Protocol ready.");
2625
2640
  } catch (err) {
2626
2641
  clearInterval(this.#feedbackInterval);
2627
2642
  this.#feedbackInterval = void 0;
@@ -2754,7 +2769,9 @@ var device_default$1 = class extends EventEmitter {
2754
2769
  await this.#protocol.tvrcSessionStart();
2755
2770
  await this.#protocol.touchStart();
2756
2771
  await this.#protocol.tiStart();
2757
- await this.#protocol.unsubscribe("_iMC");
2772
+ await this.#protocol.subscribe("_iMC", (data) => {
2773
+ this.emit("mediaControl", data);
2774
+ });
2758
2775
  this.#heartbeatInterval = setInterval(async () => await this.#heartbeat(), 15e3);
2759
2776
  await this.#subscribe();
2760
2777
  } catch (err) {
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.7",
4
+ "version": "0.9.9",
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.7",
53
- "@basmilius/apple-common": "0.9.7",
54
- "@basmilius/apple-companion-link": "0.9.7",
55
- "@basmilius/apple-encoding": "0.9.7"
52
+ "@basmilius/apple-airplay": "0.9.9",
53
+ "@basmilius/apple-common": "0.9.9",
54
+ "@basmilius/apple-companion-link": "0.9.9",
55
+ "@basmilius/apple-encoding": "0.9.9"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/bun": "^1.3.9",