@javascriptcommon/react-native-track-player 1.2.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.
Files changed (79) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/LICENSE +21 -0
  3. package/android/build.gradle +34 -0
  4. package/android/proguard-rules.txt +3 -0
  5. package/android/react-native-music-control.iml +139 -0
  6. package/android/react-native-track-player.iml +151 -0
  7. package/android/src/main/AndroidManifest.xml +30 -0
  8. package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +28 -0
  9. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +55 -0
  10. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +298 -0
  11. package/android/src/main/java/com/guichaguri/trackplayer/service/HeadlessJsMediaService.java +174 -0
  12. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +47 -0
  13. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +383 -0
  14. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +271 -0
  15. package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +243 -0
  16. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +148 -0
  17. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +379 -0
  18. package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +141 -0
  19. package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +35 -0
  20. package/android/src/main/res/drawable-hdpi/ic_forward.png +0 -0
  21. package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
  22. package/android/src/main/res/drawable-hdpi/ic_next.png +0 -0
  23. package/android/src/main/res/drawable-hdpi/ic_pause.png +0 -0
  24. package/android/src/main/res/drawable-hdpi/ic_play.png +0 -0
  25. package/android/src/main/res/drawable-hdpi/ic_previous.png +0 -0
  26. package/android/src/main/res/drawable-hdpi/ic_rewind.png +0 -0
  27. package/android/src/main/res/drawable-hdpi/ic_stop.png +0 -0
  28. package/android/src/main/res/drawable-mdpi/ic_forward.png +0 -0
  29. package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
  30. package/android/src/main/res/drawable-mdpi/ic_next.png +0 -0
  31. package/android/src/main/res/drawable-mdpi/ic_pause.png +0 -0
  32. package/android/src/main/res/drawable-mdpi/ic_play.png +0 -0
  33. package/android/src/main/res/drawable-mdpi/ic_previous.png +0 -0
  34. package/android/src/main/res/drawable-mdpi/ic_rewind.png +0 -0
  35. package/android/src/main/res/drawable-mdpi/ic_stop.png +0 -0
  36. package/android/src/main/res/drawable-xhdpi/ic_forward.png +0 -0
  37. package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
  38. package/android/src/main/res/drawable-xhdpi/ic_next.png +0 -0
  39. package/android/src/main/res/drawable-xhdpi/ic_pause.png +0 -0
  40. package/android/src/main/res/drawable-xhdpi/ic_play.png +0 -0
  41. package/android/src/main/res/drawable-xhdpi/ic_previous.png +0 -0
  42. package/android/src/main/res/drawable-xhdpi/ic_rewind.png +0 -0
  43. package/android/src/main/res/drawable-xhdpi/ic_stop.png +0 -0
  44. package/android/src/main/res/drawable-xxhdpi/ic_forward.png +0 -0
  45. package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
  46. package/android/src/main/res/drawable-xxhdpi/ic_next.png +0 -0
  47. package/android/src/main/res/drawable-xxhdpi/ic_pause.png +0 -0
  48. package/android/src/main/res/drawable-xxhdpi/ic_play.png +0 -0
  49. package/android/src/main/res/drawable-xxhdpi/ic_previous.png +0 -0
  50. package/android/src/main/res/drawable-xxhdpi/ic_rewind.png +0 -0
  51. package/android/src/main/res/drawable-xxhdpi/ic_stop.png +0 -0
  52. package/android/src/main/res/drawable-xxxhdpi/ic_forward.png +0 -0
  53. package/android/src/main/res/drawable-xxxhdpi/ic_logo.png +0 -0
  54. package/android/src/main/res/drawable-xxxhdpi/ic_next.png +0 -0
  55. package/android/src/main/res/drawable-xxxhdpi/ic_pause.png +0 -0
  56. package/android/src/main/res/drawable-xxxhdpi/ic_play.png +0 -0
  57. package/android/src/main/res/drawable-xxxhdpi/ic_previous.png +0 -0
  58. package/android/src/main/res/drawable-xxxhdpi/ic_rewind.png +0 -0
  59. package/android/src/main/res/drawable-xxxhdpi/ic_stop.png +0 -0
  60. package/index.d.ts +174 -0
  61. package/index.js +4 -0
  62. package/ios/RNTrackPlayer/Models/Capabilities.swift +17 -0
  63. package/ios/RNTrackPlayer/Models/MediaURL.swift +32 -0
  64. package/ios/RNTrackPlayer/Models/Track.swift +120 -0
  65. package/ios/RNTrackPlayer/RNTrackPlayer.swift +488 -0
  66. package/ios/RNTrackPlayer/RNTrackPlayerBridge.h +12 -0
  67. package/ios/RNTrackPlayer/RNTrackPlayerBridge.m +29 -0
  68. package/ios/RNTrackPlayer/Support/RNTrackPlayer-Bridging-Header.h +6 -0
  69. package/ios/TrackPlayer.xcodeproj/project.pbxproj +495 -0
  70. package/ios/TrackPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  71. package/ios/TrackPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  72. package/ios/TrackPlayer.xcodeproj/project.xcworkspace/xcuserdata/marco.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  73. package/ios/TrackPlayer.xcodeproj/xcuserdata/marco.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  74. package/lib/ProgressComponent.js +70 -0
  75. package/lib/eventTypes.js +28 -0
  76. package/lib/hooks.js +160 -0
  77. package/lib/index.js +177 -0
  78. package/package.json +47 -0
  79. package/react-native-track-player.podspec +22 -0
package/lib/hooks.js ADDED
@@ -0,0 +1,160 @@
1
+ import { useEffect, useState, useDebugValue, useRef } from 'react';
2
+ import * as TrackPlayer from './index';
3
+ import TrackPlayerEvents from './eventTypes';
4
+
5
+ /**
6
+ * @description
7
+ * Get current playback state and subsequent updatates
8
+ */
9
+ const usePlaybackState = () => {
10
+ const [state, setState] = useState(TrackPlayer.STATE_NONE)
11
+
12
+ useEffect(() => {
13
+ async function setPlayerState() {
14
+ const playerState = await TrackPlayer.getState()
15
+ setState(playerState)
16
+ }
17
+
18
+ setPlayerState()
19
+
20
+ const sub = TrackPlayer.addEventListener(TrackPlayer.TrackPlayerEvents.PLAYBACK_STATE, data => {
21
+ setState(data.state)
22
+ })
23
+
24
+ return () => {
25
+ sub.remove()
26
+ }
27
+ }, [])
28
+
29
+ return state
30
+ }
31
+
32
+ /**
33
+ * @description
34
+ * Attaches a handler to the given TrackPlayer events and performs cleanup on unmount
35
+ * @param {Array<string>} events - TrackPlayer events to subscribe to
36
+ * @param {(payload: any) => void} handler - callback invoked when the event fires
37
+ */
38
+ const useTrackPlayerEvents = (events, handler) => {
39
+ const savedHandler = useRef();
40
+
41
+ useEffect(() => {
42
+ savedHandler.current = handler;
43
+ }, [handler]);
44
+
45
+ useEffect(
46
+ () => {
47
+ if (__DEV__) {
48
+ const allowedTypes = Object.values(TrackPlayerEvents);
49
+ const invalidTypes = events.filter(type => !allowedTypes.includes(type));
50
+ if (invalidTypes.length) {
51
+ console.warn(
52
+ 'One or more of the events provided to useTrackPlayerEvents is ' +
53
+ `not a valid TrackPlayer event: ${invalidTypes.join('\', \'')}. ` +
54
+ 'A list of available events can be found at ' +
55
+ 'https://react-native-kit.github.io/react-native-track-player/documentation/#events'
56
+ )
57
+ }
58
+ }
59
+
60
+ const subs = events.map(event =>
61
+ TrackPlayer.addEventListener(event,
62
+ (payload) => savedHandler.current({ ...payload, type: event })
63
+ )
64
+ );
65
+
66
+ return () => {
67
+ subs.forEach(sub => sub.remove());
68
+ }
69
+ },
70
+ events
71
+ );
72
+ }
73
+
74
+ const useInterval = (callback, delay) => {
75
+ const savedCallback = useRef();
76
+
77
+ useEffect(() => {
78
+ savedCallback.current = callback;
79
+ })
80
+
81
+ useEffect(() => {
82
+ if (!delay) return;
83
+ const id = setInterval(savedCallback.current, delay);
84
+ return () => clearInterval(id);
85
+ }, [delay]);
86
+ }
87
+
88
+ const useWhenPlaybackStateChanges = callback => {
89
+ useTrackPlayerEvents(
90
+ [TrackPlayerEvents.PLAYBACK_STATE],
91
+ ({ state }) => {
92
+ callback(state);
93
+ }
94
+ );
95
+ useEffect(() => {
96
+ let didCancel = false;
97
+ const fetchPlaybackState = async () => {
98
+ const playbackState = await TrackPlayer.getState();
99
+ if (!didCancel) {
100
+ callback(playbackState);
101
+ }
102
+ }
103
+ fetchPlaybackState();
104
+ return () => { didCancel = true };
105
+ }, []);
106
+ }
107
+
108
+ const usePlaybackStateIs = (...states) => {
109
+ const [is, setIs] = useState();
110
+ useWhenPlaybackStateChanges(state => {
111
+ setIs(states.includes(state));
112
+ });
113
+
114
+ return is;
115
+ }
116
+
117
+ /**
118
+ * @description
119
+ * Poll for track progress for the given interval (in miliseconds)
120
+ * @param {number} interval - ms interval
121
+ * @returns {[
122
+ * {
123
+ * progress: number,
124
+ * bufferedPosition: number,
125
+ * duration: number
126
+ * },
127
+ * (interval: number) => void
128
+ * ]}
129
+ */
130
+ const useTrackPlayerProgress = (interval = 1000) => {
131
+ const initialState = {
132
+ position: 0,
133
+ bufferedPosition: 0,
134
+ duration: 0
135
+ };
136
+
137
+ const [state, setState] = useState(initialState);
138
+
139
+ const getProgress = async () => {
140
+ const [position, bufferedPosition, duration] = await Promise.all([
141
+ TrackPlayer.getPosition(),
142
+ TrackPlayer.getBufferedPosition(),
143
+ TrackPlayer.getDuration()
144
+ ])
145
+ setState({ position, bufferedPosition, duration });
146
+ }
147
+
148
+ const needsPoll = usePlaybackStateIs(
149
+ TrackPlayer.STATE_PLAYING,
150
+ TrackPlayer.STATE_BUFFERING
151
+ );
152
+ useInterval(getProgress, needsPoll ? interval : null);
153
+ return state;
154
+ }
155
+
156
+
157
+ // Exports
158
+ module.exports.usePlaybackState = usePlaybackState
159
+ module.exports.useTrackPlayerEvents = useTrackPlayerEvents
160
+ module.exports.useTrackPlayerProgress = useTrackPlayerProgress
package/lib/index.js ADDED
@@ -0,0 +1,177 @@
1
+ import { Platform, AppRegistry, DeviceEventEmitter, NativeEventEmitter, NativeModules } from 'react-native';
2
+ import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
3
+
4
+ const { TrackPlayerModule: TrackPlayer } = NativeModules;
5
+ const emitter = Platform.OS !== 'android' ? new NativeEventEmitter(TrackPlayer) : DeviceEventEmitter;
6
+
7
+ let registeredHeadlessTask = false;
8
+
9
+ function resolveAsset(uri) {
10
+ if(!uri) return undefined;
11
+ return resolveAssetSource(uri);
12
+ }
13
+
14
+ function resolveUrl(url) {
15
+ if(!url) return undefined;
16
+ return resolveAssetSource(url) || url;
17
+ }
18
+
19
+ function setupPlayer(options) {
20
+ return TrackPlayer.setupPlayer(options || {});
21
+ }
22
+
23
+ function updateOptions(data) {
24
+ // Clone the object before modifying it, so we don't run into problems with immutable objects
25
+ data = Object.assign({}, data);
26
+
27
+ // Resolve the asset for each icon
28
+ data.icon = resolveAsset(data.icon);
29
+ data.playIcon = resolveAsset(data.playIcon);
30
+ data.pauseIcon = resolveAsset(data.pauseIcon);
31
+ data.stopIcon = resolveAsset(data.stopIcon);
32
+ data.previousIcon = resolveAsset(data.previousIcon);
33
+ data.nextIcon = resolveAsset(data.nextIcon);
34
+ data.rewindIcon = resolveAsset(data.rewindIcon);
35
+ data.forwardIcon = resolveAsset(data.forwardIcon);
36
+
37
+ data.placeholderImage = resolveAsset(data.placeholderImage);
38
+
39
+ return TrackPlayer.updateOptions(data);
40
+ }
41
+
42
+ function setNowPlaying(track) {
43
+
44
+ // Resolve the URL
45
+ track.artwork = resolveUrl(track.artwork);
46
+
47
+ return TrackPlayer.setNowPlaying(track);
48
+ }
49
+
50
+ function remove(tracks) {
51
+ if(!Array.isArray(tracks)) {
52
+ tracks = [tracks];
53
+ }
54
+
55
+ return TrackPlayer.remove(tracks);
56
+ }
57
+
58
+ function registerPlaybackService(serviceFactory) {
59
+ if (Platform.OS === 'android' && !registeredHeadlessTask) {
60
+ // Registers the headless task
61
+ registeredHeadlessTask = true;
62
+ AppRegistry.registerHeadlessTask('TrackPlayer', serviceFactory);
63
+ } else {
64
+ // Initializes and runs the service in the next tick
65
+ setImmediate(serviceFactory());
66
+ }
67
+ }
68
+
69
+ function addEventListener(event, listener) {
70
+ return emitter.addListener(event, listener);
71
+ }
72
+
73
+ function warpEventResponse(handler, event, payload) {
74
+ // transform into the old format and return to handler
75
+ const additionalKeys = payload || {};
76
+ handler({ type: event, ...additionalKeys });
77
+ }
78
+
79
+ /**
80
+ * @deprecated since version 1.0.1. Use addEventListener instead.
81
+ */
82
+ function registerEventHandler(handler) {
83
+ let events = [
84
+ 'playback-state',
85
+ 'playback-error',
86
+ 'playback-queue-ended',
87
+ 'playback-track-changed',
88
+
89
+ 'remote-play',
90
+ 'remote-pause',
91
+ 'remote-stop',
92
+ 'remote-next',
93
+ 'remote-previous',
94
+ 'remote-jump-forward',
95
+ 'remote-jump-backward',
96
+ 'remote-seek',
97
+ 'remote-duck'
98
+ ];
99
+
100
+ if (Platform.OS === 'android') {
101
+ events.push('remote-skip', 'remote-set-rating', 'remote-play-id', 'remote-play-search');
102
+ }
103
+ else if(Platform.OS === 'ios'){
104
+ events.push('remote-play-pause')
105
+ }
106
+
107
+ registerPlaybackService(() => {
108
+ return async function() {
109
+ for (let i = 0; i < events.length; i++) {
110
+ addEventListener(events[i], warpEventResponse.bind(null, handler, events[i]));
111
+ }
112
+ };
113
+ });
114
+ }
115
+
116
+ // We'll declare each one of the constants and functions manually so IDEs can show a list of them
117
+ // We should also add documentation here, but I'll leave this task to another day
118
+
119
+ // States
120
+ module.exports.STATE_NONE = TrackPlayer.STATE_NONE;
121
+ module.exports.STATE_READY = TrackPlayer.STATE_READY;
122
+ module.exports.STATE_PLAYING = TrackPlayer.STATE_PLAYING;
123
+ module.exports.STATE_PAUSED = TrackPlayer.STATE_PAUSED;
124
+ module.exports.STATE_STOPPED = TrackPlayer.STATE_STOPPED;
125
+ module.exports.STATE_BUFFERING = TrackPlayer.STATE_BUFFERING;
126
+ module.exports.STATE_CONNECTING = TrackPlayer.STATE_CONNECTING;
127
+
128
+ // Capabilities
129
+ module.exports.CAPABILITY_PLAY = TrackPlayer.CAPABILITY_PLAY;
130
+ module.exports.CAPABILITY_PLAY_FROM_ID = TrackPlayer.CAPABILITY_PLAY_FROM_ID;
131
+ module.exports.CAPABILITY_PLAY_FROM_SEARCH = TrackPlayer.CAPABILITY_PLAY_FROM_SEARCH;
132
+ module.exports.CAPABILITY_PAUSE = TrackPlayer.CAPABILITY_PAUSE;
133
+ module.exports.CAPABILITY_STOP = TrackPlayer.CAPABILITY_STOP;
134
+ module.exports.CAPABILITY_SEEK_TO = TrackPlayer.CAPABILITY_SEEK_TO;
135
+ module.exports.CAPABILITY_SKIP = TrackPlayer.CAPABILITY_SKIP;
136
+ module.exports.CAPABILITY_SKIP_TO_NEXT = TrackPlayer.CAPABILITY_SKIP_TO_NEXT;
137
+ module.exports.CAPABILITY_SKIP_TO_PREVIOUS = TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS;
138
+ module.exports.CAPABILITY_JUMP_FORWARD = TrackPlayer.CAPABILITY_JUMP_FORWARD;
139
+ module.exports.CAPABILITY_JUMP_BACKWARD = TrackPlayer.CAPABILITY_JUMP_BACKWARD;
140
+ module.exports.CAPABILITY_SET_RATING = TrackPlayer.CAPABILITY_SET_RATING;
141
+ module.exports.CAPABILITY_LIKE = TrackPlayer.CAPABILITY_LIKE;
142
+ module.exports.CAPABILITY_DISLIKE = TrackPlayer.CAPABILITY_DISLIKE;
143
+ module.exports.CAPABILITY_BOOKMARK = TrackPlayer.CAPABILITY_BOOKMARK;
144
+
145
+ // Rating Types
146
+ module.exports.RATING_HEART = TrackPlayer.RATING_HEART;
147
+ module.exports.RATING_THUMBS_UP_DOWN = TrackPlayer.RATING_THUMBS_UP_DOWN;
148
+ module.exports.RATING_3_STARS = TrackPlayer.RATING_3_STARS;
149
+ module.exports.RATING_4_STARS = TrackPlayer.RATING_4_STARS;
150
+ module.exports.RATING_5_STARS = TrackPlayer.RATING_5_STARS;
151
+ module.exports.RATING_PERCENTAGE = TrackPlayer.RATING_PERCENTAGE;
152
+
153
+ // General
154
+ module.exports.setupPlayer = setupPlayer;
155
+ module.exports.destroy = TrackPlayer.destroy;
156
+ module.exports.updateOptions = updateOptions;
157
+ module.exports.registerEventHandler = registerEventHandler;
158
+ module.exports.registerBackendService = registerPlaybackService;
159
+ module.exports.registerPlaybackService = registerPlaybackService;
160
+ module.exports.addEventListener = addEventListener;
161
+
162
+ // Player Queue Commands
163
+ module.exports.setNowPlaying = setNowPlaying;
164
+ module.exports.updateMetadataForTrack = TrackPlayer.updateMetadataForTrack;
165
+ module.exports.updatePlayback = TrackPlayer.updatePlayback;
166
+ module.exports.reset = TrackPlayer.reset;
167
+
168
+ // Player Event Types
169
+ module.exports.TrackPlayerEvents = require('./eventTypes');
170
+
171
+ // Components
172
+ module.exports.ProgressComponent = require('./ProgressComponent');
173
+
174
+ // React Hooks (Requires React v16.8+ and React Native v0.59+)
175
+ module.exports.useTrackPlayerEvents = require('./hooks').useTrackPlayerEvents;
176
+ module.exports.useTrackPlayerProgress = require('./hooks').useTrackPlayerProgress;
177
+ module.exports.usePlaybackState = require('./hooks').usePlaybackState;
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@javascriptcommon/react-native-track-player",
3
+ "version": "1.2.9",
4
+ "description": "A fully fledged audio module created for music apps",
5
+ "contributors": [
6
+ {
7
+ "name": "David Chavez",
8
+ "email": "david@dcvz.io",
9
+ "url": "http://dcvz.io"
10
+ },
11
+ {
12
+ "name": "Guilherme Chaguri",
13
+ "email": "guichaguri@gmail.com",
14
+ "url": "http://guichaguri.com"
15
+ }
16
+ ],
17
+ "keywords": [
18
+ "react",
19
+ "react-native",
20
+ "track-player",
21
+ "audio-player",
22
+ "audio",
23
+ "player",
24
+ "music",
25
+ "controls",
26
+ "chromecast",
27
+ "android",
28
+ "ios",
29
+ "windows",
30
+ "hooks"
31
+ ],
32
+ "license": "Apache-2.0",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/doublesymmetry/react-native-track-player.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/doublesymmetry/react-native-track-player/issues"
39
+ },
40
+ "scripts": {
41
+ "prepublishOnly": "git submodule update --init --recursive"
42
+ },
43
+ "peerDependencies": {
44
+ "react": ">=16.8.6",
45
+ "react-native": ">=0.60.0-rc.2"
46
+ }
47
+ }
@@ -0,0 +1,22 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "react-native-track-player"
7
+ s.version = package["version"]
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+
11
+ s.author = "David Chavez"
12
+ s.homepage = package['repository']['url']
13
+ s.platform = { :ios => "11.0", :tvos => "11.0" }
14
+
15
+ s.ios.deployment_target = "11.0"
16
+ s.tvos.deployment_target = "11.0"
17
+
18
+ s.source = { :git => package['repository']['url'], :tag => "v#{s.version}" }
19
+ s.source_files = "ios/**/*.{h,m,swift}"
20
+
21
+ s.dependency "React-Core"
22
+ end