@javascriptcommon/react-native-track-player 1.2.9 → 1.2.24

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 (131) hide show
  1. package/android/build.gradle +61 -4
  2. package/android/src/main/AndroidManifest.xml +2 -4
  3. package/android/src/main/ic_home-playstore.png +0 -0
  4. package/android/src/main/ic_repeat-playstore.png +0 -0
  5. package/android/src/main/ic_repeat_50-playstore.png +0 -0
  6. package/android/src/main/ic_shuffle-playstore.png +0 -0
  7. package/android/src/main/ic_shuffle_50-playstore.png +0 -0
  8. package/android/src/main/ic_shuffle_sm-playstore.png +0 -0
  9. package/android/src/main/ic_stop-playstore.png +0 -0
  10. package/android/src/main/ic_test-playstore.png +0 -0
  11. package/android/src/main/java/com/guichaguri/trackplayer/{service/HeadlessJsMediaService.java → HeadlessJsMediaService.java} +83 -32
  12. package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.kt +25 -0
  13. package/android/src/main/java/com/guichaguri/trackplayer/extensions/AudioPlayerStateExt.kt +19 -0
  14. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/EventHolder.kt +30 -0
  15. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/NotificationEventHolder.kt +20 -0
  16. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/PlayerEventHolder.kt +111 -0
  17. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AAMediaSessionCallback.kt +10 -0
  18. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioContentType.kt +10 -0
  19. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItem.kt +66 -0
  20. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItemTransitionReason.kt +33 -0
  21. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioPlayerState.kt +30 -0
  22. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/BufferConfig.kt +8 -0
  23. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/CacheConfig.kt +17 -0
  24. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/Capability.kt +19 -0
  25. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/FocusChangeData.kt +3 -0
  26. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/MediaSessionCallback.kt +17 -0
  27. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationConfig.kt +43 -0
  28. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationMetadata.kt +8 -0
  29. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationState.kt +8 -0
  30. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayWhenReadyChangeData.kt +5 -0
  31. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackEndedReason.kt +5 -0
  32. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackError.kt +6 -0
  33. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackMetadata.kt +200 -0
  34. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerConfig.kt +33 -0
  35. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerOptions.kt +9 -0
  36. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PositionChangedReason.kt +39 -0
  37. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/QueuedPlayerOptions.kt +49 -0
  38. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/notification/NotificationManager.kt +678 -0
  39. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/AudioPlayer.kt +10 -0
  40. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/BaseAudioPlayer.kt +864 -0
  41. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/QueuedAudioPlayer.kt +269 -0
  42. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/MediaSourceExt.kt +35 -0
  43. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/PlayerCache.kt +26 -0
  44. package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/utils/Utils.kt +12 -0
  45. package/android/src/main/java/com/guichaguri/trackplayer/model/MetadataAdapter.kt +224 -0
  46. package/android/src/main/java/com/guichaguri/trackplayer/model/State.kt +13 -0
  47. package/android/src/main/java/com/guichaguri/trackplayer/model/Track.kt +120 -0
  48. package/android/src/main/java/com/guichaguri/trackplayer/model/TrackAudioItem.kt +19 -0
  49. package/android/src/main/java/com/guichaguri/trackplayer/model/TrackType.kt +11 -0
  50. package/android/src/main/java/com/guichaguri/trackplayer/module/AutoConnectionDetector.kt +151 -0
  51. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.kt +66 -0
  52. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.kt +1192 -0
  53. package/android/src/main/java/com/guichaguri/trackplayer/service/BundleUtils.kt +117 -0
  54. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.kt +31 -0
  55. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.kt +347 -0
  56. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.kt +1268 -0
  57. package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.kt +228 -0
  58. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.kt +141 -0
  59. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.kt +396 -0
  60. package/android/src/main/res/drawable-hdpi/ic_home.png +0 -0
  61. package/android/src/main/res/drawable-mdpi/ic_home.png +0 -0
  62. package/android/src/main/res/drawable-xhdpi/ic_home.png +0 -0
  63. package/android/src/main/res/drawable-xxhdpi/ic_home.png +0 -0
  64. package/android/src/main/res/drawable-xxxhdpi/ic_home.png +0 -0
  65. package/android/src/main/res/mipmap-hdpi/ic_arrow_down_circle_foreground.png +0 -0
  66. package/android/src/main/res/mipmap-hdpi/ic_clock_now_foreground.png +0 -0
  67. package/android/src/main/res/mipmap-hdpi/ic_close_foreground.png +0 -0
  68. package/android/src/main/res/mipmap-hdpi/ic_heart_foreground.png +0 -0
  69. package/android/src/main/res/mipmap-hdpi/ic_heart_outlined_foreground.png +0 -0
  70. package/android/src/main/res/mipmap-hdpi/ic_repeat_off_foreground.png +0 -0
  71. package/android/src/main/res/mipmap-hdpi/ic_repeat_on_foreground.png +0 -0
  72. package/android/src/main/res/mipmap-hdpi/ic_shuffle_off_foreground.png +0 -0
  73. package/android/src/main/res/mipmap-hdpi/ic_shuffle_on_foreground.png +0 -0
  74. package/android/src/main/res/mipmap-mdpi/ic_arrow_down_circle_foreground.png +0 -0
  75. package/android/src/main/res/mipmap-mdpi/ic_clock_now_foreground.png +0 -0
  76. package/android/src/main/res/mipmap-mdpi/ic_close_foreground.png +0 -0
  77. package/android/src/main/res/mipmap-mdpi/ic_heart_foreground.png +0 -0
  78. package/android/src/main/res/mipmap-mdpi/ic_heart_outlined_foreground.png +0 -0
  79. package/android/src/main/res/mipmap-mdpi/ic_repeat_off_foreground.png +0 -0
  80. package/android/src/main/res/mipmap-mdpi/ic_repeat_on_foreground.png +0 -0
  81. package/android/src/main/res/mipmap-mdpi/ic_shuffle_off_foreground.png +0 -0
  82. package/android/src/main/res/mipmap-mdpi/ic_shuffle_on_foreground.png +0 -0
  83. package/android/src/main/res/mipmap-xhdpi/ic_arrow_down_circle_foreground.png +0 -0
  84. package/android/src/main/res/mipmap-xhdpi/ic_clock_now_foreground.png +0 -0
  85. package/android/src/main/res/mipmap-xhdpi/ic_close_foreground.png +0 -0
  86. package/android/src/main/res/mipmap-xhdpi/ic_heart_foreground.png +0 -0
  87. package/android/src/main/res/mipmap-xhdpi/ic_heart_outlined_foreground.png +0 -0
  88. package/android/src/main/res/mipmap-xhdpi/ic_repeat_off_foreground.png +0 -0
  89. package/android/src/main/res/mipmap-xhdpi/ic_repeat_on_foreground.png +0 -0
  90. package/android/src/main/res/mipmap-xhdpi/ic_shuffle_off_foreground.png +0 -0
  91. package/android/src/main/res/mipmap-xhdpi/ic_shuffle_on_foreground.png +0 -0
  92. package/android/src/main/res/mipmap-xxhdpi/ic_arrow_down_circle_foreground.png +0 -0
  93. package/android/src/main/res/mipmap-xxhdpi/ic_clock_now_foreground.png +0 -0
  94. package/android/src/main/res/mipmap-xxhdpi/ic_close_foreground.png +0 -0
  95. package/android/src/main/res/mipmap-xxhdpi/ic_heart_foreground.png +0 -0
  96. package/android/src/main/res/mipmap-xxhdpi/ic_heart_outlined_foreground.png +0 -0
  97. package/android/src/main/res/mipmap-xxhdpi/ic_repeat_off_foreground.png +0 -0
  98. package/android/src/main/res/mipmap-xxhdpi/ic_repeat_on_foreground.png +0 -0
  99. package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_off_foreground.png +0 -0
  100. package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_on_foreground.png +0 -0
  101. package/android/src/main/res/mipmap-xxxhdpi/ic_arrow_down_circle_foreground.png +0 -0
  102. package/android/src/main/res/mipmap-xxxhdpi/ic_clock_now_foreground.png +0 -0
  103. package/android/src/main/res/mipmap-xxxhdpi/ic_close_foreground.png +0 -0
  104. package/android/src/main/res/mipmap-xxxhdpi/ic_heart_foreground.png +0 -0
  105. package/android/src/main/res/mipmap-xxxhdpi/ic_heart_outlined_foreground.png +0 -0
  106. package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_off_foreground.png +0 -0
  107. package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_on_foreground.png +0 -0
  108. package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_off_foreground.png +0 -0
  109. package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_on_foreground.png +0 -0
  110. package/android/src/main/res/raw/silent_5_seconds.mp3 +0 -0
  111. package/android/src/main/res/strings.xml +6 -0
  112. package/android/src/main/res/values/strings.xml +6 -0
  113. package/index.d.ts +62 -1
  114. package/lib/index.js +10 -9
  115. package/package.json +1 -1
  116. package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +0 -28
  117. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +0 -55
  118. package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +0 -298
  119. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +0 -47
  120. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +0 -383
  121. package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +0 -271
  122. package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +0 -243
  123. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +0 -148
  124. package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +0 -379
  125. package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +0 -141
  126. package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +0 -35
  127. package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
  128. package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
  129. package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
  130. package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
  131. package/android/src/main/res/drawable-xxxhdpi/ic_logo.png +0 -0
@@ -0,0 +1,117 @@
1
+ package com.guichaguri.trackplayer.service
2
+
3
+ import android.content.ContentResolver
4
+ import android.content.Context
5
+ import android.net.Uri
6
+ import android.os.Bundle
7
+ import android.support.v4.media.RatingCompat
8
+ import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper
9
+
10
+ /**
11
+ * @author Milen Pivchev @mpivchev
12
+ */
13
+ object BundleUtils {
14
+ fun getUri(context: Context, data: Bundle?, key: String?): Uri? {
15
+ if (!data!!.containsKey(key)) return null
16
+ val obj = data[key]
17
+ if (obj is String) {
18
+ // Remote or Local Uri
19
+ if (obj.trim { it <= ' ' }.isEmpty()) throw RuntimeException("The URL cannot be empty")
20
+ return Uri.parse(obj as String?)
21
+ } else if (obj is Bundle) {
22
+ // require/import
23
+ val uri = obj.getString("uri")
24
+ val helper = ResourceDrawableIdHelper.getInstance()
25
+ val id = helper.getResourceDrawableId(context, uri)
26
+ return if (id > 0) {
27
+ // In production, we can obtain the resource uri
28
+ val res = context.resources
29
+ Uri.Builder()
30
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
31
+ .authority(res.getResourcePackageName(id))
32
+ .appendPath(res.getResourceTypeName(id))
33
+ .appendPath(res.getResourceEntryName(id))
34
+ .build()
35
+ } else {
36
+ // During development, the resources might come directly from the metro server
37
+ Uri.parse(uri)
38
+ }
39
+ }
40
+ return null
41
+ }
42
+
43
+ fun getRawResourceId(context: Context, data: Bundle, key: String?): Int {
44
+ if (!data.containsKey(key)) return 0
45
+ val obj = data[key] as? Bundle ?: return 0
46
+ var name = obj.getString("uri")
47
+ if (name == null || name.isEmpty()) return 0
48
+ name = name.lowercase().replace("-", "_")
49
+ return try {
50
+ name.toInt()
51
+ } catch (ex: NumberFormatException) {
52
+ context.resources.getIdentifier(name, "raw", context.packageName)
53
+ }
54
+ }
55
+
56
+ fun getIcon(context: Context, options: Bundle, propertyName: String, defaultIcon: Int): Int {
57
+ if (!options.containsKey(propertyName)) return defaultIcon
58
+
59
+ val bundle = options.getBundle(propertyName) ?: return defaultIcon
60
+
61
+ val helper = ResourceDrawableIdHelper.getInstance()
62
+ val icon = helper.getResourceDrawableId(context, bundle.getString("uri"))
63
+ return if (icon == 0) defaultIcon else icon
64
+ }
65
+
66
+ fun getIconOrNull(context: Context, options: Bundle, propertyName: String): Int? {
67
+ if (!options.containsKey(propertyName)) return null
68
+
69
+ val bundle = options.getBundle(propertyName) ?: return null
70
+
71
+ val helper = ResourceDrawableIdHelper.getInstance()
72
+ val icon = helper.getResourceDrawableId(context, bundle.getString("uri"))
73
+ return if (icon == 0) null else icon
74
+ }
75
+
76
+ fun getRating(data: Bundle?, key: String?, ratingType: Int): RatingCompat? {
77
+ return if (!data!!.containsKey(key) || ratingType == RatingCompat.RATING_NONE) {
78
+ RatingCompat.newUnratedRating(ratingType)
79
+ } else if (ratingType == RatingCompat.RATING_HEART) {
80
+ RatingCompat.newHeartRating(data.getBoolean(key, true))
81
+ } else if (ratingType == RatingCompat.RATING_THUMB_UP_DOWN) {
82
+ RatingCompat.newThumbRating(data.getBoolean(key, true))
83
+ } else if (ratingType == RatingCompat.RATING_PERCENTAGE) {
84
+ RatingCompat.newPercentageRating(data.getFloat(key, 0f))
85
+ } else {
86
+ RatingCompat.newStarRating(ratingType, data.getFloat(key, 0f))
87
+ }
88
+ }
89
+
90
+ fun setRating(data: Bundle, key: String?, rating: RatingCompat) {
91
+ if (!rating.isRated) return
92
+ val ratingType = rating.ratingStyle
93
+ if (ratingType == RatingCompat.RATING_HEART) {
94
+ data.putBoolean(key, rating.hasHeart())
95
+ } else if (ratingType == RatingCompat.RATING_THUMB_UP_DOWN) {
96
+ data.putBoolean(key, rating.isThumbUp)
97
+ } else if (ratingType == RatingCompat.RATING_PERCENTAGE) {
98
+ data.putDouble(key, rating.percentRating.toDouble())
99
+ } else {
100
+ data.putDouble(key, rating.starRating.toDouble())
101
+ }
102
+ }
103
+
104
+ fun getInt(data: Bundle?, key: String?, defaultValue: Int): Int {
105
+ val value = data!![key]
106
+ return if (value is Number) {
107
+ value.toInt()
108
+ } else defaultValue
109
+ }
110
+
111
+ fun getIntOrNull(data: Bundle?, key: String?): Int? {
112
+ val value = data!![key]
113
+ return if (value is Number) {
114
+ value.toInt()
115
+ } else null
116
+ }
117
+ }
@@ -0,0 +1,31 @@
1
+ package com.guichaguri.trackplayer.service
2
+
3
+ import android.os.Binder
4
+ import android.os.Bundle
5
+ import android.os.Handler
6
+
7
+ /**
8
+ * @author Guichaguri
9
+ */
10
+ class MusicBinder(val service: MusicService?, val manager: MusicManager) : Binder() {
11
+
12
+ fun post(r: Runnable?) {
13
+ if (service == null) return
14
+ if (service.handler == null) service.handler = Handler()
15
+ service.handler!!.post(r!!)
16
+ }
17
+
18
+ fun updateOptions(bundle: Bundle) {
19
+ manager.setStopWithApp(bundle.getBoolean("stopWithApp", true))
20
+ manager.setAlwaysPauseOnInterruption(bundle.getBoolean("alwaysPauseOnInterruption", false))
21
+ manager.metadata.updateOptions(bundle)
22
+ }
23
+
24
+ val ratingType: Int
25
+ get() = manager.metadata.ratingType
26
+
27
+ fun destroy() {
28
+ service!!.destroy(true)
29
+ service.stopSelf()
30
+ }
31
+ }
@@ -0,0 +1,347 @@
1
+ package com.guichaguri.trackplayer.service
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.content.BroadcastReceiver
5
+ import android.content.Context
6
+ import android.content.Intent
7
+ import android.content.IntentFilter
8
+ import android.media.AudioAttributes
9
+ import android.media.AudioFocusRequest
10
+ import android.media.AudioManager
11
+ import android.net.wifi.WifiManager
12
+ import android.os.Build
13
+ import android.os.Bundle
14
+ import android.os.Handler
15
+ import android.os.PowerManager
16
+ import android.support.v4.media.session.PlaybackStateCompat
17
+ import android.util.Log
18
+ import androidx.annotation.RequiresApi
19
+ import com.guichaguri.trackplayer.module.MusicEvents
20
+ import com.guichaguri.trackplayer.service.metadata.MetadataManager
21
+ import com.guichaguri.trackplayer.model.Track
22
+
23
+ /**
24
+ * @author Guichaguri
25
+ */
26
+ class MusicManager @SuppressLint("InvalidWakeLockTag") constructor(private val service: MusicService) :
27
+ AudioManager.OnAudioFocusChangeListener {
28
+ private val wakeLock: PowerManager.WakeLock
29
+ private val wifiLock: WifiManager.WifiLock
30
+ val metadata: MetadataManager
31
+ var currentTrack: Track? = null
32
+ private var state = 0
33
+ private var previousState = 0
34
+ private var position: Long = 0
35
+ private var bufferedPosition: Long = 0
36
+
37
+ @RequiresApi(26)
38
+ private var focus: AudioFocusRequest? = null
39
+ private var hasAudioFocus = false
40
+ private var wasDucking = false
41
+ private val noisyReceiver: BroadcastReceiver = object : BroadcastReceiver() {
42
+ override fun onReceive(context: Context, intent: Intent) {
43
+ service.emit(MusicEvents.BUTTON_PAUSE, null)
44
+ }
45
+ }
46
+ private var receivingNoisyEvents = false
47
+ private var stopWithApp = true
48
+ private var alwaysPauseOnInterruption = false
49
+
50
+ init {
51
+ metadata = MetadataManager(service, this)
52
+ val powerManager = service.getSystemService(Context.POWER_SERVICE) as PowerManager
53
+ wakeLock =
54
+ powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "track-player-wake-lock")
55
+ wakeLock.setReferenceCounted(false)
56
+
57
+ // Android 7: Use the application context here to prevent any memory leaks
58
+ val wifiManager =
59
+ service.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
60
+ wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "track-player-wifi-lock")
61
+ wifiLock.setReferenceCounted(false)
62
+ }
63
+
64
+ fun shouldStopWithApp(): Boolean {
65
+ return stopWithApp
66
+ }
67
+
68
+ fun setStopWithApp(stopWithApp: Boolean) {
69
+ this.stopWithApp = stopWithApp
70
+ }
71
+
72
+ fun setAlwaysPauseOnInterruption(alwaysPauseOnInterruption: Boolean) {
73
+ this.alwaysPauseOnInterruption = alwaysPauseOnInterruption
74
+ }
75
+
76
+ val handler: Handler?
77
+ get() = service.handler
78
+
79
+ fun getState(): Long {
80
+ return state.toLong()
81
+ }
82
+
83
+ fun setState(state: Int, position: Long) {
84
+ this.state = state
85
+ if (position != -1L) {
86
+ this.position = position
87
+ bufferedPosition = position
88
+ }
89
+ onPlayerStateChanged()
90
+ }
91
+
92
+ @SuppressLint("WakelockTimeout")
93
+ fun onPlay() {
94
+ /*if(playback == null) return;
95
+
96
+ Track track = playback.getCurrentTrack();
97
+ if(track == null) return;
98
+
99
+ if(!playback.isRemote()) {
100
+ requestFocus();
101
+
102
+ if(!receivingNoisyEvents) {
103
+ receivingNoisyEvents = true;
104
+ service.registerReceiver(noisyReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
105
+ }
106
+
107
+ if(!wakeLock.isHeld()) wakeLock.acquire();
108
+
109
+ if(!Utils.isLocal(track.uri)) {
110
+ if(!wifiLock.isHeld()) wifiLock.acquire();
111
+ }
112
+ }*/requestFocus()
113
+ if (!receivingNoisyEvents) {
114
+ receivingNoisyEvents = true
115
+ service.registerReceiver(
116
+ noisyReceiver,
117
+ IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
118
+ )
119
+ }
120
+ if (!wakeLock.isHeld) wakeLock.acquire()
121
+
122
+ /*if(!Utils.isLocal(currentTrack.uri)) {
123
+ if(!wifiLock.isHeld()) wifiLock.acquire();
124
+ }*/metadata.setActive(true)
125
+ }
126
+
127
+ fun onPause() {
128
+ // Unregisters the noisy receiver
129
+ if (receivingNoisyEvents) {
130
+ try {
131
+ service.unregisterReceiver(noisyReceiver)
132
+ receivingNoisyEvents = false
133
+ } catch (e: Exception) {
134
+ }
135
+ }
136
+
137
+ // Release the wake and the wifi locks
138
+ if (wakeLock.isHeld) wakeLock.release()
139
+ if (wifiLock.isHeld) wifiLock.release()
140
+ metadata.setActive(true)
141
+ }
142
+
143
+ fun onStop() {
144
+ Log.d(Utils.LOG, "onStop")
145
+
146
+ // Unregisters the noisy receiver
147
+ if (receivingNoisyEvents) {
148
+ try {
149
+ service.unregisterReceiver(noisyReceiver)
150
+ receivingNoisyEvents = false
151
+ } catch (e: Exception) {
152
+ }
153
+ }
154
+
155
+ // Release the wake and the wifi locks
156
+ if (wakeLock.isHeld) wakeLock.release()
157
+ if (wifiLock.isHeld) wifiLock.release()
158
+ abandonFocus()
159
+ metadata.setActive(false)
160
+ }
161
+
162
+ fun onPlayerStateChanged() {
163
+ if (Utils.isPlaying(state) && !Utils.isPlaying(previousState)) {
164
+ onPlay()
165
+ } else if (Utils.isPaused(state) && !Utils.isPaused(previousState)) {
166
+ onPause()
167
+ } else if (Utils.isStopped(state) && !Utils.isStopped(previousState)) {
168
+ onStop()
169
+ }
170
+ onStateChange(state, position, bufferedPosition)
171
+ previousState = state
172
+ if (state == PlaybackStateCompat.STATE_STOPPED) {
173
+ onEnd(currentTrack, 0)
174
+ }
175
+ }
176
+
177
+ fun onStateChange(state: Int, position: Long, bufferedPosition: Long) {
178
+ Log.d(Utils.LOG, "onStateChange")
179
+ val bundle = Bundle()
180
+ bundle.putInt("state", state)
181
+ service.emit(MusicEvents.PLAYBACK_STATE, bundle)
182
+ metadata.updatePlayback(state, position, bufferedPosition, 1)
183
+ }
184
+
185
+ fun onTrackUpdate(previous: Track?, prevPos: Long, next: Track?) {
186
+ Log.d(Utils.LOG, "onTrackUpdate")
187
+ if (next != null) metadata.updateMetadata(next)
188
+ val bundle = Bundle()
189
+ bundle.putString("track", previous?.id)
190
+ bundle.putDouble("position", Utils.toSeconds(prevPos))
191
+ bundle.putString("nextTrack", next?.id)
192
+ service.emit(MusicEvents.PLAYBACK_TRACK_CHANGED, bundle)
193
+ }
194
+
195
+ fun onReset() {
196
+ metadata.removeNotifications()
197
+ }
198
+
199
+ fun onEnd(previous: Track?, prevPos: Long) {
200
+ Log.d(Utils.LOG, "onEnd")
201
+ val bundle = Bundle()
202
+ bundle.putString("track", previous?.id)
203
+ bundle.putDouble("position", Utils.toSeconds(prevPos))
204
+ service.emit(MusicEvents.PLAYBACK_QUEUE_ENDED, bundle)
205
+ }
206
+
207
+ fun onMetadataReceived(
208
+ source: String,
209
+ title: String?,
210
+ url: String?,
211
+ artist: String?,
212
+ album: String?,
213
+ date: String?,
214
+ genre: String?
215
+ ) {
216
+ Log.d(
217
+ Utils.LOG,
218
+ "onMetadataReceived: $source"
219
+ )
220
+ val bundle = Bundle()
221
+ bundle.putString("source", source)
222
+ bundle.putString("title", title)
223
+ bundle.putString("url", url)
224
+ bundle.putString("artist", artist)
225
+ bundle.putString("album", album)
226
+ bundle.putString("date", date)
227
+ bundle.putString("genre", genre)
228
+ service.emit(MusicEvents.PLAYBACK_METADATA, bundle)
229
+ }
230
+
231
+ fun onError(code: String, error: String) {
232
+ Log.d(Utils.LOG, "onError")
233
+ Log.e(
234
+ Utils.LOG,
235
+ "Playback error: $code - $error"
236
+ )
237
+ val bundle = Bundle()
238
+ bundle.putString("code", code)
239
+ bundle.putString("message", error)
240
+ service.emit(MusicEvents.PLAYBACK_ERROR, bundle)
241
+ }
242
+
243
+ override fun onAudioFocusChange(focus: Int) {
244
+ Log.d(Utils.LOG, "onDuck")
245
+ var permanent = false
246
+ var paused = false
247
+ var ducking = false
248
+ when (focus) {
249
+ AudioManager.AUDIOFOCUS_GAIN -> paused = false
250
+ AudioManager.AUDIOFOCUS_LOSS -> {
251
+ permanent = true
252
+ paused = true
253
+ abandonFocus()
254
+ }
255
+ AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> paused = true
256
+ AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> if (alwaysPauseOnInterruption) paused =
257
+ true else ducking = true
258
+ else -> {}
259
+ }
260
+ if (ducking) {
261
+ //playback.setVolumeMultiplier(0.5F);
262
+ wasDucking = true
263
+ } else if (wasDucking) {
264
+ //playback.setVolumeMultiplier(1.0F);
265
+ wasDucking = false
266
+ }
267
+ val bundle = Bundle()
268
+ bundle.putBoolean("permanent", permanent)
269
+ bundle.putBoolean("paused", paused)
270
+ bundle.putBoolean("ducking", ducking)
271
+ service.emit(MusicEvents.BUTTON_DUCK, bundle)
272
+ }
273
+
274
+ private fun requestFocus() {
275
+ if (hasAudioFocus) return
276
+ Log.d(Utils.LOG, "Requesting audio focus...")
277
+ val manager = service.getSystemService(Context.AUDIO_SERVICE) as AudioManager
278
+ val r: Int
279
+ if (manager == null) {
280
+ r = AudioManager.AUDIOFOCUS_REQUEST_FAILED
281
+ } else if (Build.VERSION.SDK_INT >= 26) {
282
+ focus = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
283
+ .setOnAudioFocusChangeListener(this)
284
+ .setAudioAttributes(
285
+ AudioAttributes.Builder()
286
+ .setUsage(AudioAttributes.USAGE_MEDIA)
287
+ .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
288
+ .build()
289
+ )
290
+ .setWillPauseWhenDucked(alwaysPauseOnInterruption)
291
+ .build()
292
+ r = if (focus != null) {
293
+ manager.requestAudioFocus(focus!!)
294
+ } else {
295
+ AudioManager.AUDIOFOCUS_REQUEST_FAILED
296
+ }
297
+ } else {
298
+ r = manager.requestAudioFocus(
299
+ this,
300
+ AudioManager.STREAM_MUSIC,
301
+ AudioManager.AUDIOFOCUS_GAIN
302
+ )
303
+ }
304
+ hasAudioFocus = r == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
305
+ }
306
+
307
+ private fun abandonFocus() {
308
+ if (!hasAudioFocus) return
309
+ Log.d(Utils.LOG, "Abandoning audio focus...")
310
+ val manager = service.getSystemService(Context.AUDIO_SERVICE) as AudioManager
311
+ val r: Int
312
+ r = if (manager == null) {
313
+ AudioManager.AUDIOFOCUS_REQUEST_FAILED
314
+ } else if (Build.VERSION.SDK_INT >= 26) {
315
+ manager.abandonAudioFocusRequest(focus!!)
316
+ } else {
317
+ manager.abandonAudioFocus(this)
318
+ }
319
+ hasAudioFocus = r != AudioManager.AUDIOFOCUS_REQUEST_GRANTED
320
+ }
321
+
322
+ fun destroy(intentToStop: Boolean) {
323
+ Log.d(Utils.LOG, "Releasing service resources...")
324
+
325
+ // Disable audio focus
326
+ abandonFocus()
327
+
328
+ // Stop receiving audio becoming noisy events
329
+ if (receivingNoisyEvents) {
330
+ try {
331
+ service.unregisterReceiver(noisyReceiver)
332
+ receivingNoisyEvents = false
333
+ } catch (e: Exception) {
334
+ }
335
+ }
336
+
337
+ // Release the playback resources
338
+ //if(playback != null) playback.destroy();
339
+
340
+ // Release the metadata resources
341
+ metadata.destroy(intentToStop)
342
+
343
+ // Release the locks
344
+ if (wifiLock.isHeld) wifiLock.release()
345
+ if (wakeLock.isHeld) wakeLock.release()
346
+ }
347
+ }