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.
Files changed (45) hide show
  1. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridAudioDevices.kt +5 -3
  2. package/android/src/main/java/com/margelo/nitro/nitroplayer/HybridTrackPlayer.kt +4 -0
  3. package/android/src/main/java/com/margelo/nitro/nitroplayer/connection/AndroidAutoConnectionDetector.kt +14 -13
  4. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/NitroPlayerLogger.kt +31 -0
  5. package/android/src/main/java/com/margelo/nitro/nitroplayer/core/TrackPlayerCore.kt +142 -95
  6. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadDatabase.kt +75 -29
  7. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadManagerCore.kt +2 -1
  8. package/android/src/main/java/com/margelo/nitro/nitroplayer/download/DownloadWorker.kt +1 -2
  9. package/android/src/main/java/com/margelo/nitro/nitroplayer/equalizer/EqualizerCore.kt +3 -2
  10. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaBrowserService.kt +25 -24
  11. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaLibraryManager.kt +3 -2
  12. package/android/src/main/java/com/margelo/nitro/nitroplayer/media/MediaSessionManager.kt +20 -19
  13. package/android/src/main/java/com/margelo/nitro/nitroplayer/playlist/PlaylistManager.kt +119 -85
  14. package/android/src/main/java/com/margelo/nitro/nitroplayer/storage/NitroPlayerStorage.kt +50 -0
  15. package/ios/HybridAudioRoutePicker.swift +1 -1
  16. package/ios/HybridDownloadManager.swift +3 -3
  17. package/ios/HybridEqualizer.swift +3 -3
  18. package/ios/HybridTrackPlayer.swift +8 -4
  19. package/ios/core/NitroPlayerLogger.swift +22 -0
  20. package/ios/core/TrackPlayerCore.swift +195 -256
  21. package/ios/download/DownloadDatabase.swift +92 -62
  22. package/ios/download/DownloadFileManager.swift +17 -17
  23. package/ios/download/DownloadManagerCore.swift +80 -44
  24. package/ios/equalizer/EqualizerCore.swift +25 -20
  25. package/ios/playlist/PlaylistManager.swift +113 -82
  26. package/ios/queue/QueueManager.swift +1 -1
  27. package/ios/storage/NitroPlayerStorage.swift +44 -0
  28. package/lib/specs/TrackPlayer.nitro.d.ts +1 -0
  29. package/lib/types/PlayerQueue.d.ts +1 -1
  30. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.cpp +5 -0
  31. package/nitrogen/generated/android/c++/JHybridTrackPlayerSpec.hpp +1 -0
  32. package/nitrogen/generated/android/c++/JReason.hpp +3 -0
  33. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/HybridTrackPlayerSpec.kt +4 -0
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroplayer/Reason.kt +2 -1
  35. package/nitrogen/generated/ios/NitroPlayer-Swift-Cxx-Bridge.hpp +12 -0
  36. package/nitrogen/generated/ios/c++/HybridTrackPlayerSpecSwift.hpp +8 -0
  37. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec.swift +1 -0
  38. package/nitrogen/generated/ios/swift/HybridTrackPlayerSpec_cxx.swift +12 -0
  39. package/nitrogen/generated/ios/swift/Reason.swift +4 -0
  40. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.cpp +1 -0
  41. package/nitrogen/generated/shared/c++/HybridTrackPlayerSpec.hpp +1 -0
  42. package/nitrogen/generated/shared/c++/Reason.hpp +4 -0
  43. package/package.json +1 -1
  44. package/src/specs/TrackPlayer.nitro.ts +1 -0
  45. 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 android.content.SharedPreferences
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 sharedPreferences: SharedPreferences =
31
- context.getSharedPreferences("NitroPlayerPlaylists", Context.MODE_PRIVATE)
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 preferences on init - only load when Android Auto needs it
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
- savePlaylistsToPreferences()
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
- savePlaylistsToPreferences()
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
- savePlaylistsToPreferences()
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
- savePlaylistsToPreferences()
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
- savePlaylistsToPreferences()
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
- savePlaylistsToPreferences()
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
- savePlaylistsToPreferences()
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
- private fun savePlaylistsToPreferences() {
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
- sharedPreferences
402
- .edit()
403
- .putString("playlists", jsonArray.toString())
404
- .putString("currentPlaylistId", currentPlaylistId)
405
- .apply()
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
- private fun loadPlaylistsFromPreferences() {
412
- try {
413
- val jsonString = sharedPreferences.getString("playlists", null)
414
- if (jsonString != null) {
415
- val jsonArray = JSONArray(jsonString)
416
- synchronized(playlists) {
417
- playlists.clear()
418
- for (i in 0 until jsonArray.length()) {
419
- val jsonObject = jsonArray.getJSONObject(i)
420
- val tracks = mutableListOf<TrackItem>()
421
- val tracksArray = jsonObject.getJSONArray("tracks")
422
- for (j in 0 until tracksArray.length()) {
423
- val trackObj = tracksArray.getJSONObject(j)
424
- val artworkStr = trackObj.optString("artwork")
425
- val artwork: Variant_NullType_String? =
426
- if (!artworkStr.isNullOrEmpty()) {
427
- Variant_NullType_String.create(artworkStr)
428
- } else {
429
- null
430
- }
431
- // Deserialize extraPayload from JSON
432
- val extraPayload: AnyMap? =
433
- if (trackObj.has("extraPayload")) {
434
- val extraPayloadJson = trackObj.getJSONObject("extraPayload")
435
- val map = AnyMap()
436
- val keyIterator = extraPayloadJson.keys()
437
- while (keyIterator.hasNext()) {
438
- val key = keyIterator.next()
439
- when (val value = extraPayloadJson.get(key)) {
440
- is String -> map.setString(key, value)
441
- is Number -> map.setDouble(key, value.toDouble())
442
- is Boolean -> map.setBoolean(key, value)
443
- }
444
- }
445
- map
446
- } else {
447
- null
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
- tracks.add(
450
- TrackItem(
451
- id = trackObj.getString("id"),
452
- title = trackObj.getString("title"),
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
- val descriptionStr = jsonObject.optString("description")
463
- val artworkStr = jsonObject.optString("artwork")
464
- val playlist =
465
- Playlist(
466
- id = jsonObject.getString("id"),
467
- name = jsonObject.getString("name"),
468
- description = if (!descriptionStr.isNullOrEmpty()) descriptionStr else null,
469
- artwork = if (!artworkStr.isNullOrEmpty()) artworkStr else null,
470
- tracks = tracks,
471
- )
472
- playlists[playlist.id] = playlist
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
- currentPlaylistId = sharedPreferences.getString("currentPlaylistId", null)
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
- print("HybridAudioRoutePicker: Could not find key window")
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
- print("🎯 HybridDownloadManager: onDownloadProgress callback registered")
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
- print("🎯 HybridDownloadManager: onDownloadStateChange callback registered")
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
- print("🎯 HybridDownloadManager: onDownloadComplete callback registered")
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
- print("🎯 HybridEqualizer: onEnabledChange callback registered")
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
- print("🎯 HybridEqualizer: onBandChange callback registered")
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
- print("🎯 HybridEqualizer: onPresetChange callback registered")
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
- print("🎯 HybridTrackPlayer: onChangeTrack callback registered")
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
- print("🎯 HybridTrackPlayer: onPlaybackStateChange callback registered")
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
- print("🎯 HybridTrackPlayer: onSeek callback registered")
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
- print("🎯 HybridTrackPlayer: onPlaybackProgressChange callback registered")
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
+ }