mirror of
https://github.com/jellyfin/jellyfin-androidtv.git
synced 2026-10-26 16:45:23 +00:00
Add media type API to set proper content type in audio attributes
This commit is contained in:
1 parent
7acfc41498
commit
d41f992b62
5 files changed
+99
-10
No files matched your search
@@ -0,0 +1,21 @@
|
||||
package org.jellyfin.playback.core.mediastream.mediatype
|
||||
|
||||
/**
|
||||
* Definition of the type for a specific media.
|
||||
*/
|
||||
enum class MediaType {
|
||||
/**
|
||||
* Media type for primarily video content like movies, tv shows and live tv.
|
||||
*/
|
||||
Video,
|
||||
|
||||
/**
|
||||
* Media type for primarily audio content like music, podcasts and audio books.
|
||||
*/
|
||||
Audio,
|
||||
|
||||
/**
|
||||
* Unknown media type.
|
||||
*/
|
||||
Unknown,
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.jellyfin.playback.core.mediastream.mediatype
|
||||
|
||||
import org.jellyfin.playback.core.element.ElementKey
|
||||
import org.jellyfin.playback.core.element.elementFlow
|
||||
import org.jellyfin.playback.core.element.requiredElement
|
||||
import org.jellyfin.playback.core.queue.QueueEntry
|
||||
|
||||
private val mediaTypeKey = ElementKey<MediaType>("MediaType")
|
||||
|
||||
/**
|
||||
* Get or set the media type this [QueueEntry]. A supported backend will use this to
|
||||
* set correct audio attributes for the media.
|
||||
*/
|
||||
var QueueEntry.mediaType by requiredElement(mediaTypeKey) { MediaType.Unknown }
|
||||
|
||||
/**
|
||||
* Get the flow of [mediaType].
|
||||
* @see mediaType
|
||||
*/
|
||||
val QueueEntry.mediaTypeFlow by elementFlow(mediaTypeKey)
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jellyfin.playback.jellyfin.queue
|
||||
|
||||
import org.jellyfin.playback.core.mediastream.mediatype.mediaType
|
||||
import org.jellyfin.playback.core.mediastream.normalizationGain
|
||||
import org.jellyfin.playback.core.queue.QueueEntry
|
||||
import org.jellyfin.playback.core.queue.QueueEntryMetadata
|
||||
@@ -10,6 +11,8 @@ import org.jellyfin.sdk.model.api.BaseItemDto
|
||||
import org.jellyfin.sdk.model.api.ImageType
|
||||
import org.jellyfin.sdk.model.extensions.ticks
|
||||
import java.util.UUID
|
||||
import org.jellyfin.playback.core.mediastream.mediatype.MediaType as PlayerMediaType
|
||||
import org.jellyfin.sdk.model.api.MediaType as SdkMediaType
|
||||
|
||||
/**
|
||||
* Create a [QueueEntry] from a [BaseItemDto].
|
||||
@@ -46,6 +49,13 @@ fun createBaseItemQueueEntry(api: ApiClient, baseItem: BaseItemDto): QueueEntry
|
||||
)
|
||||
entry.baseItem = baseItem
|
||||
entry.normalizationGain = baseItem.normalizationGain
|
||||
entry.mediaType = when (baseItem.mediaType) {
|
||||
SdkMediaType.VIDEO -> PlayerMediaType.Video
|
||||
SdkMediaType.AUDIO -> PlayerMediaType.Audio
|
||||
SdkMediaType.PHOTO,
|
||||
SdkMediaType.BOOK,
|
||||
SdkMediaType.UNKNOWN -> PlayerMediaType.Unknown
|
||||
}
|
||||
return entry
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.jellyfin.playback.media3.exoplayer
|
||||
|
||||
import androidx.media3.common.AudioAttributes
|
||||
import timber.log.Timber
|
||||
|
||||
class AudioAttributeState {
|
||||
private var _audioAttributes: AudioAttributes? = null
|
||||
|
||||
fun updateAudioAttributes(
|
||||
builder: AudioAttributes.Builder.() -> Unit,
|
||||
onChange: (audioAttributes: AudioAttributes) -> Unit,
|
||||
) {
|
||||
val newAudioAttributes = AudioAttributes.Builder().apply {
|
||||
builder()
|
||||
}.build()
|
||||
|
||||
if (_audioAttributes != newAudioAttributes) {
|
||||
Timber.d("Audio attributes changed")
|
||||
|
||||
onChange(newAudioAttributes)
|
||||
_audioAttributes = newAudioAttributes
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import android.content.Context
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.media3.common.AudioAttributes
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.PlaybackException
|
||||
@@ -27,6 +26,8 @@ import org.jellyfin.playback.core.backend.BasePlayerBackend
|
||||
import org.jellyfin.playback.core.mediastream.MediaStream
|
||||
import org.jellyfin.playback.core.mediastream.PlayableMediaStream
|
||||
import org.jellyfin.playback.core.mediastream.mediaStream
|
||||
import org.jellyfin.playback.core.mediastream.mediatype.MediaType
|
||||
import org.jellyfin.playback.core.mediastream.mediatype.mediaType
|
||||
import org.jellyfin.playback.core.mediastream.normalizationGain
|
||||
import org.jellyfin.playback.core.model.PlayState
|
||||
import org.jellyfin.playback.core.model.PositionInfo
|
||||
@@ -53,7 +54,9 @@ class ExoPlayerBackend(
|
||||
|
||||
private var currentStream: PlayableMediaStream? = null
|
||||
private var subtitleView: SubtitleView? = null
|
||||
private var audioPipeline = ExoPlayerAudioPipeline()
|
||||
private val audioPipeline = ExoPlayerAudioPipeline()
|
||||
private val audioAttributeState = AudioAttributeState()
|
||||
|
||||
private val exoPlayer by lazy {
|
||||
val dataSourceFactory = DefaultDataSource.Factory(
|
||||
context,
|
||||
@@ -95,9 +98,6 @@ class ExoPlayerBackend(
|
||||
})
|
||||
})
|
||||
.setMediaSourceFactory(mediaSourceFactory)
|
||||
.setAudioAttributes(AudioAttributes.Builder().apply {
|
||||
setUsage(C.USAGE_MEDIA)
|
||||
}.build(), true)
|
||||
.setPauseAtEndOfMediaItems(true)
|
||||
.build()
|
||||
.also { player ->
|
||||
@@ -208,19 +208,33 @@ class ExoPlayerBackend(
|
||||
preparedItemIndex = exoPlayer.mediaItemCount - 1
|
||||
}
|
||||
|
||||
// Determine how to play item
|
||||
if (preparedItemIndex == exoPlayer.currentMediaItemIndex) return
|
||||
|
||||
Timber.i("Playing ${item.mediaStream?.url}")
|
||||
|
||||
// Seek to prepared media item
|
||||
when (preparedItemIndex) {
|
||||
exoPlayer.currentMediaItemIndex - 1 -> exoPlayer.seekToPreviousMediaItem()
|
||||
exoPlayer.currentMediaItemIndex + 1 -> exoPlayer.seekToNextMediaItem()
|
||||
exoPlayer.currentMediaItemIndex -> Unit
|
||||
else -> exoPlayer.seekTo(preparedItemIndex, 0)
|
||||
}
|
||||
|
||||
// Update audio attributes
|
||||
val contentType = when (item.mediaType) {
|
||||
MediaType.Video -> C.AUDIO_CONTENT_TYPE_MOVIE
|
||||
MediaType.Audio -> C.AUDIO_CONTENT_TYPE_MUSIC
|
||||
MediaType.Unknown -> C.AUDIO_CONTENT_TYPE_UNKNOWN
|
||||
}
|
||||
|
||||
audioAttributeState.updateAudioAttributes(
|
||||
builder = {
|
||||
setContentType(contentType)
|
||||
setUsage(C.USAGE_MEDIA)
|
||||
},
|
||||
onChange = { audioAttributes ->
|
||||
exoPlayer.setAudioAttributes(audioAttributes, true)
|
||||
}
|
||||
)
|
||||
|
||||
// Enjoy!
|
||||
Timber.i("Playing ${item.mediaStream?.url}")
|
||||
exoPlayer.play()
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user