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

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} +84 -33
  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 +1177 -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 +1254 -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,8 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ data class BufferConfig(
4
+ val minBuffer: Int?,
5
+ val maxBuffer: Int?,
6
+ val playBuffer: Int?,
7
+ val backBuffer: Int?,
8
+ )
@@ -0,0 +1,17 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ /**
4
+ * Configuration for cache properties of player.
5
+ */
6
+ data class CacheConfig(
7
+ /**
8
+ * Maximum player cache size in kilobytes.
9
+ */
10
+ val maxCacheSize: Long?,
11
+
12
+ /**
13
+ * Cache identifier, used to make cache directory.
14
+ */
15
+ val identifier: String = "TrackPlayer"
16
+ )
17
+
@@ -0,0 +1,19 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ enum class Capability {
4
+ PLAY,
5
+ PLAY_FROM_ID,
6
+ PLAY_FROM_SEARCH,
7
+ PAUSE,
8
+ STOP,
9
+ SEEK_TO,
10
+ SKIP,
11
+ SKIP_TO_NEXT,
12
+ SKIP_TO_PREVIOUS,
13
+ JUMP_FORWARD,
14
+ JUMP_BACKWARD,
15
+ SET_RATING,
16
+ LIKE,
17
+ DISLIKE,
18
+ BOOKMARK
19
+ }
@@ -0,0 +1,3 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ data class FocusChangeData(val isPaused: Boolean, val isFocusLostPermanently: Boolean)
@@ -0,0 +1,17 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ import android.os.Bundle
4
+ import android.support.v4.media.RatingCompat
5
+
6
+ sealed class MediaSessionCallback {
7
+ class RATING(val rating: RatingCompat, extras: Bundle?): MediaSessionCallback()
8
+ object PLAY : MediaSessionCallback()
9
+ object PAUSE : MediaSessionCallback()
10
+ object NEXT : MediaSessionCallback()
11
+ object PREVIOUS : MediaSessionCallback()
12
+ object FORWARD : MediaSessionCallback()
13
+ object REWIND : MediaSessionCallback()
14
+ object STOP : MediaSessionCallback()
15
+ class SEEK(val positionMs: Long): MediaSessionCallback()
16
+ class CUSTOMACTION(val customAction: String): MediaSessionCallback()
17
+ }
@@ -0,0 +1,43 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ import android.app.PendingIntent
4
+ import androidx.annotation.DrawableRes
5
+
6
+ /**
7
+ * Used to configure the player notification.
8
+ * @param buttons Provide customized notification buttons. They will be shown by default. Note that buttons can still be shown and hidden at runtime by using the functions in [NotificationManager][com.doublesymmetry.kotlinaudio.notification.NotificationManager], but they will have the default icon if not set explicitly here.
9
+ * @param accentColor The accent color of the notification.
10
+ * @param smallIcon The small icon of the notification which is also shown in the system status bar.
11
+ * @param pendingIntent The [PendingIntent] that would be called when tapping on the notification itself.
12
+ */
13
+ data class NotificationConfig(
14
+ val buttons: List<NotificationButton>,
15
+ val accentColor: Int? = null,
16
+ @DrawableRes val smallIcon: Int? = null,
17
+ val pendingIntent: PendingIntent? = null
18
+ )
19
+
20
+ /**
21
+ * Provide customized notification buttons. They will be shown by default. Note that buttons can still be shown and hidden at runtime by using the functions in [NotificationManager][com.doublesymmetry.kotlinaudio.notification.NotificationManager], but they will have the default icon if not set explicitly here.
22
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPlayPauseButton]
23
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showStopButton]
24
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showRewindButton]
25
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showRewindButtonCompact]
26
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showForwardButton]
27
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showForwardButtonCompact]
28
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showNextButton]
29
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showNextButtonCompact]
30
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButton]
31
+ * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButtonCompact]
32
+ */
33
+ @Suppress("ClassName")
34
+ sealed class NotificationButton(val customAction: String? = null) {
35
+ class PLAY_PAUSE(@DrawableRes val playIcon: Int? = null, @DrawableRes val pauseIcon: Int? = null): NotificationButton()
36
+ class STOP(@DrawableRes val icon: Int? = null): NotificationButton()
37
+ class FORWARD(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton()
38
+ class BACKWARD(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton()
39
+ class NEXT(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton()
40
+ class PREVIOUS(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton()
41
+ object SEEK_TO : NotificationButton()
42
+ class CUSTOM_ACTION(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false, customAction: String): NotificationButton(customAction=customAction)
43
+ }
@@ -0,0 +1,8 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ data class NotificationMetadata(
4
+ val title: String?= null,
5
+ val artist: String? = null,
6
+ val artworkUrl: String? = null,
7
+ val duration: Long? = null
8
+ )
@@ -0,0 +1,8 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ import android.app.Notification
4
+
5
+ sealed class NotificationState {
6
+ class POSTED(val notificationId: Int, val notification: Notification, val ongoing: Boolean) : NotificationState()
7
+ class CANCELLED(val notificationId: Int): NotificationState()
8
+ }
@@ -0,0 +1,5 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ import com.google.android.exoplayer2.Player
4
+
5
+ data class PlayWhenReadyChangeData(val playWhenReady: Boolean, val pausedBecauseReachedEnd: Boolean)
@@ -0,0 +1,5 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ enum class PlaybackEndedReason {
4
+ PLAYED_UNTIL_END, PLAYER_STOPPED, SKIPPED_TO_NEXT, SKIPPED_TO_PREVIOUS, JUMPED_TO_INDEX
5
+ }
@@ -0,0 +1,6 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ data class PlaybackError (
4
+ val code: String? = null,
5
+ val message: String? = null
6
+ )
@@ -0,0 +1,200 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ import com.google.android.exoplayer2.metadata.flac.VorbisComment
4
+ import com.google.android.exoplayer2.metadata.icy.IcyHeaders
5
+ import com.google.android.exoplayer2.metadata.icy.IcyInfo
6
+ import com.google.android.exoplayer2.metadata.id3.TextInformationFrame
7
+ import com.google.android.exoplayer2.metadata.id3.UrlLinkFrame
8
+ import com.google.android.exoplayer2.metadata.mp4.MdtaMetadataEntry
9
+ import com.google.android.exoplayer2.metadata.Metadata
10
+
11
+ data class PlaybackMetadata(
12
+ val source: String,
13
+ var title: String? = null,
14
+ var url: String? = null,
15
+ var artist: String? = null,
16
+ var album: String? = null,
17
+ var date: String? = null,
18
+ var genre: String? = null
19
+ ) {
20
+ companion object {
21
+ /**
22
+ * ID3 Metadata (MP3)
23
+ * https://en.wikipedia.org/wiki/ID3
24
+ */
25
+ fun fromId3Metadata(metadata: Metadata): PlaybackMetadata? {
26
+ var handled = false
27
+
28
+ var title: String? = null
29
+ var url: String? = null
30
+ var artist: String? = null
31
+ var album: String? = null
32
+ var date: String? = null
33
+ var genre: String? = null
34
+
35
+ (0 until metadata.length()).forEach { i ->
36
+ when (val entry = metadata[i]) {
37
+ is TextInformationFrame -> {
38
+ when (entry.id.uppercase()) {
39
+ "TIT2", "TT2" -> {
40
+ handled = true
41
+ title = entry.value
42
+ }
43
+ "TALB", "TOAL", "TAL" -> {
44
+ handled = true
45
+ album = entry.value
46
+ }
47
+ "TOPE", "TPE1", "TP1" -> {
48
+ handled = true
49
+ artist = entry.value
50
+ }
51
+ "TDRC", "TOR" -> {
52
+ handled = true
53
+ date = entry.value
54
+ }
55
+ "TCON", "TCO" -> {
56
+ handled = true
57
+ genre = entry.value
58
+ }
59
+
60
+ }
61
+ }
62
+ is UrlLinkFrame -> {
63
+ when (entry.id.uppercase()) {
64
+ "WOAS", "WOAF", "WOAR", "WAR" -> {
65
+ handled = true;
66
+ url = entry.url;
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+
74
+ return if (handled) PlaybackMetadata("id3", title, url, artist, album, date, genre) else null
75
+ }
76
+
77
+ /**
78
+ * Shoutcast / Icecast metadata (ICY protocol)
79
+ * https://cast.readme.io/docs/icy
80
+ */
81
+ fun fromIcy(metadata: Metadata): PlaybackMetadata? {
82
+ for (i in 0 until metadata.length()) {
83
+ when (val entry = metadata[i]) {
84
+ is IcyHeaders -> {
85
+ return PlaybackMetadata("icy-headers", title = entry.name, url = entry.url, genre = entry.genre)
86
+ }
87
+ is IcyInfo -> {
88
+ val artist: String?
89
+ val title: String?
90
+ val index =
91
+ if (entry.title == null) -1 else entry.title!!.indexOf(" - ")
92
+ if (index != -1) {
93
+ artist = entry.title!!.substring(0, index)
94
+ title = entry.title!!.substring(index + 3)
95
+ } else {
96
+ artist = null
97
+ title = entry.title
98
+ }
99
+
100
+ return PlaybackMetadata("icy", title = title, url = entry.url, artist = artist)
101
+ }
102
+ }
103
+ }
104
+
105
+ return null
106
+ }
107
+
108
+ /**
109
+ * Vorbis Comments (Vorbis, FLAC, Opus, Speex, Theora)
110
+ * https://xiph.org/vorbis/doc/v-comment.html
111
+ */
112
+ fun fromVorbisComment(metadata: Metadata): PlaybackMetadata? {
113
+ var handled = false;
114
+
115
+ var title: String? = null
116
+ var url: String? = null
117
+ var artist: String? = null
118
+ var album: String? = null
119
+ var date: String? = null
120
+ var genre: String? = null
121
+
122
+ for (i in 0 until metadata.length()) {
123
+ val entry = metadata[i]
124
+ if (entry is VorbisComment) {
125
+ when (entry.key) {
126
+ "TITLE" -> {
127
+ handled = true
128
+ title = entry.value;
129
+ }
130
+ "ARTIST" -> {
131
+ handled = true
132
+ artist = entry.value;
133
+ }
134
+ "ALBUM" -> {
135
+ handled = true
136
+ album = entry.value;
137
+ }
138
+ "DATE" -> {
139
+ handled = true
140
+ date = entry.value
141
+ }
142
+ "GENRE" -> {
143
+ handled = true
144
+ genre = entry.value
145
+ }
146
+ "URL" -> {
147
+ handled = true
148
+ url = entry.value
149
+ }
150
+ }
151
+ }
152
+ }
153
+ return if (handled) PlaybackMetadata("vorbis-comment", title, url, artist, album, date, genre) else null
154
+ }
155
+
156
+ /**
157
+ * QuickTime MDTA metadata (mov, qt)
158
+ * https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/Metadata/Metadata.html
159
+ */
160
+ fun fromQuickTime(metadata: Metadata): PlaybackMetadata? {
161
+ var handled = false;
162
+
163
+ var title: String? = null
164
+ var artist: String? = null
165
+ var album: String? = null
166
+ var date: String? = null
167
+ var genre: String? = null
168
+
169
+ for (i in 0 until metadata.length()) {
170
+ val entry = metadata[i];
171
+ if (entry is MdtaMetadataEntry) {
172
+ when (entry.key) {
173
+ "com.apple.quicktime.title" -> {
174
+ handled = true
175
+ title = entry.value.toString();
176
+ }
177
+ "com.apple.quicktime.artist" -> {
178
+ handled = true
179
+ artist = entry.value.toString();
180
+ }
181
+ "com.apple.quicktime.album" -> {
182
+ handled = true
183
+ album = entry.value.toString();
184
+ }
185
+ "com.apple.quicktime.creationdate" -> {
186
+ handled = true
187
+ date = entry.value.toString();
188
+ }
189
+ "com.apple.quicktime.genre" -> {
190
+ handled = true
191
+ genre = entry.value.toString();
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ return if (handled) PlaybackMetadata("quicktime", title = title, artist = artist, album = album, date = date, genre = genre) else null
198
+ }
199
+ }
200
+ }
@@ -0,0 +1,33 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ import com.guichaguri.trackplayer.kotlinaudio.models.AudioContentType
4
+
5
+ data class PlayerConfig(
6
+ /**
7
+ * Toggle whether or not a player action triggered from an outside source should be intercepted.
8
+ *
9
+ * The sources can be: media buttons on headphones, Android Wear, Android Auto, Google Assistant, media notification, etc.
10
+ *
11
+ * Setting this to true enables the use of [onPlayerActionTriggeredExternally][com.doublesymmetry.kotlinaudio.event.PlayerEventHolder.onPlayerActionTriggeredExternally] events.
12
+ *
13
+ * **Example**:
14
+ * ```
15
+ * val player = QueuedAudioPlayer(requireActivity(), playerConfig = PlayerConfig(interceptPlayerActionsTriggeredExternally = true))
16
+ * ```
17
+ */
18
+ var interceptPlayerActionsTriggeredExternally: Boolean = false,
19
+
20
+ /**
21
+ * Toggle whether the player should pause automatically when audio is rerouted from a headset to device speakers.
22
+ */
23
+ val handleAudioBecomingNoisy: Boolean = false,
24
+
25
+ /**
26
+ * Whether audio focus should be managed automatically. See https://medium.com/google-exoplayer/easy-audio-focus-with-exoplayer-a2dcbbe4640e
27
+ */
28
+ val handleAudioFocus: Boolean = false,
29
+ /**
30
+ * The audio content type.
31
+ */
32
+ val audioContentType: AudioContentType = AudioContentType.MUSIC
33
+ )
@@ -0,0 +1,9 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ interface PlayerOptions {
4
+ var alwaysPauseOnInterruption: Boolean
5
+ }
6
+
7
+ internal data class DefaultPlayerOptions(
8
+ override var alwaysPauseOnInterruption: Boolean = false,
9
+ ) : PlayerOptions
@@ -0,0 +1,39 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ /**
4
+ * Use these events to track when and why the positionMs of an [AudioItem] changes.
5
+ * Examples include changes to [AudioItem] queue, seeking, skipping, etc.
6
+ */
7
+ sealed class PositionChangedReason(val oldPosition: Long, val newPosition: Long) {
8
+ /**
9
+ * Position has changed because the player has automatically transitioned to the next [AudioItem].
10
+ *
11
+ * @see [AudioItemTransitionReason]
12
+ */
13
+ class AUTO(oldPosition: Long, newPosition: Long) : PositionChangedReason(oldPosition, newPosition)
14
+
15
+ /**
16
+ * Position has changed because of a queue update.
17
+ */
18
+ class QUEUE_CHANGED(oldPosition: Long, newPosition: Long) : PositionChangedReason(oldPosition, newPosition)
19
+
20
+ /**
21
+ * Position has changed because a seek has occurred within the current [AudioItem], or another one.
22
+ */
23
+ class SEEK(oldPosition: Long, newPosition: Long) : PositionChangedReason(oldPosition, newPosition)
24
+
25
+ /**
26
+ * Position has changed because an attempted seek has failed. This can occur if we tried to see to an invalid positionMs.
27
+ */
28
+ class SEEK_FAILED(oldPosition: Long, newPosition: Long) : PositionChangedReason(oldPosition, newPosition)
29
+
30
+ /**
31
+ * Position has changed because a period (example: an ad) has been skipped.
32
+ */
33
+ class SKIPPED_PERIOD(oldPosition: Long, newPosition: Long) : PositionChangedReason(oldPosition, newPosition)
34
+
35
+ /**
36
+ * Position has changed for an unknown reason.
37
+ */
38
+ class UNKNOWN(oldPosition: Long, newPosition: Long) : PositionChangedReason(oldPosition, newPosition)
39
+ }
@@ -0,0 +1,49 @@
1
+ package com.guichaguri.trackplayer.kotlinaudio.models
2
+
3
+ import com.google.android.exoplayer2.ExoPlayer
4
+ import com.google.android.exoplayer2.Player
5
+
6
+ interface QueuedPlayerOptions : PlayerOptions {
7
+ override var alwaysPauseOnInterruption: Boolean
8
+ var repeatMode: RepeatMode
9
+ }
10
+
11
+ class DefaultQueuedPlayerOptions(
12
+ private val exoPlayer: ExoPlayer,
13
+ override var alwaysPauseOnInterruption: Boolean = false,
14
+ ) : QueuedPlayerOptions {
15
+ // Functions in data classes might or might not be a bit of a code smell.
16
+ // I'm using the passed exoPlayer which breaks separation of concerns. But it's also useful.
17
+ // More here: https://www.reddit.com/r/Kotlin/comments/ehqe4e/why_is_it_bad_practice_to_have_functions_in_data/
18
+ // TODO: Figure out a way for this function to be outside of this data class
19
+ override var repeatMode: RepeatMode
20
+ get() {
21
+ return when (exoPlayer.repeatMode) {
22
+ Player.REPEAT_MODE_ALL -> RepeatMode.ALL
23
+ Player.REPEAT_MODE_ONE -> RepeatMode.ONE
24
+ else -> RepeatMode.OFF
25
+ }
26
+ }
27
+ set(value) {
28
+ when (value) {
29
+ RepeatMode.ALL -> exoPlayer.repeatMode = Player.REPEAT_MODE_ALL
30
+ RepeatMode.ONE -> exoPlayer.repeatMode = Player.REPEAT_MODE_ONE
31
+ RepeatMode.OFF -> exoPlayer.repeatMode = Player.REPEAT_MODE_OFF
32
+ }
33
+ }
34
+ }
35
+
36
+ enum class RepeatMode {
37
+ OFF, ONE, ALL;
38
+
39
+ companion object {
40
+ fun fromOrdinal(ordinal: Int): RepeatMode {
41
+ return when (ordinal) {
42
+ 0 -> OFF
43
+ 1 -> ONE
44
+ 2 -> ALL
45
+ else -> error("Wrong ordinal")
46
+ }
47
+ }
48
+ }
49
+ }