@rntp/player 5.1.0 → 5.1.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.
@@ -48,10 +48,6 @@ class TrackPlayerModule internal constructor(private val context: ReactApplicati
48
48
  private val controller = MainThreadMediaController()
49
49
  private var lastStreamMetadata: MetadataReceivedEvent? = null
50
50
  private var lastMediaMetadata: MediaMetadataChangedEvent? = null
51
- // Cached PlayerConfig.autoUpdateMetadataFromStream — refreshed in setupPlayer.
52
- // When true, ICY/ID3 updates rewrite the queued MediaItem so Now Playing /
53
- // getActiveMediaItem follow the live title even without JS. When false, we
54
- // only emit MetadataReceived and let the app mutate the queue itself.
55
51
  @Volatile private var autoUpdateMetadataFromStream: Boolean = true
56
52
 
57
53
  // endregion
@@ -671,10 +667,6 @@ class TrackPlayerModule internal constructor(private val context: ReactApplicati
671
667
  context.emitEvent(PlaybackStateChangedEvent(state))
672
668
  }
673
669
 
674
- // Effective MediaItem metadata changed (queue transitioned, an
675
- // updateMetadata call landed, or the auto-update path rewrote the active
676
- // item). This is what backs `getActiveMediaItem()` and the system Now
677
- // Playing info, so this is the surface most apps want to observe.
678
670
  override fun onMediaMetadataChanged(mediaMetadata: MediaMetadata) {
679
671
  val event = MediaMetadataChangedEvent(
680
672
  title = mediaMetadata.title?.toString(),
@@ -690,18 +682,6 @@ class TrackPlayerModule internal constructor(private val context: ReactApplicati
690
682
  context.emitEvent(event)
691
683
  }
692
684
 
693
- // Raw stream-derived metadata (ICY blocks, ID3 frames, ...). Always emit
694
- // the pre-merge view so consumers that need stream-truth (e.g. analytics
695
- // or sanitization pipelines) see every frame.
696
- //
697
- // When `autoUpdateMetadataFromStream` is enabled (default), additionally
698
- // rewrite the active MediaItem so the merged effective view picks up the
699
- // change. That replaceMediaItem call triggers `onMediaMetadataChanged`,
700
- // which then emits `MediaMetadataChanged` with the merged result —
701
- // preserving any user-supplied fields (genre, album, etc.) the stream
702
- // didn't include. The two events are intentionally separate: one for
703
- // "what came in" (synchronous), one for "what the active item is now"
704
- // (after the binder roundtrip lands).
705
685
  override fun onMetadata(metadata: Metadata) {
706
686
  val event = StreamMetadataExtractor.extract(metadata) ?: return
707
687
  if (event != lastStreamMetadata) {
@@ -85,15 +85,7 @@ data class MetadataReceivedEvent(
85
85
  }
86
86
  }
87
87
 
88
- /**
89
- * Carries the *effective* metadata of the currently active MediaItem after
90
- * any merge between stream-derived metadata and user-supplied fields. Fires
91
- * on track transitions, explicit updateMetadata calls, and (when
92
- * autoUpdateMetadataFromStream is enabled) after the native side rewrites
93
- * the active item in response to stream metadata.
94
- *
95
- * Mirrors Media3's Player.Listener.onMediaMetadataChanged callback.
96
- */
88
+ /** Effective active-item metadata (Media3 [Player.Listener.onMediaMetadataChanged]). */
97
89
  data class MediaMetadataChangedEvent(
98
90
  val title: String?,
99
91
  val artist: String?,
@@ -9,32 +9,9 @@ import android.net.Uri
9
9
  import androidx.media3.common.MediaMetadata
10
10
  import androidx.media3.common.Player
11
11
 
12
- /**
13
- * Pure helper that writes a stream-derived [MetadataReceivedEvent] back into
14
- * the [Player]'s current MediaItem.
15
- *
16
- * Used by [com.doublesymmetry.trackplayer.TrackPlayerModule.onMetadata] when
17
- * `PlayerConfig.autoUpdateMetadataFromStream` is enabled (the default), so
18
- * that:
19
- * - `getActiveMediaItem()` reflects the live ICY title.
20
- * - `MPNowPlayingInfoCenter`'s Android analogue (Media3 session → system
21
- * notification, Bluetooth, Android Auto) follows along.
22
- *
23
- * Lives outside [com.doublesymmetry.trackplayer.TrackPlayerModule] so it can
24
- * be unit-tested against a real [androidx.media3.exoplayer.ExoPlayer] under
25
- * Robolectric without spinning up a [androidx.media3.session.MediaController]
26
- * + service.
27
- */
12
+ /** Merges stream metadata into the current [Player] media item (see [PlayerConfig.autoUpdateMetadataFromStream]). */
28
13
  internal object MetadataApplier {
29
14
 
30
- /**
31
- * Merges [event]'s non-null fields onto the current item's [MediaMetadata]
32
- * and dispatches a [Player.replaceMediaItem]. The new MediaItem reuses the
33
- * existing URI so Media3 keeps playback uninterrupted.
34
- *
35
- * @return `true` if the mutation was dispatched, `false` if there is no
36
- * current item to update.
37
- */
38
15
  fun applyToCurrentMediaItem(player: Player, event: MetadataReceivedEvent): Boolean {
39
16
  val idx = player.currentMediaItemIndex
40
17
  if (idx < 0 || idx >= player.mediaItemCount) return false
@@ -20,13 +20,6 @@ import org.robolectric.RobolectricTestRunner
20
20
  import org.robolectric.RuntimeEnvironment
21
21
  import org.robolectric.annotation.Config
22
22
 
23
- /**
24
- * Exercises [MetadataApplier.applyToCurrentMediaItem] against a real
25
- * [ExoPlayer] under Robolectric. We use [ExoPlayer] directly (rather than the
26
- * [androidx.media3.session.MediaController] used at runtime) because both
27
- * implement the [androidx.media3.common.Player] interface that the applier
28
- * targets — and ExoPlayer is the only one we can stand up without a service.
29
- */
30
23
  @RunWith(RobolectricTestRunner::class)
31
24
  @Config(sdk = [33])
32
25
  class MetadataApplierTest {
@@ -80,9 +73,6 @@ class MetadataApplierTest {
80
73
 
81
74
  @Test
82
75
  fun `preserves existing user-supplied fields the event does not touch`() {
83
- // Mirrors the real-world case: an app queues a radio station with a fixed
84
- // `genre` / `albumTitle` and the stream subsequently sends new ICY titles
85
- // without artwork/genre. Those originals must survive the rewrite.
86
76
  player.setMediaItems(
87
77
  listOf(
88
78
  buildItem(
@@ -107,8 +97,6 @@ class MetadataApplierTest {
107
97
 
108
98
  @Test
109
99
  fun `overwrites previous stream-supplied title on next update`() {
110
- // Two consecutive ICY updates: second one fully replaces the first's
111
- // title + artist (same currentIndex, so the rewrite is in place).
112
100
  player.setMediaItems(listOf(buildItem("radio")))
113
101
 
114
102
  MetadataApplier.applyToCurrentMediaItem(
@@ -127,9 +115,6 @@ class MetadataApplierTest {
127
115
 
128
116
  @Test
129
117
  fun `null fields in event do not clobber existing values (sticky semantics)`() {
130
- // Match iOS withMetadata behavior: nil from stream means "leave alone",
131
- // not "clear". Useful when a station sends artist on one update and only
132
- // title on the next.
133
118
  player.setMediaItems(listOf(buildItem(id = "radio", artist = "Existing Artist")))
134
119
  val event = MetadataReceivedEvent(title = "Just a Title", artist = null)
135
120
 
@@ -212,7 +197,6 @@ class MetadataApplierTest {
212
197
  buildItem("track-3", title = "Title 3"),
213
198
  )
214
199
  )
215
- // currentIndex defaults to 0 — that's the one we expect to mutate.
216
200
  val event = MetadataReceivedEvent(title = "Live Title 1", artist = null)
217
201
 
218
202
  MetadataApplier.applyToCurrentMediaItem(player, event)
@@ -226,9 +210,6 @@ class MetadataApplierTest {
226
210
 
227
211
  @Test
228
212
  fun `event with all null fields leaves item unchanged but still reports applied`() {
229
- // The applier doesn't gate on empty events — that's the caller's job
230
- // (StreamMetadataExtractor.extract already returns null for empty
231
- // metadata blocks, so this code path is mostly defensive).
232
213
  player.setMediaItems(listOf(buildItem(id = "radio", title = "Original Title")))
233
214
  val event = MetadataReceivedEvent(
234
215
  title = null, artist = null, albumTitle = null, artworkUri = null, genre = null,
@@ -20,15 +20,7 @@ class TrackPlayer: RCTEventEmitter {
20
20
  private var progressSyncTimer: Timer?
21
21
  private var progressSyncIntervalSeconds: Double = 0
22
22
  private var progressSyncHttpUrl: String?
23
- // When true (default), incoming stream metadata (ICY/ID3) is written back
24
- // into the queued MediaItem so getActiveTrack() and MPNowPlayingInfoCenter
25
- // reflect the live title. When false, only the MetadataReceived event fires
26
- // and apps update the queue themselves via TrackPlayer.updateMetadata(…).
27
23
  private var autoUpdateMetadataFromStream: Bool = true
28
- // Tracks the last-emitted effective metadata so we don't double-emit
29
- // MediaMetadataChanged when the same merged view lands twice (e.g. an
30
- // ICY frame with no actual changes, or a manual updateMetadata that
31
- // re-applies identical fields).
32
24
  private var lastEmittedMediaMetadata: MediaMetadataChangedEvent?
33
25
  private var progressSyncHttpHeaders: [String: String]?
34
26
 
@@ -323,9 +315,6 @@ class TrackPlayer: RCTEventEmitter {
323
315
  )
324
316
 
325
317
  player.updateMetadata(at: idx, with: updated)
326
- // Only emit MediaMetadataChanged for the *active* item — updating a
327
- // non-current queue entry's metadata changes its stored fields but
328
- // doesn't affect what `getActiveMediaItem` returns.
329
318
  if idx == player.currentIndex {
330
319
  emitMediaMetadataChangedIfNeeded(for: updated)
331
320
  }
@@ -557,17 +546,12 @@ class TrackPlayer: RCTEventEmitter {
557
546
  let mediaItem = item as? MediaItem
558
547
  let dict = mediaItem?.toDictionary()
559
548
  BrowseTreeStore.shared.updateNowPlaying(mediaId: mediaItem?.mediaId)
560
- // Reset dedup state on transitions so the first emit for the new item
561
- // is never suppressed by a coincidental match against the previous one.
562
549
  lastEmittedMediaMetadata = nil
563
550
  emitEvent(event: MediaItemTransitionEvent(item: dict, index: index))
564
551
  emitMediaMetadataChangedIfNeeded(for: mediaItem)
565
552
  }
566
553
 
567
554
  func handleMetadataReceived(_ metadata: StreamMetadata) {
568
- // Always emit the raw stream-truth event first (mirrors Android: synchronous,
569
- // pre-merge). Consumers that care about the *effective* view get the
570
- // separate MediaMetadataChanged event below.
571
555
  emitEvent(event: MetadataReceivedEvent(metadata: metadata))
572
556
 
573
557
  guard autoUpdateMetadataFromStream else { return }
@@ -584,12 +568,7 @@ class TrackPlayer: RCTEventEmitter {
584
568
  emitMediaMetadataChangedIfNeeded(for: updated)
585
569
  }
586
570
 
587
- /// Build a MediaMetadataChanged event from a merged MediaItem and emit it,
588
- /// skipping duplicate emits when the effective view is unchanged.
589
- ///
590
- /// Note: iOS's MediaItem schema does not include `genre`, so that field
591
- /// is always nil in events from this platform. Android emits it whenever
592
- /// present in either the queued item or the stream.
571
+ /// iOS MediaItem has no `genre`; Android may include it in this event.
593
572
  private func emitMediaMetadataChangedIfNeeded(for item: MediaItem?) {
594
573
  guard let item else { return }
595
574
  let event = MediaMetadataChangedEvent(
@@ -9,13 +9,7 @@ import XCTest
9
9
  @testable import PlayerCore
10
10
 
11
11
  final class AVPlayerEngineIntegrationTests: XCTestCase {
12
- // Generous timeout for tests that play AAC to completion through the cache
13
- // proxy. The fast path is sub-second locally, but GitHub-hosted runners
14
- // routinely starve the simulator audio pipeline ("HALC IOWorkLoop: skipping
15
- // cycle due to overload") and the previous 10s budget was tight enough that
16
- // testCachedPlaybackCompletesWithoutContentLength flaked on CI. 30s is well
17
- // beyond observed worst-case on macos-26 while staying short enough to fail
18
- // fast for genuine regressions.
12
+ /// Cache-proxy playback tests need a longer wait on slow CI simulators.
19
13
  private let playbackTimeout: TimeInterval = 30.0
20
14
 
21
15
  private var engine: AVPlayerEngine!
@@ -14,14 +14,8 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
14
14
  */
15
15
 
16
16
  /**
17
- * Returns the currently active media item, updating on item transitions and
18
- * whenever the active item's effective metadata changes (e.g. ICY tags from
19
- * a live radio stream rewriting title/artist).
20
- *
21
- * Subscribes to {@link Event.MediaMetadataChanged} rather than
22
- * {@link Event.MetadataReceived} so the re-read of {@link getActiveMediaItem}
23
- * happens *after* native has finished merging the new metadata into the
24
- * queued item — no race against the IPC that lands the auto-update.
17
+ * Active media item; refreshes on {@link Event.MediaItemTransition} and
18
+ * {@link Event.MediaMetadataChanged} (after native merges stream metadata).
25
19
  */
26
20
  function useActiveMediaItem() {
27
21
  const [item, setItem] = (0, _react.useState)(() => TrackPlayer.getActiveMediaItem());
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","TrackPlayer","_interopRequireWildcard","_index","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","useActiveMediaItem","item","setItem","useState","getActiveMediaItem","useEffect","transitionSub","addEventListener","Event","MediaItemTransition","event","metadataSub","MediaMetadataChanged","remove"],"sourceRoot":"../../../src","sources":["hooks/useActiveMediaItem.ts"],"mappings":";;;;;;AAKA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,WAAA,GAAAC,uBAAA,CAAAF,OAAA;AACA,IAAAG,MAAA,GAAAH,OAAA;AAAkC,SAAAE,wBAAAE,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAJ,uBAAA,YAAAA,CAAAE,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAPlC;AACA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASkB,kBAAkBA,CAAA,EAAqB;EACrD,MAAM,CAACC,IAAI,EAAEC,OAAO,CAAC,GAAG,IAAAC,eAAQ,EAAmB,MACjDzB,WAAW,CAAC0B,kBAAkB,CAAC,CACjC,CAAC;EAED,IAAAC,gBAAS,EAAC,MAAM;IACd,MAAMC,aAAa,GAAG5B,WAAW,CAAC6B,gBAAgB,CAChDC,YAAK,CAACC,mBAAmB,EACxBC,KAAK,IAAK;MACTR,OAAO,CAACQ,KAAK,CAACT,IAAI,CAAC;IACrB,CACF,CAAC;IACD,MAAMU,WAAW,GAAGjC,WAAW,CAAC6B,gBAAgB,CAC9CC,YAAK,CAACI,oBAAoB,EAC1B,MAAM;MACJV,OAAO,CAACxB,WAAW,CAAC0B,kBAAkB,CAAC,CAAC,CAAC;IAC3C,CACF,CAAC;IACD,OAAO,MAAM;MACXE,aAAa,CAACO,MAAM,CAAC,CAAC;MACtBF,WAAW,CAACE,MAAM,CAAC,CAAC;IACtB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOZ,IAAI;AACb","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","TrackPlayer","_interopRequireWildcard","_index","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","useActiveMediaItem","item","setItem","useState","getActiveMediaItem","useEffect","transitionSub","addEventListener","Event","MediaItemTransition","event","metadataSub","MediaMetadataChanged","remove"],"sourceRoot":"../../../src","sources":["hooks/useActiveMediaItem.ts"],"mappings":";;;;;;AAKA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,WAAA,GAAAC,uBAAA,CAAAF,OAAA;AACA,IAAAG,MAAA,GAAAH,OAAA;AAAkC,SAAAE,wBAAAE,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAJ,uBAAA,YAAAA,CAAAE,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AAPlC;AACA;AACA;AACA;;AAOA;AACA;AACA;AACA;AACO,SAASkB,kBAAkBA,CAAA,EAAqB;EACrD,MAAM,CAACC,IAAI,EAAEC,OAAO,CAAC,GAAG,IAAAC,eAAQ,EAAmB,MACjDzB,WAAW,CAAC0B,kBAAkB,CAAC,CACjC,CAAC;EAED,IAAAC,gBAAS,EAAC,MAAM;IACd,MAAMC,aAAa,GAAG5B,WAAW,CAAC6B,gBAAgB,CAChDC,YAAK,CAACC,mBAAmB,EACxBC,KAAK,IAAK;MACTR,OAAO,CAACQ,KAAK,CAACT,IAAI,CAAC;IACrB,CACF,CAAC;IACD,MAAMU,WAAW,GAAGjC,WAAW,CAAC6B,gBAAgB,CAC9CC,YAAK,CAACI,oBAAoB,EAC1B,MAAM;MACJV,OAAO,CAACxB,WAAW,CAAC0B,kBAAkB,CAAC,CAAC,CAAC;IAC3C,CACF,CAAC;IACD,OAAO,MAAM;MACXE,aAAa,CAACO,MAAM,CAAC,CAAC;MACtBF,WAAW,CAACE,MAAM,CAAC,CAAC;IACtB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOZ,IAAI;AACb","ignoreList":[]}
@@ -9,14 +9,8 @@ import { useEffect, useState } from 'react';
9
9
  import * as TrackPlayer from "../audio.js";
10
10
  import { Event } from "../events/index.js";
11
11
  /**
12
- * Returns the currently active media item, updating on item transitions and
13
- * whenever the active item's effective metadata changes (e.g. ICY tags from
14
- * a live radio stream rewriting title/artist).
15
- *
16
- * Subscribes to {@link Event.MediaMetadataChanged} rather than
17
- * {@link Event.MetadataReceived} so the re-read of {@link getActiveMediaItem}
18
- * happens *after* native has finished merging the new metadata into the
19
- * queued item — no race against the IPC that lands the auto-update.
12
+ * Active media item; refreshes on {@link Event.MediaItemTransition} and
13
+ * {@link Event.MediaMetadataChanged} (after native merges stream metadata).
20
14
  */
21
15
  export function useActiveMediaItem() {
22
16
  const [item, setItem] = useState(() => TrackPlayer.getActiveMediaItem());
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useState","TrackPlayer","Event","useActiveMediaItem","item","setItem","getActiveMediaItem","transitionSub","addEventListener","MediaItemTransition","event","metadataSub","MediaMetadataChanged","remove"],"sourceRoot":"../../../src","sources":["hooks/useActiveMediaItem.ts"],"mappings":";;AAAA;AACA;AACA;AACA;;AAEA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAC3C,OAAO,KAAKC,WAAW,MAAM,aAAU;AACvC,SAASC,KAAK,QAAQ,oBAAW;AAGjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,kBAAkBA,CAAA,EAAqB;EACrD,MAAM,CAACC,IAAI,EAAEC,OAAO,CAAC,GAAGL,QAAQ,CAAmB,MACjDC,WAAW,CAACK,kBAAkB,CAAC,CACjC,CAAC;EAEDP,SAAS,CAAC,MAAM;IACd,MAAMQ,aAAa,GAAGN,WAAW,CAACO,gBAAgB,CAChDN,KAAK,CAACO,mBAAmB,EACxBC,KAAK,IAAK;MACTL,OAAO,CAACK,KAAK,CAACN,IAAI,CAAC;IACrB,CACF,CAAC;IACD,MAAMO,WAAW,GAAGV,WAAW,CAACO,gBAAgB,CAC9CN,KAAK,CAACU,oBAAoB,EAC1B,MAAM;MACJP,OAAO,CAACJ,WAAW,CAACK,kBAAkB,CAAC,CAAC,CAAC;IAC3C,CACF,CAAC;IACD,OAAO,MAAM;MACXC,aAAa,CAACM,MAAM,CAAC,CAAC;MACtBF,WAAW,CAACE,MAAM,CAAC,CAAC;IACtB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOT,IAAI;AACb","ignoreList":[]}
1
+ {"version":3,"names":["useEffect","useState","TrackPlayer","Event","useActiveMediaItem","item","setItem","getActiveMediaItem","transitionSub","addEventListener","MediaItemTransition","event","metadataSub","MediaMetadataChanged","remove"],"sourceRoot":"../../../src","sources":["hooks/useActiveMediaItem.ts"],"mappings":";;AAAA;AACA;AACA;AACA;;AAEA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAC3C,OAAO,KAAKC,WAAW,MAAM,aAAU;AACvC,SAASC,KAAK,QAAQ,oBAAW;AAGjC;AACA;AACA;AACA;AACA,OAAO,SAASC,kBAAkBA,CAAA,EAAqB;EACrD,MAAM,CAACC,IAAI,EAAEC,OAAO,CAAC,GAAGL,QAAQ,CAAmB,MACjDC,WAAW,CAACK,kBAAkB,CAAC,CACjC,CAAC;EAEDP,SAAS,CAAC,MAAM;IACd,MAAMQ,aAAa,GAAGN,WAAW,CAACO,gBAAgB,CAChDN,KAAK,CAACO,mBAAmB,EACxBC,KAAK,IAAK;MACTL,OAAO,CAACK,KAAK,CAACN,IAAI,CAAC;IACrB,CACF,CAAC;IACD,MAAMO,WAAW,GAAGV,WAAW,CAACO,gBAAgB,CAC9CN,KAAK,CAACU,oBAAoB,EAC1B,MAAM;MACJP,OAAO,CAACJ,WAAW,CAACK,kBAAkB,CAAC,CAAC,CAAC;IAC3C,CACF,CAAC;IACD,OAAO,MAAM;MACXC,aAAa,CAACM,MAAM,CAAC,CAAC;MACtBF,WAAW,CAACE,MAAM,CAAC,CAAC;IACtB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,OAAOT,IAAI;AACb","ignoreList":[]}
@@ -3,21 +3,8 @@
3
3
  * Commercial use requires a license. See https://rntp.dev/pricing
4
4
  */
5
5
  /**
6
- * Fired when the *effective* metadata of the currently active MediaItem
7
- * changes — i.e. the view that backs {@link getActiveMediaItem} and the system
8
- * Now Playing info (lock screen, Bluetooth, Android Auto / CarPlay).
9
- *
10
- * Sources include:
11
- * - Track transitions (the new active item's metadata)
12
- * - Explicit {@link updateMetadata} calls
13
- * - The native auto-update path that rewrites the active MediaItem when stream
14
- * metadata (ICY / ID3) arrives — only fires when
15
- * {@link PlayerConfig.autoUpdateMetadataFromStream} is enabled (the default).
16
- *
17
- * Contrast with {@link MetadataReceivedEvent}, which fires for every metadata
18
- * frame the stream pushes (raw, pre-merge) regardless of whether the queue is
19
- * updated. Many apps only need this event; subscribe to MetadataReceived only
20
- * when you specifically need stream-truth (e.g. scrobbling).
6
+ * Effective metadata for the active item ({@link getActiveMediaItem}, Now Playing).
7
+ * Use {@link MetadataReceivedEvent} for raw per-frame stream metadata instead.
21
8
  *
22
9
  * @since 5.1.0
23
10
  */
@@ -1 +1 @@
1
- {"version":3,"file":"MediaMetadataChanged.d.ts","sourceRoot":"","sources":["../../../../src/events/MediaMetadataChanged.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
1
+ {"version":3,"file":"MediaMetadataChanged.d.ts","sourceRoot":"","sources":["../../../../src/events/MediaMetadataChanged.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -4,14 +4,8 @@
4
4
  */
5
5
  import type { MediaItem } from '../interfaces';
6
6
  /**
7
- * Returns the currently active media item, updating on item transitions and
8
- * whenever the active item's effective metadata changes (e.g. ICY tags from
9
- * a live radio stream rewriting title/artist).
10
- *
11
- * Subscribes to {@link Event.MediaMetadataChanged} rather than
12
- * {@link Event.MetadataReceived} so the re-read of {@link getActiveMediaItem}
13
- * happens *after* native has finished merging the new metadata into the
14
- * queued item — no race against the IPC that lands the auto-update.
7
+ * Active media item; refreshes on {@link Event.MediaItemTransition} and
8
+ * {@link Event.MediaMetadataChanged} (after native merges stream metadata).
15
9
  */
16
10
  export declare function useActiveMediaItem(): MediaItem | null;
17
11
  //# sourceMappingURL=useActiveMediaItem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useActiveMediaItem.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useActiveMediaItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,GAAG,IAAI,CAyBrD"}
1
+ {"version":3,"file":"useActiveMediaItem.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useActiveMediaItem.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,GAAG,IAAI,CAyBrD"}
@@ -111,15 +111,8 @@ export interface PlayerConfig {
111
111
  */
112
112
  handleAudioBecomingNoisy?: boolean;
113
113
  /**
114
- * When `true`, stream-derived metadata (ICY/ID3) automatically updates the
115
- * MediaItem in the queue, keeping `getActiveMediaItem()` and the system Now
116
- * Playing info (lock screen, notification, CarPlay/Android Auto) in sync with
117
- * the live title — without requiring app code to be running.
118
- *
119
- * When `false`, only the {@link Event.MetadataReceived} event is emitted; the
120
- * queue MediaItem is left untouched. Use this to filter/sanitize stream
121
- * metadata yourself and call {@link updateMetadata} from a listener or
122
- * background event handler.
114
+ * When `true` (default), ICY/ID3 metadata updates the queued MediaItem and Now Playing.
115
+ * When `false`, only {@link Event.MetadataReceived} is emitted; call {@link updateMetadata} yourself.
123
116
  *
124
117
  * @default true
125
118
  * @since 5.1.0
@@ -1 +1 @@
1
- {"version":3,"file":"PlayerConfig.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/PlayerConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B;AAED,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAE1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,aAAa,CAAC;AAEvD,4CAA4C;AAC5C,eAAO,MAAM,6BAA6B,EAAE,mBAG3C,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,qBAAqB;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,YAAY,CAAC,EAAE;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,uEAAuE;AACvE,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAC1C,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,OAAO,GAAG,cAAc,CAAC,CACzD,GAAG;IACF,OAAO,EAAE,mBAAmB,CAAC;CAM9B,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC;;OAEG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;CAC1D;AAED,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACjC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;;;;;;;;;OAaG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACxC"}
1
+ {"version":3,"file":"PlayerConfig.d.ts","sourceRoot":"","sources":["../../../../src/interfaces/PlayerConfig.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC;CAC5B;AAED,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAE1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,aAAa,CAAC;AAEvD,4CAA4C;AAC5C,eAAO,MAAM,6BAA6B,EAAE,mBAG3C,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IACvC,qBAAqB;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,YAAY,CAAC,EAAE;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,uEAAuE;AACvE,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAC1C,IAAI,CAAC,YAAY,EAAE,SAAS,GAAG,OAAO,GAAG,cAAc,CAAC,CACzD,GAAG;IACF,OAAO,EAAE,mBAAmB,CAAC;CAM9B,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC;;OAEG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC;CAC1D;AAED,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACjC;;;OAGG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC;;;;;;OAMG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACxC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rntp/player",
3
- "version": "5.1.0",
3
+ "version": "5.1.2",
4
4
  "description": "The premium audio player for React Native",
5
5
  "source": "./src/index.tsx",
6
6
  "react-native": "./src/index.tsx",
@@ -14,7 +14,8 @@
14
14
  "types": "./lib/typescript/src/index.d.ts",
15
15
  "import": "./lib/module/index.js",
16
16
  "require": "./lib/commonjs/index.js"
17
- }
17
+ },
18
+ "./package.json": "./package.json"
18
19
  },
19
20
  "files": [
20
21
  "src",
@@ -4,21 +4,8 @@
4
4
  */
5
5
 
6
6
  /**
7
- * Fired when the *effective* metadata of the currently active MediaItem
8
- * changes — i.e. the view that backs {@link getActiveMediaItem} and the system
9
- * Now Playing info (lock screen, Bluetooth, Android Auto / CarPlay).
10
- *
11
- * Sources include:
12
- * - Track transitions (the new active item's metadata)
13
- * - Explicit {@link updateMetadata} calls
14
- * - The native auto-update path that rewrites the active MediaItem when stream
15
- * metadata (ICY / ID3) arrives — only fires when
16
- * {@link PlayerConfig.autoUpdateMetadataFromStream} is enabled (the default).
17
- *
18
- * Contrast with {@link MetadataReceivedEvent}, which fires for every metadata
19
- * frame the stream pushes (raw, pre-merge) regardless of whether the queue is
20
- * updated. Many apps only need this event; subscribe to MetadataReceived only
21
- * when you specifically need stream-truth (e.g. scrobbling).
7
+ * Effective metadata for the active item ({@link getActiveMediaItem}, Now Playing).
8
+ * Use {@link MetadataReceivedEvent} for raw per-frame stream metadata instead.
22
9
  *
23
10
  * @since 5.1.0
24
11
  */
@@ -9,14 +9,8 @@ import { Event } from '../events';
9
9
  import type { MediaItem } from '../interfaces';
10
10
 
11
11
  /**
12
- * Returns the currently active media item, updating on item transitions and
13
- * whenever the active item's effective metadata changes (e.g. ICY tags from
14
- * a live radio stream rewriting title/artist).
15
- *
16
- * Subscribes to {@link Event.MediaMetadataChanged} rather than
17
- * {@link Event.MetadataReceived} so the re-read of {@link getActiveMediaItem}
18
- * happens *after* native has finished merging the new metadata into the
19
- * queued item — no race against the IPC that lands the auto-update.
12
+ * Active media item; refreshes on {@link Event.MediaItemTransition} and
13
+ * {@link Event.MediaMetadataChanged} (after native merges stream metadata).
20
14
  */
21
15
  export function useActiveMediaItem(): MediaItem | null {
22
16
  const [item, setItem] = useState<MediaItem | null>(() =>
@@ -136,15 +136,8 @@ export interface PlayerConfig {
136
136
  */
137
137
  handleAudioBecomingNoisy?: boolean;
138
138
  /**
139
- * When `true`, stream-derived metadata (ICY/ID3) automatically updates the
140
- * MediaItem in the queue, keeping `getActiveMediaItem()` and the system Now
141
- * Playing info (lock screen, notification, CarPlay/Android Auto) in sync with
142
- * the live title — without requiring app code to be running.
143
- *
144
- * When `false`, only the {@link Event.MetadataReceived} event is emitted; the
145
- * queue MediaItem is left untouched. Use this to filter/sanitize stream
146
- * metadata yourself and call {@link updateMetadata} from a listener or
147
- * background event handler.
139
+ * When `true` (default), ICY/ID3 metadata updates the queued MediaItem and Now Playing.
140
+ * When `false`, only {@link Event.MetadataReceived} is emitted; call {@link updateMetadata} yourself.
148
141
  *
149
142
  * @default true
150
143
  * @since 5.1.0