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.
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +6 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +7 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerListener.kt +32 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerNotify.kt +5 -0
- package/ios/HybridTrackPlayer.swift +6 -0
- package/ios/core/TrackPlayerCore.swift +13 -0
- package/ios/core/TrackPlayerListener.swift +89 -0
- package/ios/core/TrackPlayerNotify.swift +4 -0
- package/lib/hooks/callbackManager.d.ts +10 -1
- package/lib/hooks/callbackManager.js +33 -0
- package/lib/hooks/index.d.ts +1 -0
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/useTimedMetadata.d.ts +16 -0
- package/lib/hooks/useTimedMetadata.js +21 -0
- package/lib/specs/TrackPlayer.nitro.d.ts +6 -1
- package/lib/types/PlayerQueue.d.ts +15 -0
- package/nitrogen/generated/android/NitroPlayerOnLoad.cpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_TimedMetadata.hpp +79 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +9 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +1 -0
- package/nitrogen/generated/android/c++/JTimedMetadata.hpp +74 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Func_void_TimedMetadata.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +9 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/TimedMetadata.kt +50 -0
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.cpp +8 -0
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +25 -0
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Umbrella.hpp +3 -0
- package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +9 -0
- package/nitrogen/generated/ios/swift/Func_void_TimedMetadata.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +16 -0
- package/nitrogen/generated/ios/swift/TimedMetadata.swift +114 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/TimedMetadata.hpp +100 -0
- package/package.json +1 -1
- package/src/hooks/callbackManager.ts +47 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useTimedMetadata.ts +25 -0
- package/src/specs/TrackPlayer.nitro.ts +6 -0
- package/src/types/PlayerQueue.ts +16 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { PlayerQueue, TrackPlayer } from '../index'
|
|
2
|
-
import type {
|
|
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
|
package/src/hooks/index.ts
CHANGED
|
@@ -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>
|
package/src/types/PlayerQueue.ts
CHANGED
|
@@ -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
|