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.
- package/android/build.gradle +111 -0
- package/android/src/main/AndroidManifest.xml +44 -0
- package/android/src/main/java/com/reactnativemp3/Mp3Package.kt +23 -0
- package/android/src/main/java/com/reactnativemp3/Mp3TurboModule.kt +43 -0
- package/android/src/main/java/com/reactnativemp3/database/MusicDatabase.kt +48 -0
- package/android/src/main/java/com/reactnativemp3/database/dao/SongDao.kt +72 -0
- package/android/src/main/java/com/reactnativemp3/database/entities/PlaylistEntity.kt +58 -0
- package/android/src/main/java/com/reactnativemp3/database/entities/SongEntity.kt +104 -0
- package/android/src/main/java/com/reactnativemp3/database/entities/ThumbnailCacheEntity.kt +43 -0
- package/android/src/main/java/com/reactnativemp3/managers/CacheManager.kt +0 -0
- package/android/src/main/java/com/reactnativemp3/managers/EqualizerManager.kt +0 -0
- package/android/src/main/java/com/reactnativemp3/modules/MetadataModule.kt +330 -0
- package/android/src/main/java/com/reactnativemp3/modules/NotificationModule.kt +236 -0
- package/android/src/main/java/com/reactnativemp3/modules/PlayerModule.kt +710 -0
- package/android/src/main/java/com/reactnativemp3/modules/ScannerModule.kt +640 -0
- package/android/src/main/java/com/reactnativemp3/services/AudioFocusService.kt +0 -0
- package/android/src/main/java/com/reactnativemp3/services/FileObserverService.kt +0 -0
- package/android/src/main/java/com/reactnativemp3/services/MusicService.kt +309 -0
- package/android/src/main/java/com/reactnativemp3/utils/MediaStoreUtils.kt +0 -0
- package/android/src/main/java/com/reactnativemp3/utils/PermissionUtils.kt +0 -0
- package/android/src/main/jni/Mp3TurboModule.cpp +29 -0
- package/android/src/main/res/drawable/ic_music_note.xml +11 -0
- package/android/src/main/res/drawable/ic_pause.xml +11 -0
- package/android/src/main/res/drawable/ic_play.xml +11 -0
- package/android/src/main/res/drawable/ic_skip_next.xml +11 -0
- package/android/src/main/res/drawable/ic_skip_previous.xml +11 -0
- package/android/src/main/res/drawable/ic_stop.xml +11 -0
- package/lib/components/MusicList.d.ts +0 -0
- package/lib/components/MusicList.js +1 -0
- package/lib/components/MusicPlayerUI.d.ts +0 -0
- package/lib/components/MusicPlayerUI.js +1 -0
- package/lib/hooks/useMusicPlayer.d.ts +38 -0
- package/lib/hooks/useMusicPlayer.js +242 -0
- package/lib/hooks/useMusicScanner.d.ts +27 -0
- package/lib/hooks/useMusicScanner.js +217 -0
- package/lib/hooks/usePermissions.d.ts +9 -0
- package/lib/hooks/usePermissions.js +55 -0
- package/lib/index.d.ts +144 -0
- package/lib/index.js +148 -0
- package/lib/types/common.types.d.ts +79 -0
- package/lib/types/common.types.js +2 -0
- package/lib/types/index.d.ts +3 -0
- package/lib/types/index.js +2 -0
- package/lib/types/player.types.d.ts +35 -0
- package/lib/types/player.types.js +2 -0
- package/lib/types/scanner.types.d.ts +29 -0
- package/lib/types/scanner.types.js +2 -0
- package/lib/utils/constants.d.ts +31 -0
- package/lib/utils/constants.js +55 -0
- package/lib/utils/events.d.ts +0 -0
- package/lib/utils/events.js +1 -0
- package/package.json +62 -0
- package/src/components/MusicList.tsx +0 -0
- package/src/components/MusicPlayerUI.tsx +0 -0
- package/src/hooks/useMusicPlayer.ts +358 -0
- package/src/hooks/useMusicScanner.ts +286 -0
- package/src/hooks/usePermissions.ts +64 -0
- package/src/index.ts +214 -0
- package/src/types/common.types.ts +86 -0
- package/src/types/index.ts +4 -0
- package/src/types/player.types.ts +37 -0
- package/src/types/scanner.types.ts +31 -0
- package/src/utils/constants.ts +56 -0
- package/src/utils/events.ts +0 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
package com.reactnativemp3.services
|
|
2
|
+
|
|
3
|
+
import android.app.Notification
|
|
4
|
+
import android.app.NotificationChannel
|
|
5
|
+
import android.app.NotificationManager
|
|
6
|
+
import android.app.PendingIntent
|
|
7
|
+
import android.app.Service
|
|
8
|
+
import android.content.Context
|
|
9
|
+
import android.content.Intent
|
|
10
|
+
import android.graphics.Bitmap
|
|
11
|
+
import android.graphics.BitmapFactory
|
|
12
|
+
import android.media.AudioManager
|
|
13
|
+
import android.media.MediaPlayer
|
|
14
|
+
import android.os.Binder
|
|
15
|
+
import android.os.Build
|
|
16
|
+
import android.os.IBinder
|
|
17
|
+
import android.support.v4.media.session.MediaSessionCompat
|
|
18
|
+
import androidx.core.app.NotificationCompat
|
|
19
|
+
import androidx.media.app.NotificationCompat as MediaNotificationCompat
|
|
20
|
+
import com.reactnativemp3.R
|
|
21
|
+
import kotlinx.coroutines.CoroutineScope
|
|
22
|
+
import kotlinx.coroutines.Dispatchers
|
|
23
|
+
import kotlinx.coroutines.SupervisorJob
|
|
24
|
+
import kotlinx.coroutines.launch
|
|
25
|
+
import java.lang.ref.WeakReference
|
|
26
|
+
|
|
27
|
+
class MusicService : Service(), AudioManager.OnAudioFocusChangeListener {
|
|
28
|
+
|
|
29
|
+
companion object {
|
|
30
|
+
private const val NOTIFICATION_CHANNEL_ID = "music_service_channel"
|
|
31
|
+
private const val NOTIFICATION_ID = 1002
|
|
32
|
+
const val ACTION_PLAY = "com.reactnativemp3.ACTION_PLAY"
|
|
33
|
+
const val ACTION_PAUSE = "com.reactnativemp3.ACTION_PAUSE"
|
|
34
|
+
const val ACTION_NEXT = "com.reactnativemp3.ACTION_NEXT"
|
|
35
|
+
const val ACTION_PREVIOUS = "com.reactnativemp3.ACTION_PREVIOUS"
|
|
36
|
+
const val ACTION_STOP = "com.reactnativemp3.ACTION_STOP"
|
|
37
|
+
|
|
38
|
+
fun createIntent(context: Context): Intent {
|
|
39
|
+
return Intent(context, MusicService::class.java)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private val binder = MusicBinder()
|
|
44
|
+
private lateinit var notificationManager: NotificationManager
|
|
45
|
+
private lateinit var audioManager: AudioManager
|
|
46
|
+
private var mediaSession: MediaSessionCompat? = null
|
|
47
|
+
|
|
48
|
+
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
|
49
|
+
|
|
50
|
+
// Media player state
|
|
51
|
+
private var mediaPlayer: MediaPlayer? = null
|
|
52
|
+
private var isPlaying: Boolean = false
|
|
53
|
+
private var currentTitle: String = ""
|
|
54
|
+
private var currentArtist: String = ""
|
|
55
|
+
private var currentAlbum: String = ""
|
|
56
|
+
private var albumArtBitmap: Bitmap? = null
|
|
57
|
+
|
|
58
|
+
inner class MusicBinder : Binder() {
|
|
59
|
+
fun getService(): MusicService = this@MusicService
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
override fun onCreate() {
|
|
63
|
+
super.onCreate()
|
|
64
|
+
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
65
|
+
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
66
|
+
createNotificationChannel()
|
|
67
|
+
setupMediaSession()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
|
71
|
+
intent?.action?.let { handleAction(it) }
|
|
72
|
+
return START_STICKY
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
override fun onBind(intent: Intent?): IBinder {
|
|
76
|
+
return binder
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override fun onUnbind(intent: Intent?): Boolean {
|
|
80
|
+
stopForeground(true)
|
|
81
|
+
stopSelf()
|
|
82
|
+
return super.onUnbind(intent)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun onDestroy() {
|
|
86
|
+
cleanup()
|
|
87
|
+
super.onDestroy()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
override fun onAudioFocusChange(focusChange: Int) {
|
|
91
|
+
when (focusChange) {
|
|
92
|
+
AudioManager.AUDIOFOCUS_LOSS -> {
|
|
93
|
+
// Lost audio focus for an indefinite period
|
|
94
|
+
pausePlayback()
|
|
95
|
+
}
|
|
96
|
+
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
|
|
97
|
+
// Lost audio focus for a short time
|
|
98
|
+
pausePlayback()
|
|
99
|
+
}
|
|
100
|
+
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
|
|
101
|
+
// Lost focus but can play at a lower volume
|
|
102
|
+
mediaPlayer?.setVolume(0.2f, 0.2f)
|
|
103
|
+
}
|
|
104
|
+
AudioManager.AUDIOFOCUS_GAIN -> {
|
|
105
|
+
// Gained audio focus
|
|
106
|
+
mediaPlayer?.setVolume(1.0f, 1.0f)
|
|
107
|
+
if (isPlaying) {
|
|
108
|
+
startPlayback()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
fun setPlaybackMetadata(title: String, artist: String, album: String, albumArt: Bitmap?) {
|
|
115
|
+
currentTitle = title
|
|
116
|
+
currentArtist = artist
|
|
117
|
+
currentAlbum = album
|
|
118
|
+
albumArtBitmap = albumArt
|
|
119
|
+
updateNotification()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
fun startPlayback() {
|
|
123
|
+
isPlaying = true
|
|
124
|
+
requestAudioFocus()
|
|
125
|
+
mediaPlayer?.start()
|
|
126
|
+
updateNotification()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
fun pausePlayback() {
|
|
130
|
+
isPlaying = false
|
|
131
|
+
mediaPlayer?.pause()
|
|
132
|
+
updateNotification()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
fun stopPlayback() {
|
|
136
|
+
isPlaying = false
|
|
137
|
+
mediaPlayer?.stop()
|
|
138
|
+
mediaPlayer?.release()
|
|
139
|
+
mediaPlayer = null
|
|
140
|
+
updateNotification()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fun setMediaPlayer(player: MediaPlayer) {
|
|
144
|
+
mediaPlayer?.release()
|
|
145
|
+
mediaPlayer = player
|
|
146
|
+
isPlaying = player.isPlaying
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private fun handleAction(action: String) {
|
|
150
|
+
when (action) {
|
|
151
|
+
ACTION_PLAY -> startPlayback()
|
|
152
|
+
ACTION_PAUSE -> pausePlayback()
|
|
153
|
+
ACTION_NEXT -> {
|
|
154
|
+
// Forward to activity/receiver
|
|
155
|
+
sendBroadcast(Intent(ACTION_NEXT))
|
|
156
|
+
}
|
|
157
|
+
ACTION_PREVIOUS -> {
|
|
158
|
+
// Forward to activity/receiver
|
|
159
|
+
sendBroadcast(Intent(ACTION_PREVIOUS))
|
|
160
|
+
}
|
|
161
|
+
ACTION_STOP -> {
|
|
162
|
+
stopPlayback()
|
|
163
|
+
stopForeground(true)
|
|
164
|
+
stopSelf()
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private fun requestAudioFocus(): Boolean {
|
|
170
|
+
val result = audioManager.requestAudioFocus(
|
|
171
|
+
this,
|
|
172
|
+
AudioManager.STREAM_MUSIC,
|
|
173
|
+
AudioManager.AUDIOFOCUS_GAIN
|
|
174
|
+
)
|
|
175
|
+
return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private fun createNotificationChannel() {
|
|
179
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
180
|
+
val channel = NotificationChannel(
|
|
181
|
+
NOTIFICATION_CHANNEL_ID,
|
|
182
|
+
"Music Playback",
|
|
183
|
+
NotificationManager.IMPORTANCE_LOW
|
|
184
|
+
).apply {
|
|
185
|
+
description = "Shows music playback controls"
|
|
186
|
+
setShowBadge(false)
|
|
187
|
+
lockscreenVisibility = Notification.VISIBILITY_PUBLIC
|
|
188
|
+
setSound(null, null)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
notificationManager.createNotificationChannel(channel)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private fun setupMediaSession() {
|
|
196
|
+
mediaSession = MediaSessionCompat(this, "MusicService").apply {
|
|
197
|
+
setFlags(
|
|
198
|
+
MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or
|
|
199
|
+
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
|
|
200
|
+
)
|
|
201
|
+
setCallback(object : MediaSessionCompat.Callback() {
|
|
202
|
+
override fun onPlay() {
|
|
203
|
+
startPlayback()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
override fun onPause() {
|
|
207
|
+
pausePlayback()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
override fun onSkipToNext() {
|
|
211
|
+
sendBroadcast(Intent(ACTION_NEXT))
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
override fun onSkipToPrevious() {
|
|
215
|
+
sendBroadcast(Intent(ACTION_PREVIOUS))
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
override fun onStop() {
|
|
219
|
+
stopPlayback()
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
isActive = true
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private fun updateNotification() {
|
|
227
|
+
scope.launch {
|
|
228
|
+
val notification = buildNotification()
|
|
229
|
+
startForeground(NOTIFICATION_ID, notification)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private suspend fun buildNotification(): Notification {
|
|
234
|
+
// Create pending intents
|
|
235
|
+
val playIntent = createPendingIntent(ACTION_PLAY)
|
|
236
|
+
val pauseIntent = createPendingIntent(ACTION_PAUSE)
|
|
237
|
+
val nextIntent = createPendingIntent(ACTION_NEXT)
|
|
238
|
+
val previousIntent = createPendingIntent(ACTION_PREVIOUS)
|
|
239
|
+
val stopIntent = createPendingIntent(ACTION_STOP)
|
|
240
|
+
|
|
241
|
+
val builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
|
|
242
|
+
.setSmallIcon(R.drawable.ic_music_note)
|
|
243
|
+
.setContentTitle(currentTitle.ifEmpty { "Music Player" })
|
|
244
|
+
.setContentText(currentArtist.ifEmpty { "Unknown Artist" })
|
|
245
|
+
.setSubText(currentAlbum.ifEmpty { "Unknown Album" })
|
|
246
|
+
.setLargeIcon(albumArtBitmap)
|
|
247
|
+
.setStyle(
|
|
248
|
+
MediaNotificationCompat.MediaStyle()
|
|
249
|
+
.setMediaSession(mediaSession?.sessionToken)
|
|
250
|
+
.setShowActionsInCompactView(0, 1, 2)
|
|
251
|
+
)
|
|
252
|
+
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
253
|
+
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
254
|
+
.setOngoing(isPlaying)
|
|
255
|
+
.setShowWhen(false)
|
|
256
|
+
.setAutoCancel(false)
|
|
257
|
+
.setDeleteIntent(stopIntent)
|
|
258
|
+
|
|
259
|
+
// Add actions
|
|
260
|
+
if (isPlaying) {
|
|
261
|
+
builder.addAction(
|
|
262
|
+
R.drawable.ic_pause,
|
|
263
|
+
"Pause",
|
|
264
|
+
pauseIntent
|
|
265
|
+
)
|
|
266
|
+
} else {
|
|
267
|
+
builder.addAction(
|
|
268
|
+
R.drawable.ic_play,
|
|
269
|
+
"Play",
|
|
270
|
+
playIntent
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
builder.addAction(
|
|
275
|
+
R.drawable.ic_skip_previous,
|
|
276
|
+
"Previous",
|
|
277
|
+
previousIntent
|
|
278
|
+
).addAction(
|
|
279
|
+
R.drawable.ic_skip_next,
|
|
280
|
+
"Next",
|
|
281
|
+
nextIntent
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
return builder.build()
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private fun createPendingIntent(action: String): PendingIntent {
|
|
288
|
+
val intent = Intent(action).apply {
|
|
289
|
+
setPackage(packageName)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
293
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
294
|
+
} else {
|
|
295
|
+
PendingIntent.FLAG_UPDATE_CURRENT
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return PendingIntent.getBroadcast(this, action.hashCode(), intent, flags)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private fun cleanup() {
|
|
302
|
+
mediaPlayer?.release()
|
|
303
|
+
mediaPlayer = null
|
|
304
|
+
mediaSession?.release()
|
|
305
|
+
mediaSession = null
|
|
306
|
+
audioManager.abandonAudioFocus(this)
|
|
307
|
+
scope.cancel()
|
|
308
|
+
}
|
|
309
|
+
}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#include <jni.h>
|
|
2
|
+
#include <string>
|
|
3
|
+
#include <fbjni/fbjni.h>
|
|
4
|
+
#include <ReactCommon/TurboModuleManagerDelegate.h>
|
|
5
|
+
#include <ReactCommon/CallInvokerHolder.h>
|
|
6
|
+
|
|
7
|
+
#include "Mp3TurboModule.h"
|
|
8
|
+
|
|
9
|
+
using namespace facebook;
|
|
10
|
+
using namespace facebook::react;
|
|
11
|
+
|
|
12
|
+
// JNI Methods
|
|
13
|
+
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
|
|
14
|
+
return jni::initialize(vm, [] {
|
|
15
|
+
Mp3TurboModule::registerNatives();
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Module registration
|
|
20
|
+
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
|
21
|
+
JNIEnv* env;
|
|
22
|
+
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
|
|
23
|
+
return JNI_ERR;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Register your native methods here
|
|
27
|
+
|
|
28
|
+
return JNI_VERSION_1_6;
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:width="24dp"
|
|
4
|
+
android:height="24dp"
|
|
5
|
+
android:viewportWidth="24"
|
|
6
|
+
android:viewportHeight="24">
|
|
7
|
+
|
|
8
|
+
<path
|
|
9
|
+
android:fillColor="#FFFFFF"
|
|
10
|
+
android:pathData="M12,3L12,12.26C11.5,12.09 11,12 10.5,12C8,12 6,14 6,16.5S8,21 10.5,21 15,19 15,16.5V6h4V3H12z"/>
|
|
11
|
+
</vector>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:width="24dp"
|
|
4
|
+
android:height="24dp"
|
|
5
|
+
android:viewportWidth="24"
|
|
6
|
+
android:viewportHeight="24">
|
|
7
|
+
|
|
8
|
+
<path
|
|
9
|
+
android:fillColor="#FFFFFF"
|
|
10
|
+
android:pathData="M6,19h4V5H6V19zM14,5v14h4V5H14z"/>
|
|
11
|
+
</vector>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:width="24dp"
|
|
4
|
+
android:height="24dp"
|
|
5
|
+
android:viewportWidth="24"
|
|
6
|
+
android:viewportHeight="24">
|
|
7
|
+
|
|
8
|
+
<path
|
|
9
|
+
android:fillColor="#FFFFFF"
|
|
10
|
+
android:pathData="M8,5.14V19.14L19,12.14L8,5.14Z"/>
|
|
11
|
+
</vector>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:width="24dp"
|
|
4
|
+
android:height="24dp"
|
|
5
|
+
android:viewportWidth="24"
|
|
6
|
+
android:viewportHeight="24">
|
|
7
|
+
|
|
8
|
+
<path
|
|
9
|
+
android:fillColor="#FFFFFF"
|
|
10
|
+
android:pathData="M6,18l8.5-6L6,6v12zM16,6v12h2V6h-2z"/>
|
|
11
|
+
</vector>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:width="24dp"
|
|
4
|
+
android:height="24dp"
|
|
5
|
+
android:viewportWidth="24"
|
|
6
|
+
android:viewportHeight="24">
|
|
7
|
+
|
|
8
|
+
<path
|
|
9
|
+
android:fillColor="#FFFFFF"
|
|
10
|
+
android:pathData="M6,6h2v12H6zm3.5,6l8.5,6V6z"/>
|
|
11
|
+
</vector>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
android:width="24dp"
|
|
4
|
+
android:height="24dp"
|
|
5
|
+
android:viewportWidth="24"
|
|
6
|
+
android:viewportHeight="24">
|
|
7
|
+
|
|
8
|
+
<path
|
|
9
|
+
android:fillColor="#FFFFFF"
|
|
10
|
+
android:pathData="M6,6h12v12H6z"/>
|
|
11
|
+
</vector>
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Song, PlaybackState, PlayerOptions } from '../types/common.types';
|
|
2
|
+
interface UseMusicPlayerProps {
|
|
3
|
+
autoSetup?: boolean;
|
|
4
|
+
playerOptions?: PlayerOptions;
|
|
5
|
+
}
|
|
6
|
+
interface UseMusicPlayerReturn {
|
|
7
|
+
playbackState: PlaybackState;
|
|
8
|
+
currentSong: Song | null;
|
|
9
|
+
queue: Song[];
|
|
10
|
+
isPlaying: boolean;
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
error: string | null;
|
|
13
|
+
play: (uri: string) => Promise<void>;
|
|
14
|
+
playSong: (song: Song) => Promise<void>;
|
|
15
|
+
playFromQueue: (index: number) => void;
|
|
16
|
+
pause: () => void;
|
|
17
|
+
stop: () => void;
|
|
18
|
+
seekTo: (position: number) => void;
|
|
19
|
+
skipToNext: () => void;
|
|
20
|
+
skipToPrevious: () => void;
|
|
21
|
+
setVolume: (volume: number) => void;
|
|
22
|
+
setPlaybackRate: (rate: number) => void;
|
|
23
|
+
setQueue: (songs: Song[]) => void;
|
|
24
|
+
addToQueue: (songs: Song[]) => void;
|
|
25
|
+
clearQueue: () => void;
|
|
26
|
+
getQueue: () => Promise<Song[]>;
|
|
27
|
+
setRepeatMode: (mode: 'none' | 'one' | 'all') => void;
|
|
28
|
+
setShuffleMode: (enabled: boolean) => void;
|
|
29
|
+
setEqualizerPreset: (preset: string) => void;
|
|
30
|
+
setEqualizerBands: (bands: number[]) => void;
|
|
31
|
+
enableEqualizer: (enabled: boolean) => void;
|
|
32
|
+
setupBackgroundPlayback: (config?: any) => void;
|
|
33
|
+
stopBackgroundPlayback: () => void;
|
|
34
|
+
setSleepTimer: (minutes: number) => void;
|
|
35
|
+
cancelSleepTimer: () => void;
|
|
36
|
+
}
|
|
37
|
+
export declare const useMusicPlayer: ({ autoSetup, playerOptions, }?: UseMusicPlayerProps) => UseMusicPlayerReturn;
|
|
38
|
+
export {};
|