react-native-nitro-player 1.5.1-alpha.0 → 1.6.0-alpha.1

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.
Files changed (41) hide show
  1. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +6 -0
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +7 -0
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerListener.kt +32 -0
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerNotify.kt +5 -0
  5. package/ios/HybridTrackPlayer.swift +6 -0
  6. package/ios/core/TrackPlayerCore.swift +13 -0
  7. package/ios/core/TrackPlayerListener.swift +89 -0
  8. package/ios/core/TrackPlayerNotify.swift +4 -0
  9. package/lib/hooks/callbackManager.d.ts +10 -1
  10. package/lib/hooks/callbackManager.js +33 -0
  11. package/lib/hooks/index.d.ts +1 -0
  12. package/lib/hooks/index.js +1 -0
  13. package/lib/hooks/useTimedMetadata.d.ts +16 -0
  14. package/lib/hooks/useTimedMetadata.js +21 -0
  15. package/lib/specs/TrackPlayer.nitro.d.ts +6 -1
  16. package/lib/types/PlayerQueue.d.ts +15 -0
  17. package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +2 -0
  18. package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +79 -0
  19. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +9 -0
  20. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +1 -0
  21. package/nitrogen/generated/android/c++/JTimedMetadata.hpp +74 -0
  22. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_TimedMetadata.kt +80 -0
  23. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +9 -0
  24. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TimedMetadata.kt +50 -0
  25. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +8 -0
  26. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +25 -0
  27. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +3 -0
  28. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +9 -0
  29. package/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift +46 -0
  30. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +1 -0
  31. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +16 -0
  32. package/nitrogen/generated/ios/swift/TimedMetadata.swift +114 -0
  33. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -0
  34. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +4 -0
  35. package/nitrogen/generated/shared/c++/TimedMetadata.hpp +100 -0
  36. package/package.json +1 -1
  37. package/src/hooks/callbackManager.ts +47 -1
  38. package/src/hooks/index.ts +1 -0
  39. package/src/hooks/useTimedMetadata.ts +25 -0
  40. package/src/specs/TrackPlayer.nitro.ts +6 -0
  41. package/src/types/PlayerQueue.ts +16 -0
@@ -1,5 +1,10 @@
1
1
  import { PlayerQueue, TrackPlayer } from '../index'
2
- import type { TrackItem, TrackPlayerState, Reason } from '../types/PlayerQueue'
2
+ import type {
3
+ TrackItem,
4
+ TrackPlayerState,
5
+ Reason,
6
+ TimedMetadata,
7
+ } from '../types/PlayerQueue'
3
8
 
4
9
  type PlaybackStateCallback = (state: TrackPlayerState, reason?: Reason) => void
5
10
  type TrackChangeCallback = (track: TrackItem, reason?: Reason) => void
@@ -9,6 +14,7 @@ type PlaybackProgressCallback = (
9
14
  isManuallySeeked?: boolean
10
15
  ) => void
11
16
  type SeekCallback = (position: number, totalDuration: number) => void
17
+ type TimedMetadataCallback = (metadata: TimedMetadata) => void
12
18
  type TemporaryQueueCallback = (
13
19
  playNextQueue: TrackItem[],
14
20
  upNextQueue: TrackItem[]
@@ -24,6 +30,7 @@ class CallbackSubscriptionManager {
24
30
  private trackChangeSubscribers = new Set<TrackChangeCallback>()
25
31
  private playbackProgressSubscribers = new Set<PlaybackProgressCallback>()
26
32
  private seekSubscribers = new Set<SeekCallback>()
33
+ private timedMetadataSubscribers = new Set<TimedMetadataCallback>()
27
34
  private temporaryQueueSubscribers = new Set<TemporaryQueueCallback>()
28
35
  private playlistsChangedSubscribers = new Set<() => void>()
29
36
  private isPlaylistsChangedRegistered = false
@@ -31,6 +38,7 @@ class CallbackSubscriptionManager {
31
38
  private isTrackChangeRegistered = false
32
39
  private isPlaybackProgressRegistered = false
33
40
  private isSeekRegistered = false
41
+ private isTimedMetadataRegistered = false
34
42
  private isTemporaryQueueRegistered = false
35
43
 
36
44
  /**
@@ -263,6 +271,44 @@ class CallbackSubscriptionManager {
263
271
  )
264
272
  }
265
273
  }
274
+
275
+ /**
276
+ * Subscribe to in-stream (timed) metadata events
277
+ * @returns Unsubscribe function
278
+ */
279
+ subscribeToTimedMetadata(callback: TimedMetadataCallback): () => void {
280
+ this.timedMetadataSubscribers.add(callback)
281
+ this.ensureTimedMetadataRegistered()
282
+
283
+ return () => {
284
+ this.timedMetadataSubscribers.delete(callback)
285
+ }
286
+ }
287
+
288
+ private ensureTimedMetadataRegistered(): void {
289
+ if (this.isTimedMetadataRegistered) return
290
+
291
+ try {
292
+ TrackPlayer.onTimedMetadata((metadata) => {
293
+ this.timedMetadataSubscribers.forEach((subscriber) => {
294
+ try {
295
+ subscriber(metadata)
296
+ } catch (error) {
297
+ console.error(
298
+ '[CallbackManager] Error in timed metadata subscriber:',
299
+ error
300
+ )
301
+ }
302
+ })
303
+ })
304
+ this.isTimedMetadataRegistered = true
305
+ } catch (error) {
306
+ console.error(
307
+ '[CallbackManager] Failed to register timed metadata callback:',
308
+ error
309
+ )
310
+ }
311
+ }
266
312
  }
267
313
 
268
314
  // Export singleton instance
@@ -4,6 +4,7 @@ export { useOnPlaybackStateChange } from './useOnPlaybackStateChange'
4
4
  export type { PlaybackStateResult } from './useOnPlaybackStateChange'
5
5
  export { useOnSeek } from './useOnSeek'
6
6
  export { useOnPlaybackProgressChange } from './useOnPlaybackProgressChange'
7
+ export { useTimedMetadata } from './useTimedMetadata'
7
8
  export { useAndroidAutoConnection } from './useAndroidAutoConnection'
8
9
  export { useAudioDevices } from './useAudioDevices'
9
10
  export { useNowPlaying } from './useNowPlaying'
@@ -0,0 +1,25 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { callbackManager } from './callbackManager'
3
+ import type { TimedMetadata } from '../types/PlayerQueue'
4
+
5
+ /**
6
+ * Hook to subscribe to in-stream (timed) metadata — ICY/Shoutcast StreamTitle
7
+ * updates and ID3 frames emitted while a live stream plays.
8
+ *
9
+ * @returns The most recent metadata, or undefined until the first event arrives
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * function NowPlayingFromStream() {
14
+ * const metadata = useTimedMetadata()
15
+ * return <Text>{metadata?.title ?? 'Live'}</Text>
16
+ * }
17
+ * ```
18
+ */
19
+ export function useTimedMetadata(): TimedMetadata | undefined {
20
+ const [metadata, setMetadata] = useState<TimedMetadata | undefined>(undefined)
21
+
22
+ useEffect(() => callbackManager.subscribeToTimedMetadata(setMetadata), [])
23
+
24
+ return metadata
25
+ }
@@ -7,6 +7,7 @@ import type {
7
7
  PlayerState,
8
8
  PlayerConfig,
9
9
  Playlist,
10
+ TimedMetadata,
10
11
  } from '../types/PlayerQueue'
11
12
 
12
13
  export interface PlayerQueue extends HybridObject<{
@@ -96,6 +97,11 @@ export interface TrackPlayer extends HybridObject<{
96
97
  isManuallySeeked?: boolean
97
98
  ) => void
98
99
  ): void
100
+ /**
101
+ * Register callback for in-stream (timed) metadata — ICY/Shoutcast StreamTitle
102
+ * updates and ID3 frames emitted while a live stream plays.
103
+ */
104
+ onTimedMetadata(callback: (metadata: TimedMetadata) => void): void
99
105
  onAndroidAutoConnectionChange(callback: (connected: boolean) => void): void
100
106
  isAndroidAutoConnected(): boolean
101
107
  setVolume(volume: number): Promise<void>
@@ -40,6 +40,22 @@ export interface PlayerState {
40
40
  currentPlayingType: CurrentPlayingType
41
41
  }
42
42
 
43
+ /** In-stream metadata emitted while a stream plays (ICY/Shoutcast StreamTitle, ID3 frames) */
44
+ export interface TimedMetadata {
45
+ title?: string
46
+ /** Split out of `title` when the stream sends only `"Artist - Title"` */
47
+ artist?: string
48
+ album?: string
49
+ /**
50
+ * ICY `StreamUrl` / ID3 webpage frame. Radio providers commonly put the
51
+ * current track's artwork URL here (Live365, StreamGuys), but some send a
52
+ * station or artist page instead — check the value before treating it as art.
53
+ */
54
+ url?: string
55
+ /** Artwork URL the stream tagged as artwork, when it sends one explicitly */
56
+ artworkUrl?: string
57
+ }
58
+
43
59
  export interface PlayerConfig {
44
60
  androidAutoEnabled?: boolean
45
61
  carPlayEnabled?: boolean