@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.
- package/android/build.gradle +61 -4
- package/android/src/main/AndroidManifest.xml +2 -4
- package/android/src/main/ic_home-playstore.png +0 -0
- package/android/src/main/ic_repeat-playstore.png +0 -0
- package/android/src/main/ic_repeat_50-playstore.png +0 -0
- package/android/src/main/ic_shuffle-playstore.png +0 -0
- package/android/src/main/ic_shuffle_50-playstore.png +0 -0
- package/android/src/main/ic_shuffle_sm-playstore.png +0 -0
- package/android/src/main/ic_stop-playstore.png +0 -0
- package/android/src/main/ic_test-playstore.png +0 -0
- package/android/src/main/java/com/guichaguri/trackplayer/{service/HeadlessJsMediaService.java → HeadlessJsMediaService.java} +84 -33
- package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.kt +25 -0
- package/android/src/main/java/com/guichaguri/trackplayer/extensions/AudioPlayerStateExt.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/EventHolder.kt +30 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/NotificationEventHolder.kt +20 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/event/PlayerEventHolder.kt +111 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AAMediaSessionCallback.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioContentType.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItem.kt +66 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioItemTransitionReason.kt +33 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/AudioPlayerState.kt +30 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/BufferConfig.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/CacheConfig.kt +17 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/Capability.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/FocusChangeData.kt +3 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/MediaSessionCallback.kt +17 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationConfig.kt +43 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationMetadata.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationState.kt +8 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayWhenReadyChangeData.kt +5 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackEndedReason.kt +5 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackError.kt +6 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackMetadata.kt +200 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerConfig.kt +33 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlayerOptions.kt +9 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PositionChangedReason.kt +39 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/QueuedPlayerOptions.kt +49 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/notification/NotificationManager.kt +678 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/AudioPlayer.kt +10 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/BaseAudioPlayer.kt +864 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/QueuedAudioPlayer.kt +269 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/MediaSourceExt.kt +35 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/players/components/PlayerCache.kt +26 -0
- package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/utils/Utils.kt +12 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/MetadataAdapter.kt +224 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/State.kt +13 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/Track.kt +120 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/TrackAudioItem.kt +19 -0
- package/android/src/main/java/com/guichaguri/trackplayer/model/TrackType.kt +11 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/AutoConnectionDetector.kt +151 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.kt +66 -0
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.kt +1177 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/BundleUtils.kt +117 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.kt +31 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.kt +347 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.kt +1254 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.kt +228 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.kt +141 -0
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.kt +396 -0
- package/android/src/main/res/drawable-hdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_home.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_home.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_arrow_down_circle_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_clock_now_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_close_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_heart_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_heart_outlined_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_repeat_on_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_off_foreground.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_shuffle_on_foreground.png +0 -0
- package/android/src/main/res/raw/silent_5_seconds.mp3 +0 -0
- package/android/src/main/res/strings.xml +6 -0
- package/android/src/main/res/values/strings.xml +6 -0
- package/index.d.ts +62 -1
- package/lib/index.js +10 -9
- package/package.json +1 -1
- package/android/src/main/java/com/guichaguri/trackplayer/TrackPlayer.java +0 -28
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicEvents.java +0 -55
- package/android/src/main/java/com/guichaguri/trackplayer/module/MusicModule.java +0 -298
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicBinder.java +0 -47
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicManager.java +0 -383
- package/android/src/main/java/com/guichaguri/trackplayer/service/MusicService.java +0 -271
- package/android/src/main/java/com/guichaguri/trackplayer/service/Utils.java +0 -243
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/ButtonEvents.java +0 -148
- package/android/src/main/java/com/guichaguri/trackplayer/service/metadata/MetadataManager.java +0 -379
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/Track.java +0 -141
- package/android/src/main/java/com/guichaguri/trackplayer/service/models/TrackType.java +0 -35
- package/android/src/main/res/drawable-hdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_logo.png +0 -0
- package/android/src/main/res/drawable-xxxhdpi/ic_logo.png +0 -0
|
@@ -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
|
+
}
|
package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/MediaSessionCallback.kt
ADDED
|
@@ -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
|
+
}
|
package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationConfig.kt
ADDED
|
@@ -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
|
+
}
|
package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/NotificationState.kt
ADDED
|
@@ -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
|
+
}
|
package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PlaybackMetadata.kt
ADDED
|
@@ -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
|
+
)
|
package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/PositionChangedReason.kt
ADDED
|
@@ -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
|
+
}
|
package/android/src/main/java/com/guichaguri/trackplayer/kotlinaudio/models/QueuedPlayerOptions.kt
ADDED
|
@@ -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
|
+
}
|