react-native-nitro-player 0.5.3 → 0.5.5
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/HybridAudioDevices.kt +5 -3
- package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +4 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/connection/AndroidAutoConnectionDetector.kt +14 -13
- package/android/src/main/java/com/margelo/nitro/nitroplayer/core/NitroPlayerLogger.kt +31 -0
- package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +142 -95
- package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +75 -29
- package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadManagerCore.kt +2 -1
- package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadWorker.kt +1 -2
- package/android/src/main/java/com/margelo/nitro/nitroplayer/equalizer/EqualizerCore.kt +3 -2
- package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaBrowserService.kt +25 -24
- package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaLibraryManager.kt +3 -2
- package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +20 -19
- package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +119 -85
- package/android/src/main/java/com/margelo/nitro/nitroplayer/storage/NitroPlayerStorage.kt +50 -0
- package/ios/HybridAudioRoutePicker.swift +1 -1
- package/ios/HybridDownloadManager.swift +3 -3
- package/ios/HybridEqualizer.swift +3 -3
- package/ios/HybridTrackPlayer.swift +8 -4
- package/ios/core/NitroPlayerLogger.swift +22 -0
- package/ios/core/TrackPlayerCore.swift +195 -256
- package/ios/download/DownloadDatabase.swift +92 -62
- package/ios/download/DownloadFileManager.swift +17 -17
- package/ios/download/DownloadManagerCore.swift +80 -44
- package/ios/equalizer/EqualizerCore.swift +25 -20
- package/ios/playlist/PlaylistManager.swift +113 -82
- package/ios/queue/QueueManager.swift +1 -1
- package/ios/storage/NitroPlayerStorage.swift +44 -0
- package/lib/specs/TrackPlayer.nitro.d.ts +1 -0
- package/lib/types/PlayerQueue.d.ts +1 -1
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +5 -0
- package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +1 -0
- package/nitrogen/generated/android/c++/JReason.hpp +3 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +4 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Reason.kt +2 -1
- package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +12 -0
- package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +8 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +12 -0
- package/nitrogen/generated/ios/swift/Reason.swift +4 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +1 -0
- package/nitrogen/generated/shared/c++/Reason.hpp +4 -0
- package/package.json +1 -1
- package/src/specs/TrackPlayer.nitro.ts +1 -0
- package/src/types/PlayerQueue.ts +1 -1
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
package com.margelo.nitro.nitroplayer.playlist
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
-
import
|
|
5
|
-
import com.margelo.nitro.core.NullType
|
|
4
|
+
import com.margelo.nitro.core.AnyMap
|
|
6
5
|
import com.margelo.nitro.nitroplayer.QueueOperation
|
|
7
6
|
import com.margelo.nitro.nitroplayer.TrackItem
|
|
8
7
|
import com.margelo.nitro.nitroplayer.Variant_NullType_String
|
|
9
8
|
import com.margelo.nitro.nitroplayer.core.TrackPlayerCore
|
|
10
9
|
import com.margelo.nitro.nitroplayer.media.NitroPlayerMediaBrowserService
|
|
10
|
+
import com.margelo.nitro.nitroplayer.storage.NitroPlayerStorage
|
|
11
11
|
import org.json.JSONArray
|
|
12
12
|
import org.json.JSONObject
|
|
13
13
|
import java.util.UUID
|
|
14
14
|
import java.util.concurrent.CopyOnWriteArrayList
|
|
15
15
|
|
|
16
|
-
import com.margelo.nitro.core.AnyMap
|
|
17
|
-
|
|
18
16
|
/**
|
|
19
17
|
* Manages multiple playlists using ExoPlayer's native playlist functionality
|
|
20
18
|
* Based on: https://developer.android.com/media/media3/exoplayer/playlists
|
|
@@ -27,14 +25,22 @@ class PlaylistManager private constructor(
|
|
|
27
25
|
private val playlistListeners = mutableMapOf<String, CopyOnWriteArrayList<(Playlist, QueueOperation?) -> Unit>>()
|
|
28
26
|
private var currentPlaylistId: String? = null
|
|
29
27
|
|
|
30
|
-
private val
|
|
31
|
-
|
|
28
|
+
private val saveHandler = android.os.Handler(android.os.Looper.getMainLooper())
|
|
29
|
+
private val saveRunnable = Runnable { saveToFile() }
|
|
30
|
+
|
|
31
|
+
private fun scheduleSave() {
|
|
32
|
+
saveHandler.removeCallbacks(saveRunnable)
|
|
33
|
+
saveHandler.postDelayed(saveRunnable, 300)
|
|
34
|
+
}
|
|
32
35
|
|
|
33
36
|
companion object {
|
|
34
37
|
@Volatile
|
|
35
38
|
@Suppress("ktlint:standard:property-naming")
|
|
36
39
|
private var INSTANCE: PlaylistManager? = null
|
|
37
40
|
|
|
41
|
+
// Legacy SharedPreferences name (migration only)
|
|
42
|
+
private const val LEGACY_PREFS_NAME = "NitroPlayerPlaylists"
|
|
43
|
+
|
|
38
44
|
@JvmStatic
|
|
39
45
|
fun getInstance(context: Context): PlaylistManager =
|
|
40
46
|
INSTANCE ?: synchronized(this) {
|
|
@@ -43,7 +49,7 @@ class PlaylistManager private constructor(
|
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
init {
|
|
46
|
-
// Don't load from
|
|
52
|
+
// Don't load from file on init - only load when Android Auto needs it
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
/**
|
|
@@ -63,7 +69,7 @@ class PlaylistManager private constructor(
|
|
|
63
69
|
|
|
64
70
|
// Only cache for Android Auto if connected
|
|
65
71
|
if (NitroPlayerMediaBrowserService.isAndroidAutoConnected) {
|
|
66
|
-
|
|
72
|
+
scheduleSave()
|
|
67
73
|
}
|
|
68
74
|
notifyPlaylistsChanged(QueueOperation.ADD)
|
|
69
75
|
NitroPlayerMediaBrowserService.getInstance()?.onPlaylistsUpdated()
|
|
@@ -87,7 +93,7 @@ class PlaylistManager private constructor(
|
|
|
87
93
|
playlistListeners.remove(playlistId)
|
|
88
94
|
// Only cache for Android Auto if connected
|
|
89
95
|
if (NitroPlayerMediaBrowserService.isAndroidAutoConnected) {
|
|
90
|
-
|
|
96
|
+
scheduleSave()
|
|
91
97
|
}
|
|
92
98
|
notifyPlaylistsChanged(QueueOperation.REMOVE)
|
|
93
99
|
NitroPlayerMediaBrowserService.getInstance()?.onPlaylistsUpdated()
|
|
@@ -122,7 +128,7 @@ class PlaylistManager private constructor(
|
|
|
122
128
|
|
|
123
129
|
// Only cache for Android Auto if connected
|
|
124
130
|
if (NitroPlayerMediaBrowserService.isAndroidAutoConnected) {
|
|
125
|
-
|
|
131
|
+
scheduleSave()
|
|
126
132
|
}
|
|
127
133
|
notifyPlaylistChanged(playlistId, QueueOperation.UPDATE)
|
|
128
134
|
notifyPlaylistsChanged(QueueOperation.UPDATE)
|
|
@@ -172,7 +178,7 @@ class PlaylistManager private constructor(
|
|
|
172
178
|
|
|
173
179
|
// Only cache for Android Auto if connected
|
|
174
180
|
if (NitroPlayerMediaBrowserService.isAndroidAutoConnected) {
|
|
175
|
-
|
|
181
|
+
scheduleSave()
|
|
176
182
|
}
|
|
177
183
|
notifyPlaylistChanged(playlistId, QueueOperation.ADD)
|
|
178
184
|
NitroPlayerMediaBrowserService.getInstance()?.onPlaylistUpdated(playlistId)
|
|
@@ -210,7 +216,7 @@ class PlaylistManager private constructor(
|
|
|
210
216
|
|
|
211
217
|
// Only cache for Android Auto if connected
|
|
212
218
|
if (NitroPlayerMediaBrowserService.isAndroidAutoConnected) {
|
|
213
|
-
|
|
219
|
+
scheduleSave()
|
|
214
220
|
}
|
|
215
221
|
notifyPlaylistChanged(playlistId, QueueOperation.ADD)
|
|
216
222
|
NitroPlayerMediaBrowserService.getInstance()?.onPlaylistUpdated(playlistId)
|
|
@@ -246,7 +252,7 @@ class PlaylistManager private constructor(
|
|
|
246
252
|
}
|
|
247
253
|
|
|
248
254
|
if (removed) {
|
|
249
|
-
|
|
255
|
+
scheduleSave()
|
|
250
256
|
notifyPlaylistChanged(playlistId, QueueOperation.REMOVE)
|
|
251
257
|
NitroPlayerMediaBrowserService.getInstance()?.onPlaylistUpdated(playlistId)
|
|
252
258
|
|
|
@@ -284,7 +290,7 @@ class PlaylistManager private constructor(
|
|
|
284
290
|
playlists[playlistId] = playlist.copy(tracks = tracks)
|
|
285
291
|
}
|
|
286
292
|
|
|
287
|
-
|
|
293
|
+
scheduleSave()
|
|
288
294
|
notifyPlaylistChanged(playlistId, QueueOperation.UPDATE)
|
|
289
295
|
NitroPlayerMediaBrowserService.getInstance()?.onPlaylistUpdated(playlistId)
|
|
290
296
|
|
|
@@ -361,7 +367,9 @@ class PlaylistManager private constructor(
|
|
|
361
367
|
playlistListeners[playlistId]?.forEach { it(playlist, operation) }
|
|
362
368
|
}
|
|
363
369
|
|
|
364
|
-
|
|
370
|
+
// MARK: - Persistence
|
|
371
|
+
|
|
372
|
+
private fun saveToFile() {
|
|
365
373
|
try {
|
|
366
374
|
val jsonArray = JSONArray()
|
|
367
375
|
synchronized(playlists) {
|
|
@@ -383,7 +391,6 @@ class PlaylistManager private constructor(
|
|
|
383
391
|
put("duration", track.duration)
|
|
384
392
|
put("url", track.url)
|
|
385
393
|
track.artwork?.let { put("artwork", it) }
|
|
386
|
-
// Serialize extraPayload to JSON for persistence
|
|
387
394
|
track.extraPayload?.let { payload ->
|
|
388
395
|
val extraPayloadMap = payload.toHashMap()
|
|
389
396
|
val extraPayloadJson = JSONObject(extraPayloadMap)
|
|
@@ -398,84 +405,111 @@ class PlaylistManager private constructor(
|
|
|
398
405
|
}
|
|
399
406
|
}
|
|
400
407
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
408
|
+
val wrapper = JSONObject().apply {
|
|
409
|
+
put("playlists", jsonArray)
|
|
410
|
+
put("currentPlaylistId", currentPlaylistId)
|
|
411
|
+
}
|
|
412
|
+
NitroPlayerStorage.write(context, "playlists.json", wrapper.toString())
|
|
406
413
|
} catch (e: Exception) {
|
|
407
414
|
e.printStackTrace()
|
|
408
415
|
}
|
|
409
416
|
}
|
|
410
417
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
418
|
+
fun loadPlaylistsFromFile() {
|
|
419
|
+
// 1. Try new JSON file (post-migration)
|
|
420
|
+
val json = NitroPlayerStorage.read(context, "playlists.json")
|
|
421
|
+
if (json != null) {
|
|
422
|
+
try {
|
|
423
|
+
val wrapper = JSONObject(json)
|
|
424
|
+
val jsonArray = wrapper.optJSONArray("playlists") ?: JSONArray()
|
|
425
|
+
parseAndLoadPlaylists(jsonArray)
|
|
426
|
+
currentPlaylistId = if (wrapper.isNull("currentPlaylistId")) null
|
|
427
|
+
else wrapper.optString("currentPlaylistId", null.toString()).takeIf { it != "null" }
|
|
428
|
+
} catch (e: Exception) {
|
|
429
|
+
e.printStackTrace()
|
|
430
|
+
}
|
|
431
|
+
return
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// 2. Migrate from SharedPreferences (one-time, existing installs)
|
|
435
|
+
val prefs = context.getSharedPreferences(LEGACY_PREFS_NAME, Context.MODE_PRIVATE)
|
|
436
|
+
val legacyJson = prefs.getString("playlists", null)
|
|
437
|
+
if (legacyJson != null) {
|
|
438
|
+
try {
|
|
439
|
+
val jsonArray = JSONArray(legacyJson)
|
|
440
|
+
parseAndLoadPlaylists(jsonArray)
|
|
441
|
+
currentPlaylistId = prefs.getString("currentPlaylistId", null)
|
|
442
|
+
// Remove old SharedPreferences data to free space
|
|
443
|
+
prefs.edit().remove("playlists").remove("currentPlaylistId").apply()
|
|
444
|
+
// Persist in new format
|
|
445
|
+
saveToFile()
|
|
446
|
+
} catch (e: Exception) {
|
|
447
|
+
e.printStackTrace()
|
|
448
|
+
}
|
|
449
|
+
return
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// 3. Fresh install — nothing to load
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
private fun parseAndLoadPlaylists(jsonArray: JSONArray) {
|
|
456
|
+
synchronized(playlists) {
|
|
457
|
+
playlists.clear()
|
|
458
|
+
for (i in 0 until jsonArray.length()) {
|
|
459
|
+
val jsonObject = jsonArray.getJSONObject(i)
|
|
460
|
+
val tracks = mutableListOf<TrackItem>()
|
|
461
|
+
val tracksArray = jsonObject.getJSONArray("tracks")
|
|
462
|
+
for (j in 0 until tracksArray.length()) {
|
|
463
|
+
val trackObj = tracksArray.getJSONObject(j)
|
|
464
|
+
val artworkStr = trackObj.optString("artwork")
|
|
465
|
+
val artwork: Variant_NullType_String? =
|
|
466
|
+
if (!artworkStr.isNullOrEmpty()) {
|
|
467
|
+
Variant_NullType_String.create(artworkStr)
|
|
468
|
+
} else {
|
|
469
|
+
null
|
|
470
|
+
}
|
|
471
|
+
val extraPayload: AnyMap? =
|
|
472
|
+
if (trackObj.has("extraPayload")) {
|
|
473
|
+
val extraPayloadJson = trackObj.getJSONObject("extraPayload")
|
|
474
|
+
val map = AnyMap()
|
|
475
|
+
val keyIterator = extraPayloadJson.keys()
|
|
476
|
+
while (keyIterator.hasNext()) {
|
|
477
|
+
val key = keyIterator.next()
|
|
478
|
+
when (val value = extraPayloadJson.get(key)) {
|
|
479
|
+
is String -> map.setString(key, value)
|
|
480
|
+
is Number -> map.setDouble(key, value.toDouble())
|
|
481
|
+
is Boolean -> map.setBoolean(key, value)
|
|
448
482
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
artist = trackObj.getString("artist"),
|
|
454
|
-
album = trackObj.getString("album"),
|
|
455
|
-
duration = trackObj.getDouble("duration"),
|
|
456
|
-
url = trackObj.getString("url"),
|
|
457
|
-
artwork = artwork,
|
|
458
|
-
extraPayload = extraPayload,
|
|
459
|
-
),
|
|
460
|
-
)
|
|
483
|
+
}
|
|
484
|
+
map
|
|
485
|
+
} else {
|
|
486
|
+
null
|
|
461
487
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
488
|
+
tracks.add(
|
|
489
|
+
TrackItem(
|
|
490
|
+
id = trackObj.getString("id"),
|
|
491
|
+
title = trackObj.getString("title"),
|
|
492
|
+
artist = trackObj.getString("artist"),
|
|
493
|
+
album = trackObj.getString("album"),
|
|
494
|
+
duration = trackObj.getDouble("duration"),
|
|
495
|
+
url = trackObj.getString("url"),
|
|
496
|
+
artwork = artwork,
|
|
497
|
+
extraPayload = extraPayload,
|
|
498
|
+
),
|
|
499
|
+
)
|
|
474
500
|
}
|
|
475
|
-
|
|
501
|
+
val descriptionStr = jsonObject.optString("description")
|
|
502
|
+
val artworkStr = jsonObject.optString("artwork")
|
|
503
|
+
val playlist =
|
|
504
|
+
Playlist(
|
|
505
|
+
id = jsonObject.getString("id"),
|
|
506
|
+
name = jsonObject.getString("name"),
|
|
507
|
+
description = if (!descriptionStr.isNullOrEmpty()) descriptionStr else null,
|
|
508
|
+
artwork = if (!artworkStr.isNullOrEmpty()) artworkStr else null,
|
|
509
|
+
tracks = tracks,
|
|
510
|
+
)
|
|
511
|
+
playlists[playlist.id] = playlist
|
|
476
512
|
}
|
|
477
|
-
} catch (e: Exception) {
|
|
478
|
-
e.printStackTrace()
|
|
479
513
|
}
|
|
480
514
|
}
|
|
481
515
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
package com.margelo.nitro.nitroplayer.storage
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.margelo.nitro.nitroplayer.core.NitroPlayerLogger
|
|
5
|
+
import java.io.File
|
|
6
|
+
|
|
7
|
+
object NitroPlayerStorage {
|
|
8
|
+
private const val TAG = "NitroPlayerStorage"
|
|
9
|
+
private const val DIR_NAME = "nitroplayer"
|
|
10
|
+
|
|
11
|
+
/** Reads the contents of [filename] from the NitroPlayer storage directory, or null if absent. */
|
|
12
|
+
fun read(context: Context, filename: String): String? {
|
|
13
|
+
val file = File(storageDirectory(context), filename)
|
|
14
|
+
return if (file.exists()) {
|
|
15
|
+
try {
|
|
16
|
+
file.readText()
|
|
17
|
+
} catch (e: Exception) {
|
|
18
|
+
NitroPlayerLogger.log(TAG, "read($filename) failed: $e")
|
|
19
|
+
null
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
null
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Atomically writes [json] to [filename] in the NitroPlayer storage directory.
|
|
28
|
+
* Writes to `<filename>.tmp` first, then renames — leaving the prior file
|
|
29
|
+
* untouched on failure (crash-safe).
|
|
30
|
+
*/
|
|
31
|
+
fun write(context: Context, filename: String, json: String) {
|
|
32
|
+
try {
|
|
33
|
+
val dir = storageDirectory(context)
|
|
34
|
+
dir.mkdirs()
|
|
35
|
+
val tmp = File(dir, "$filename.tmp")
|
|
36
|
+
val dest = File(dir, filename)
|
|
37
|
+
tmp.writeText(json)
|
|
38
|
+
if (!tmp.renameTo(dest)) {
|
|
39
|
+
// renameTo can fail across mount points; copy then delete as fallback
|
|
40
|
+
dest.writeText(tmp.readText())
|
|
41
|
+
tmp.delete()
|
|
42
|
+
}
|
|
43
|
+
} catch (e: Exception) {
|
|
44
|
+
NitroPlayerLogger.log(TAG, "write($filename) failed: $e")
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Returns the NitroPlayer subdirectory inside filesDir. */
|
|
49
|
+
private fun storageDirectory(context: Context): File = File(context.filesDir, DIR_NAME)
|
|
50
|
+
}
|
|
@@ -30,7 +30,7 @@ class HybridAudioRoutePicker: HybridAudioRoutePickerSpec {
|
|
|
30
30
|
.flatMap({ $0.windows })
|
|
31
31
|
.first(where: { $0.isKeyWindow })
|
|
32
32
|
else {
|
|
33
|
-
|
|
33
|
+
NitroPlayerLogger.log("HybridAudioRoutePicker", "Could not find key window")
|
|
34
34
|
return
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -208,19 +208,19 @@ final class HybridDownloadManager: HybridDownloadManagerSpec {
|
|
|
208
208
|
// MARK: - Event Callbacks
|
|
209
209
|
|
|
210
210
|
func onDownloadProgress(callback: @escaping (DownloadProgress) -> Void) throws {
|
|
211
|
-
|
|
211
|
+
NitroPlayerLogger.log("HybridDownloadManager", "onDownloadProgress callback registered")
|
|
212
212
|
core.addProgressCallback(callback)
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
func onDownloadStateChange(
|
|
216
216
|
callback: @escaping (String, String, DownloadState, DownloadError?) -> Void
|
|
217
217
|
) throws {
|
|
218
|
-
|
|
218
|
+
NitroPlayerLogger.log("HybridDownloadManager", "onDownloadStateChange callback registered")
|
|
219
219
|
core.addStateChangeCallback(callback)
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
func onDownloadComplete(callback: @escaping (DownloadedTrack) -> Void) throws {
|
|
223
|
-
|
|
223
|
+
NitroPlayerLogger.log("HybridDownloadManager", "onDownloadComplete callback registered")
|
|
224
224
|
core.addCompleteCallback(callback)
|
|
225
225
|
}
|
|
226
226
|
}
|
|
@@ -95,17 +95,17 @@ final class HybridEqualizer: HybridEqualizerSpec {
|
|
|
95
95
|
// MARK: - Event Callbacks
|
|
96
96
|
|
|
97
97
|
func onEnabledChange(callback: @escaping (Bool) -> Void) throws {
|
|
98
|
-
|
|
98
|
+
NitroPlayerLogger.log("HybridEqualizer", "onEnabledChange callback registered")
|
|
99
99
|
core.addOnEnabledChangeListener(owner: self, callback)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
func onBandChange(callback: @escaping ([EqualizerBand]) -> Void) throws {
|
|
103
|
-
|
|
103
|
+
NitroPlayerLogger.log("HybridEqualizer", "onBandChange callback registered")
|
|
104
104
|
core.addOnBandChangeListener(owner: self, callback)
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
func onPresetChange(callback: @escaping (Variant_NullType_String?) -> Void) throws {
|
|
108
|
-
|
|
108
|
+
NitroPlayerLogger.log("HybridEqualizer", "onPresetChange callback registered")
|
|
109
109
|
core.addOnPresetChangeListener(owner: self, callback)
|
|
110
110
|
}
|
|
111
111
|
}
|
|
@@ -78,6 +78,10 @@ final class HybridTrackPlayer: HybridTrackPlayerSpec {
|
|
|
78
78
|
return core.setRepeatMode(mode: mode)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
func getRepeatMode() throws -> RepeatMode {
|
|
82
|
+
return core.getRepeatMode()
|
|
83
|
+
}
|
|
84
|
+
|
|
81
85
|
// MARK: - Configuration
|
|
82
86
|
|
|
83
87
|
func configure(config: PlayerConfig) throws {
|
|
@@ -91,22 +95,22 @@ final class HybridTrackPlayer: HybridTrackPlayerSpec {
|
|
|
91
95
|
// MARK: - Event Callbacks
|
|
92
96
|
|
|
93
97
|
func onChangeTrack(callback: @escaping (TrackItem, Reason?) -> Void) throws {
|
|
94
|
-
|
|
98
|
+
NitroPlayerLogger.log("HybridTrackPlayer", "onChangeTrack callback registered")
|
|
95
99
|
core.addOnChangeTrackListener(owner: self, callback)
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
func onPlaybackStateChange(callback: @escaping (TrackPlayerState, Reason?) -> Void) throws {
|
|
99
|
-
|
|
103
|
+
NitroPlayerLogger.log("HybridTrackPlayer", "onPlaybackStateChange callback registered")
|
|
100
104
|
core.addOnPlaybackStateChangeListener(owner: self, callback)
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
func onSeek(callback: @escaping (Double, Double) -> Void) throws {
|
|
104
|
-
|
|
108
|
+
NitroPlayerLogger.log("HybridTrackPlayer", "onSeek callback registered")
|
|
105
109
|
core.addOnSeekListener(owner: self, callback)
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
func onPlaybackProgressChange(callback: @escaping (Double, Double, Bool?) -> Void) throws {
|
|
109
|
-
|
|
113
|
+
NitroPlayerLogger.log("HybridTrackPlayer", "onPlaybackProgressChange callback registered")
|
|
110
114
|
core.addOnPlaybackProgressChangeListener(owner: self, callback)
|
|
111
115
|
}
|
|
112
116
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Logger.swift
|
|
3
|
+
// NitroPlayer
|
|
4
|
+
//
|
|
5
|
+
// Created by Ritesh Shukla on 18/02/26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
class NitroPlayerLogger {
|
|
11
|
+
#if DEBUG
|
|
12
|
+
static var isEnabled = true
|
|
13
|
+
#else
|
|
14
|
+
static var isEnabled = false
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
static func log(_ header: String = "NitroPlayer", _ message: @autoclosure () -> String) {
|
|
18
|
+
if isEnabled {
|
|
19
|
+
print("[\(header)] \(message())")
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|