react-native-mp3 0.1.0

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 (64) hide show
  1. package/android/build.gradle +111 -0
  2. package/android/src/main/AndroidManifest.xml +44 -0
  3. package/android/src/main/java/com/reactnativemp3/Mp3Package.kt +23 -0
  4. package/android/src/main/java/com/reactnativemp3/Mp3TurboModule.kt +43 -0
  5. package/android/src/main/java/com/reactnativemp3/database/MusicDatabase.kt +48 -0
  6. package/android/src/main/java/com/reactnativemp3/database/dao/SongDao.kt +72 -0
  7. package/android/src/main/java/com/reactnativemp3/database/entities/PlaylistEntity.kt +58 -0
  8. package/android/src/main/java/com/reactnativemp3/database/entities/SongEntity.kt +104 -0
  9. package/android/src/main/java/com/reactnativemp3/database/entities/ThumbnailCacheEntity.kt +43 -0
  10. package/android/src/main/java/com/reactnativemp3/managers/CacheManager.kt +0 -0
  11. package/android/src/main/java/com/reactnativemp3/managers/EqualizerManager.kt +0 -0
  12. package/android/src/main/java/com/reactnativemp3/modules/MetadataModule.kt +330 -0
  13. package/android/src/main/java/com/reactnativemp3/modules/NotificationModule.kt +236 -0
  14. package/android/src/main/java/com/reactnativemp3/modules/PlayerModule.kt +710 -0
  15. package/android/src/main/java/com/reactnativemp3/modules/ScannerModule.kt +640 -0
  16. package/android/src/main/java/com/reactnativemp3/services/AudioFocusService.kt +0 -0
  17. package/android/src/main/java/com/reactnativemp3/services/FileObserverService.kt +0 -0
  18. package/android/src/main/java/com/reactnativemp3/services/MusicService.kt +309 -0
  19. package/android/src/main/java/com/reactnativemp3/utils/MediaStoreUtils.kt +0 -0
  20. package/android/src/main/java/com/reactnativemp3/utils/PermissionUtils.kt +0 -0
  21. package/android/src/main/jni/Mp3TurboModule.cpp +29 -0
  22. package/android/src/main/res/drawable/ic_music_note.xml +11 -0
  23. package/android/src/main/res/drawable/ic_pause.xml +11 -0
  24. package/android/src/main/res/drawable/ic_play.xml +11 -0
  25. package/android/src/main/res/drawable/ic_skip_next.xml +11 -0
  26. package/android/src/main/res/drawable/ic_skip_previous.xml +11 -0
  27. package/android/src/main/res/drawable/ic_stop.xml +11 -0
  28. package/lib/components/MusicList.d.ts +0 -0
  29. package/lib/components/MusicList.js +1 -0
  30. package/lib/components/MusicPlayerUI.d.ts +0 -0
  31. package/lib/components/MusicPlayerUI.js +1 -0
  32. package/lib/hooks/useMusicPlayer.d.ts +38 -0
  33. package/lib/hooks/useMusicPlayer.js +242 -0
  34. package/lib/hooks/useMusicScanner.d.ts +27 -0
  35. package/lib/hooks/useMusicScanner.js +217 -0
  36. package/lib/hooks/usePermissions.d.ts +9 -0
  37. package/lib/hooks/usePermissions.js +55 -0
  38. package/lib/index.d.ts +144 -0
  39. package/lib/index.js +148 -0
  40. package/lib/types/common.types.d.ts +79 -0
  41. package/lib/types/common.types.js +2 -0
  42. package/lib/types/index.d.ts +3 -0
  43. package/lib/types/index.js +2 -0
  44. package/lib/types/player.types.d.ts +35 -0
  45. package/lib/types/player.types.js +2 -0
  46. package/lib/types/scanner.types.d.ts +29 -0
  47. package/lib/types/scanner.types.js +2 -0
  48. package/lib/utils/constants.d.ts +31 -0
  49. package/lib/utils/constants.js +55 -0
  50. package/lib/utils/events.d.ts +0 -0
  51. package/lib/utils/events.js +1 -0
  52. package/package.json +62 -0
  53. package/src/components/MusicList.tsx +0 -0
  54. package/src/components/MusicPlayerUI.tsx +0 -0
  55. package/src/hooks/useMusicPlayer.ts +358 -0
  56. package/src/hooks/useMusicScanner.ts +286 -0
  57. package/src/hooks/usePermissions.ts +64 -0
  58. package/src/index.ts +214 -0
  59. package/src/types/common.types.ts +86 -0
  60. package/src/types/index.ts +4 -0
  61. package/src/types/player.types.ts +37 -0
  62. package/src/types/scanner.types.ts +31 -0
  63. package/src/utils/constants.ts +56 -0
  64. package/src/utils/events.ts +0 -0
package/src/index.ts ADDED
@@ -0,0 +1,214 @@
1
+ import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
2
+
3
+ // Import constants
4
+ import { ScannerEvents, PlayerEvents, RepeatMode, EqualizerPresets, AudioExtensions } from './utils/constants';
5
+ import { Album, Artist, PlaybackState, ScannerOptions, Song } from './types';
6
+
7
+ // Types - Re-export explicitly to avoid conflicts
8
+ export {
9
+ Song,
10
+ Album,
11
+ Artist,
12
+ Playlist,
13
+ PlaybackState,
14
+ EqualizerPreset,
15
+ ScannerOptions,
16
+ PlayerOptions,
17
+ } from './types/common.types';
18
+
19
+ export type {
20
+ ScannerEvents as ScannerEventsType,
21
+ ScannerEventType,
22
+ } from './types/scanner.types';
23
+
24
+ export type {
25
+ PlayerEvents as PlayerEventsType,
26
+ PlayerEventType,
27
+ } from './types/player.types';
28
+
29
+ // Constants - export as values
30
+ export {
31
+ ScannerEvents,
32
+ PlayerEvents,
33
+ RepeatMode,
34
+ EqualizerPresets,
35
+ AudioExtensions,
36
+ };
37
+
38
+ // Hooks
39
+ export { useMusicPlayer } from './hooks/useMusicPlayer';
40
+ export { useMusicScanner } from './hooks/useMusicScanner';
41
+ export { usePermissions } from './hooks/usePermissions';
42
+
43
+ // Optional UI Components (if needed)
44
+ // export { MusicPlayerUI } from './components/MusicPlayerUI';
45
+ // export { MusicList } from './components/MusicList';
46
+
47
+ // Native Modules
48
+ const { ScannerModule, PlayerModule, MetadataModule, NotificationModule } =
49
+ NativeModules;
50
+
51
+ // Event Emitters
52
+ const scannerEventEmitter = new NativeEventEmitter(ScannerModule);
53
+ const playerEventEmitter = new NativeEventEmitter(PlayerModule);
54
+
55
+ // Check if native modules are available
56
+ if (!ScannerModule || !PlayerModule) {
57
+ console.warn(
58
+ 'react-native-mp3 native modules are not available. Make sure to link the package properly.'
59
+ );
60
+ }
61
+
62
+ // Scanner Module Functions
63
+ export const Scanner = {
64
+ // Permission
65
+ requestStoragePermission: (): Promise<boolean> =>
66
+ ScannerModule.requestStoragePermission(),
67
+ checkPermissionStatus: (): Promise<boolean> =>
68
+ ScannerModule.checkPermissionStatus(),
69
+
70
+ // Scanning
71
+ scanMusicFiles: (options?: ScannerOptions): Promise<any> =>
72
+ ScannerModule.scanMusicFiles(options || {}),
73
+ getCachedSongs: (options?: any): Promise<Song[]> =>
74
+ ScannerModule.getCachedSongs(options || {}),
75
+
76
+ // File Operations
77
+ deleteSong: (songId: string): Promise<boolean> =>
78
+ ScannerModule.deleteSong(songId),
79
+ addToFavorites: (songId: string): Promise<boolean> =>
80
+ ScannerModule.addToFavorites(songId),
81
+ removeFromFavorites: (songId: string): Promise<boolean> =>
82
+ ScannerModule.removeFromFavorites(songId),
83
+
84
+ // Metadata
85
+ getAlbums: (): Promise<Album[]> => ScannerModule.getAlbums(),
86
+ getArtists: (): Promise<Artist[]> => ScannerModule.getArtists(),
87
+ searchSongs: (query: string): Promise<Song[]> => ScannerModule.searchSongs(query),
88
+
89
+ // Cache Management
90
+ clearCache: (): Promise<boolean> => ScannerModule.clearCache(),
91
+
92
+ // File Monitoring
93
+ startFileMonitoring: (): void => ScannerModule.startFileMonitoring(),
94
+ stopFileMonitoring: (): void => ScannerModule.stopFileMonitoring(),
95
+
96
+ // Events
97
+ addEventListener: (
98
+ event: string,
99
+ listener: (data: any) => void
100
+ ): { remove: () => void } => {
101
+ const subscription = scannerEventEmitter.addListener(event, listener);
102
+ return { remove: () => subscription.remove() };
103
+ },
104
+
105
+ removeAllListeners: (event?: string): void => {
106
+ if (event) {
107
+ scannerEventEmitter.removeAllListeners(event);
108
+ } else {
109
+ // Remove all events by specifying each event type
110
+ const scannerEventTypes = Object.values(ScannerEvents) as string[];
111
+ scannerEventTypes.forEach(eventType => {
112
+ scannerEventEmitter.removeAllListeners(eventType);
113
+ });
114
+ }
115
+ },
116
+ };
117
+
118
+ // Player Module Functions
119
+ export const Player = {
120
+ // Playback Control
121
+ play: (uri: string): Promise<void> => PlayerModule.play(uri),
122
+ playFromQueue: (index: number): void => PlayerModule.playFromQueue(index),
123
+ pause: (): void => PlayerModule.pause(),
124
+ stop: (): void => PlayerModule.stop(),
125
+ seekTo: (position: number): void => PlayerModule.seekTo(position),
126
+ skipToNext: (): void => PlayerModule.skipToNext(),
127
+ skipToPrevious: (): void => PlayerModule.skipToPrevious(),
128
+ setVolume: (volume: number): void => PlayerModule.setVolume(volume),
129
+ setPlaybackRate: (rate: number): void => PlayerModule.setPlaybackRate(rate),
130
+
131
+ // Queue Management
132
+ setQueue: (songs: Song[]): void => PlayerModule.setQueue(songs),
133
+ addToQueue: (songs: Song[]): void => PlayerModule.addToQueue(songs),
134
+ clearQueue: (): void => PlayerModule.clearQueue(),
135
+ getQueue: (): Promise<Song[]> => PlayerModule.getQueue(),
136
+ getCurrentTrack: (): Promise<Song> => PlayerModule.getCurrentTrack(),
137
+
138
+ // Playback State
139
+ getPlaybackState: (): Promise<PlaybackState> => PlayerModule.getPlaybackState(),
140
+ getCurrentTime: (): Promise<number> => PlayerModule.getCurrentTime(),
141
+ getDuration: (): Promise<number> => PlayerModule.getDuration(),
142
+ isPlaying: (): Promise<boolean> => PlayerModule.isPlaying(),
143
+
144
+ // Playback Modes
145
+ setRepeatMode: (mode: 'none' | 'one' | 'all'): void =>
146
+ PlayerModule.setRepeatMode(mode),
147
+ setShuffleMode: (enabled: boolean): void => PlayerModule.setShuffleMode(enabled),
148
+
149
+ // Equalizer
150
+ setEqualizerPreset: (preset: string): void => PlayerModule.setEqualizerPreset(preset),
151
+ setEqualizerBands: (bands: number[]): void => PlayerModule.setEqualizerBands(bands),
152
+ getEqualizerPresets: (): Promise<string[]> => PlayerModule.getEqualizerPresets(),
153
+ enableEqualizer: (enabled: boolean): void => PlayerModule.enableEqualizer(enabled),
154
+
155
+ // Sleep Timer
156
+ setSleepTimer: (minutes: number): void => PlayerModule.setSleepTimer(minutes),
157
+ cancelSleepTimer: (): void => PlayerModule.cancelSleepTimer(),
158
+
159
+ // Background Playback
160
+ setupBackgroundPlayback: (config?: any): void =>
161
+ PlayerModule.setupBackgroundPlayback(config || {}),
162
+ stopBackgroundPlayback: (): void => PlayerModule.stopBackgroundPlayback(),
163
+
164
+ // Events
165
+ addEventListener: (
166
+ event: string,
167
+ listener: (data: any) => void
168
+ ): { remove: () => void } => {
169
+ const subscription = playerEventEmitter.addListener(event, listener);
170
+ return { remove: () => subscription.remove() };
171
+ },
172
+
173
+ removeAllListeners: (event?: string): void => {
174
+ if (event) {
175
+ playerEventEmitter.removeAllListeners(event);
176
+ } else {
177
+ // Remove all events by specifying each event type
178
+ const playerEventTypes = Object.values(PlayerEvents) as string[];
179
+ playerEventTypes.forEach(eventType => {
180
+ playerEventEmitter.removeAllListeners(eventType);
181
+ });
182
+ }
183
+ },
184
+ };
185
+
186
+ // Metadata Module Functions
187
+ export const Metadata = {
188
+ extractMetadata: (uri: string): Promise<any> => MetadataModule.extractMetadata(uri),
189
+ getAlbumArt: (uri: string, size?: number): Promise<string> =>
190
+ MetadataModule.getAlbumArt(uri, size || 300),
191
+ getLyrics: (uri: string): Promise<string | null> => MetadataModule.getLyrics(uri),
192
+ updateMetadata: (uri: string, metadata: any): Promise<boolean> =>
193
+ MetadataModule.updateMetadata(uri, metadata),
194
+ };
195
+
196
+ // Notification Module Functions
197
+ export const Notifications = {
198
+ setupNotificationChannel: (): void => NotificationModule.setupNotificationChannel(),
199
+ updateNotification: (metadata: any): void => NotificationModule.updateNotification(metadata),
200
+ hideNotification: (): void => NotificationModule.hideNotification(),
201
+ showNotification: (): void => NotificationModule.showNotification(),
202
+ };
203
+
204
+ // Default export
205
+ export default {
206
+ Scanner,
207
+ Player,
208
+ Metadata,
209
+ Notifications,
210
+ };
211
+
212
+ // Platform check
213
+ export const isAndroid = Platform.OS === 'android';
214
+ export const isIOS = Platform.OS === 'ios';
@@ -0,0 +1,86 @@
1
+ export interface Song {
2
+ id: string;
3
+ title: string;
4
+ artist: string;
5
+ album: string;
6
+ duration: number;
7
+ path: string;
8
+ uri: string;
9
+ albumArtUri?: string;
10
+ size: number;
11
+ mimeType: string;
12
+ trackNumber: number;
13
+ year?: number;
14
+ genre?: string;
15
+ dateAdded: number;
16
+ lastModified: number;
17
+ isFavorite: boolean;
18
+ playCount: number;
19
+ lastPlayed?: number;
20
+ bitrate?: number;
21
+ sampleRate?: number;
22
+ channels?: number;
23
+ composer?: string;
24
+ bookmark: number;
25
+ isPodcast: boolean;
26
+ rating?: number;
27
+ }
28
+
29
+ export interface Album {
30
+ name: string;
31
+ songCount: number;
32
+ albumArtUri?: string;
33
+ artist?: string;
34
+ year?: number;
35
+ }
36
+
37
+ export interface Artist {
38
+ name: string;
39
+ songCount: number;
40
+ albumCount: number;
41
+ }
42
+
43
+ export interface Playlist {
44
+ id: string;
45
+ name: string;
46
+ songCount: number;
47
+ thumbnailUri?: string;
48
+ createdAt: number;
49
+ }
50
+
51
+ export interface PlaybackState {
52
+ isPlaying: boolean;
53
+ currentTime: number;
54
+ duration: number;
55
+ buffered?: number;
56
+ playbackRate: number;
57
+ volume: number;
58
+ repeatMode: 'none' | 'one' | 'all';
59
+ shuffleMode: boolean;
60
+ currentSong?: Song;
61
+ queue: Song[];
62
+ queuePosition: number;
63
+ error?: string;
64
+ }
65
+
66
+ export interface EqualizerPreset {
67
+ name: string;
68
+ bands: number[];
69
+ }
70
+
71
+ export interface ScannerOptions {
72
+ forceRescan?: boolean;
73
+ paths?: string[];
74
+ maxFiles?: number;
75
+ extensions?: string[];
76
+ }
77
+
78
+ export interface PlayerOptions {
79
+ autoPlay?: boolean;
80
+ keepAwake?: boolean;
81
+ volume?: number;
82
+ speed?: number;
83
+ repeatMode?: 'none' | 'one' | 'all';
84
+ audioFocus?: boolean;
85
+ ducking?: boolean;
86
+ }
@@ -0,0 +1,4 @@
1
+ // Re-export everything explicitly
2
+ export type { Song, Album, Artist, Playlist, PlaybackState, EqualizerPreset, ScannerOptions, PlayerOptions } from './common.types';
3
+ export type { ScannerEvents, ScannerEventType } from './scanner.types';
4
+ export type { PlayerEvents, PlayerEventType } from './player.types';
@@ -0,0 +1,37 @@
1
+ export interface PlayerEvents {
2
+ PLAYBACK_STATE_CHANGED: {
3
+ isPlaying: boolean;
4
+ currentTime: number;
5
+ duration: number;
6
+ buffered?: number;
7
+ };
8
+ PLAYBACK_QUEUE_CHANGED: {
9
+ queue: any[];
10
+ position: number;
11
+ };
12
+ PLAYBACK_ERROR: {
13
+ error: string;
14
+ songId?: string;
15
+ };
16
+ PLAYBACK_COMPLETE: {
17
+ songId: string;
18
+ };
19
+ PLAYBACK_NEXT: {
20
+ songId: string;
21
+ };
22
+ PLAYBACK_PREVIOUS: {
23
+ songId: string;
24
+ };
25
+ EQUALIZER_CHANGED: {
26
+ enabled: boolean;
27
+ preset?: string;
28
+ bands?: number[];
29
+ };
30
+ }
31
+
32
+ export type PlayerEventType = keyof PlayerEvents;
33
+
34
+ export interface AudioFocusConfig {
35
+ focusGain: number; // AudioManager.AUDIOFOCUS_GAIN
36
+ willPauseWhenDucked: boolean;
37
+ }
@@ -0,0 +1,31 @@
1
+ export interface ScannerEvents {
2
+ SCAN_PROGRESS: {
3
+ processed: number;
4
+ total: number;
5
+ percentage: number;
6
+ };
7
+ SCAN_COMPLETE: {
8
+ totalSongs: number;
9
+ scanPaths: string[];
10
+ };
11
+ FILE_ADDED: {
12
+ songId: string;
13
+ path: string;
14
+ song: any;
15
+ };
16
+ FILE_DELETED: {
17
+ songId: string;
18
+ path: string;
19
+ };
20
+ PERMISSION_STATUS: {
21
+ granted: boolean;
22
+ message: string;
23
+ };
24
+ }
25
+
26
+ export type ScannerEventType = keyof ScannerEvents;
27
+
28
+ export interface ScanResult {
29
+ totalSongs: number;
30
+ scanPaths: string[];
31
+ }
@@ -0,0 +1,56 @@
1
+ export const ScannerEvents = {
2
+ SCAN_PROGRESS: 'SCAN_PROGRESS',
3
+ SCAN_COMPLETE: 'SCAN_COMPLETE',
4
+ FILE_ADDED: 'FILE_ADDED',
5
+ FILE_DELETED: 'FILE_DELETED',
6
+ PERMISSION_STATUS: 'PERMISSION_STATUS',
7
+ } as const;
8
+
9
+ export const PlayerEvents = {
10
+ PLAYBACK_STATE_CHANGED: 'PLAYBACK_STATE_CHANGED',
11
+ PLAYBACK_QUEUE_CHANGED: 'PLAYBACK_QUEUE_CHANGED',
12
+ PLAYBACK_ERROR: 'PLAYBACK_ERROR',
13
+ PLAYBACK_COMPLETE: 'PLAYBACK_COMPLETE',
14
+ PLAYBACK_NEXT: 'PLAYBACK_NEXT',
15
+ PLAYBACK_PREVIOUS: 'PLAYBACK_PREVIOUS',
16
+ EQUALIZER_CHANGED: 'EQUALIZER_CHANGED',
17
+ } as const;
18
+
19
+ export const RepeatMode = {
20
+ NONE: 'none',
21
+ ONE: 'one',
22
+ ALL: 'all',
23
+ } as const;
24
+
25
+ export const EqualizerPresets = {
26
+ NORMAL: 'normal',
27
+ ROCK: 'rock',
28
+ POP: 'pop',
29
+ JAZZ: 'jazz',
30
+ CLASSIC: 'classic',
31
+ DANCE: 'dance',
32
+ FLAT: 'flat',
33
+ } as const;
34
+
35
+ export const AudioExtensions = [
36
+ '.mp3',
37
+ '.mp4',
38
+ '.m4a',
39
+ '.aac',
40
+ '.flac',
41
+ '.wav',
42
+ '.ogg',
43
+ '.opus',
44
+ '.wma',
45
+ '.amr',
46
+ '.aif',
47
+ '.aiff',
48
+ '.mid',
49
+ '.midi',
50
+ '.xmf',
51
+ '.mxmf',
52
+ '.rtttl',
53
+ '.rtx',
54
+ '.ota',
55
+ '.imy',
56
+ ];
File without changes