Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jellyfin/jellyfin-androidtv
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9331be411eb5ac2e74c05773812a22808de86d6d
Choose a base ref
...
head repository: jellyfin/jellyfin-androidtv
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c0ce8f0f1c5d8023d40f779ba7b02674de18ce73
Choose a head ref
  • 14 commits
  • 11 files changed
  • 2 contributors

Commits on Dec 20, 2024

  1. Update dependency gradle to v8.12

    renovate[bot] authored and nielsvanvelzen committed Dec 20, 2024
    Copy the full SHA
    ed9dd72 View commit details
  2. Update dependency io.mockk:mockk to v1.13.14

    renovate[bot] authored and nielsvanvelzen committed Dec 20, 2024
    Copy the full SHA
    4ebb45b View commit details

Commits on Dec 21, 2024

  1. Fix UI audio queue order when shuffling

    nielsvanvelzen committed Dec 21, 2024
    Copy the full SHA
    e87e96e View commit details
  2. Fix useNextIndex never removing first element in ShuffleOrderIndexPro…

    …vider and RandomOrderIndexProvider
    nielsvanvelzen committed Dec 21, 2024
    Copy the full SHA
    5547bbc View commit details
  3. Fix QueueService.next not respecting usePlaybackOrder and useRepeatMo…

    …de properly
    nielsvanvelzen committed Dec 21, 2024
    Copy the full SHA
    25e79e9 View commit details
  4. Prevent AudioNowPlayingFragment from showing without active queue

    nielsvanvelzen committed Dec 21, 2024
    Copy the full SHA
    eb7fd83 View commit details
  5. Fix QueueService.getNextIndices returning one item too many when usin…

    …g REPEAT_ENTRY_ONCE
    nielsvanvelzen committed Dec 21, 2024
    Copy the full SHA
    8b2d398 View commit details
  6. Fix music play action not working after queue has ended

    nielsvanvelzen committed Dec 21, 2024
    Copy the full SHA
    f95f3d4 View commit details
  7. Copy the full SHA
    c18a68a View commit details
  8. Use private entry index in QueueService

    nielsvanvelzen committed Dec 21, 2024
    Copy the full SHA
    1adb9b0 View commit details

Commits on Dec 23, 2024

  1. Update dependency io.insert-koin:koin-androidx-compose to v4.0.1

    renovate[bot] authored and nielsvanvelzen committed Dec 23, 2024
    Copy the full SHA
    f098472 View commit details
  2. Update github/codeql-action action to v3.28.0

    renovate[bot] authored and nielsvanvelzen committed Dec 23, 2024
    Copy the full SHA
    3323442 View commit details
  3. Update koin to v4.0.1

    renovate[bot] authored and nielsvanvelzen committed Dec 23, 2024
    Copy the full SHA
    dae017c View commit details

Commits on Dec 24, 2024

  1. Update Kotlin

    renovate[bot] authored Dec 24, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    c0ce8f0 View commit details
2 changes: 1 addition & 1 deletion .github/workflows/app-lint.yaml
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ jobs:
- name: Run detekt and lint tasks
run: ./gradlew detekt lint
- name: Upload SARIF files
uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
if: ${{ always() }}
with:
sarif_file: .
Original file line number Diff line number Diff line change
@@ -256,14 +256,9 @@ public void onProgress(long pos) {
@Override
public void onQueueStatusChanged(boolean hasQueue) {
Timber.d("Queue status changed (hasQueue=%s)", hasQueue);
if (hasQueue) {
loadItem();
if (mediaManager.getValue().isAudioPlayerInitialized()) {
updateButtons();
}
} else {
if (navigationRepository.getValue().getCanGoBack()) navigationRepository.getValue().goBack();
else navigationRepository.getValue().reset(Destinations.INSTANCE.getHome());
loadItem();
if (mediaManager.getValue().isAudioPlayerInitialized()) {
updateButtons();
}
}

@@ -308,6 +303,9 @@ private void loadItem() {
if (mBaseItem != null) {
updatePoster();
updateInfo(mBaseItem);
} else {
if (navigationRepository.getValue().getCanGoBack()) navigationRepository.getValue().goBack();
else navigationRepository.getValue().navigate(Destinations.INSTANCE.getHome());
}
}

Original file line number Diff line number Diff line change
@@ -31,7 +31,6 @@ import org.jellyfin.playback.jellyfin.queue.createBaseItemQueueEntry
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.MediaType
import kotlin.math.max

@Suppress("TooManyFunctions")
class RewriteMediaManager(
@@ -136,25 +135,23 @@ class RewriteMediaManager(
}.launchIn(this)

playbackManager.queue.entry.onEach { updateAdapter() }.launchIn(this)
playbackManager.state.playbackOrder.onEach { updateAdapter() }.launchIn(this)
}

private fun updateAdapter() {
// Get all items as BaseRowItem
val items = queueSupplier
.items
// Map to audio queue items
.mapIndexed { index, item ->
AudioQueueBaseRowItem(item).apply {
playing = playbackManager.queue.entryIndex.value == index
}
}
// Remove items before currently playing item
.drop(max(0, playbackManager.queue.entryIndex.value))
val currentItem = playbackManager.queue.entry.value?.baseItem?.let(::AudioQueueBaseRowItem)?.apply {
playing = true
}
// It's safe to run this blocking as all items are prefetched via the [BaseItemQueueSupplier]
val upcomingItems = runBlocking { playbackManager.queue.peekNext(100) }
.mapIndexedNotNull { index, item -> item.baseItem?.let(::AudioQueueBaseRowItem) }

val items = listOfNotNull(currentItem) + upcomingItems

// Update item row
currentAudioQueue.replaceAll(
items,
areItemsTheSame = { old, new -> (old as? AudioQueueBaseRowItem)?.baseItem == (new as? AudioQueueBaseRowItem)?.baseItem },
areItemsTheSame = { old, new -> (old as? AudioQueueBaseRowItem)?.baseItem?.id == (new as? AudioQueueBaseRowItem)?.baseItem?.id },
// The equals functions for BaseRowItem only compare by id
areContentsTheSame = { _, _ -> false },
)
@@ -269,7 +266,7 @@ class RewriteMediaManager(

override fun togglePlayPause() {
val playState = playbackManager.state.playState.value
if (playState == PlayState.PAUSED) playbackManager.state.unpause()
if (playState == PlayState.PAUSED || playState == PlayState.STOPPED) playbackManager.state.unpause()
else if (playState == PlayState.PLAYING) playbackManager.state.pause()
}

10 changes: 5 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -30,14 +30,14 @@ java-jdk = "21"
jellyfin-androidx-media = "1.5.0+1"
jellyfin-apiclient = "v0.7.10"
jellyfin-sdk = "1.6.3"
koin = "4.0.0"
koin-compose = "4.0.0"
koin = "4.0.1"
koin-compose = "4.0.1"
kotest = "5.9.1"
kotlin = "2.0.21"
kotlinx-coroutines = "1.9.0"
kotlin = "2.1.0"
kotlinx-coroutines = "1.10.1"
kotlinx-serialization = "1.7.3"
markwon = "4.6.2"
mockk = "1.13.13"
mockk = "1.13.14"
slf4j-timber = "0.0.4"
timber = "5.0.1"

4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=f397b287023acdba1e9f6fc5ea72d22dd63669d59ed4a289a29b1a76eee151c6
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionSha256Sum=7a00d51fb93147819aab76024feece20b6b84e420694101f276be952e08bef03
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
3 changes: 1 addition & 2 deletions gradlew
Original file line number Diff line number Diff line change
@@ -86,8 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
8 changes: 7 additions & 1 deletion playback/core/src/main/kotlin/PlayerState.kt
Original file line number Diff line number Diff line change
@@ -88,7 +88,13 @@ class MutablePlayerState(
_videoSize.value = VideoSize(width, height)
}

override fun onMediaStreamEnd(mediaStream: PlayableMediaStream) = Unit
override fun onMediaStreamEnd(mediaStream: PlayableMediaStream) {
// Make sure to start stream again if repeat mode is turned on
// Note: the QueueService is responsible for changing REPEAT_ENTRY_ONCE to NONE
if (_repeatMode.value != RepeatMode.NONE) {
backendService.backend?.play()
}
}
})

volume = options.playerVolumeState
26 changes: 14 additions & 12 deletions playback/core/src/main/kotlin/queue/QueueService.kt
Original file line number Diff line number Diff line change
@@ -113,14 +113,14 @@ class QueueService internal constructor() : PlayerService(), Queue {
val repeatMode = if (useRepeatMode) state.repeatMode.value else RepeatMode.NONE

return when (repeatMode) {
RepeatMode.NONE -> provider.provideIndices(amount, estimatedSize, currentQueueIndicesPlayed, entryIndex.value)
RepeatMode.NONE -> provider.provideIndices(amount, estimatedSize, currentQueueIndicesPlayed, _entryIndex.value)

RepeatMode.REPEAT_ENTRY_ONCE -> buildList {
add(entryIndex.value)
addAll(provider.provideIndices(amount, estimatedSize, currentQueueIndicesPlayed, entryIndex.value))
RepeatMode.REPEAT_ENTRY_ONCE -> buildList(amount) {
add(_entryIndex.value)
addAll(provider.provideIndices(amount - 1, estimatedSize, currentQueueIndicesPlayed, _entryIndex.value))
}.take(amount)

RepeatMode.REPEAT_ENTRY_INFINITE -> List(amount) { entryIndex.value }
RepeatMode.REPEAT_ENTRY_INFINITE -> List(amount) { _entryIndex.value }
}
}

@@ -132,13 +132,15 @@ class QueueService internal constructor() : PlayerService(), Queue {

override suspend fun next(usePlaybackOrder: Boolean, useRepeatMode: Boolean): QueueEntry? {
val index = getNextIndices(1, usePlaybackOrder, useRepeatMode).firstOrNull() ?: return null
if (usePlaybackOrder) {
// Automatically set repeat mode back to none when using the ONCE option
if (state.repeatMode.value == RepeatMode.REPEAT_ENTRY_ONCE && index == this._entryIndex.value) {
state.setRepeatMode(RepeatMode.NONE)
} else if (state.repeatMode.value == RepeatMode.NONE) {
orderIndexProvider.useNextIndex()
}

val provider = if (usePlaybackOrder) orderIndexProvider else defaultOrderIndexProvider
val repeatMode = if (useRepeatMode) state.repeatMode.value else RepeatMode.NONE

// Automatically set repeat mode back to none when using the ONCE option
if (repeatMode == RepeatMode.REPEAT_ENTRY_ONCE && index == this._entryIndex.value) {
state.setRepeatMode(RepeatMode.NONE)
} else if (repeatMode == RepeatMode.NONE) {
provider.useNextIndex()
}

return setIndex(index, true)
Original file line number Diff line number Diff line change
@@ -23,6 +23,6 @@ internal class RandomOrderIndexProvider : OrderIndexProvider {
}

override fun useNextIndex() {
nextIndices.remove(0)
nextIndices.removeAt(0)
}
}
Original file line number Diff line number Diff line change
@@ -34,6 +34,6 @@ internal class ShuffleOrderIndexProvider : OrderIndexProvider {
}

override fun useNextIndex() {
nextIndices.remove(0)
nextIndices.removeAt(0)
}
}
2 changes: 2 additions & 0 deletions playback/media3/exoplayer/src/main/kotlin/ExoPlayerBackend.kt
Original file line number Diff line number Diff line change
@@ -209,6 +209,8 @@ class ExoPlayerBackend(
}

override fun play() {
// If the item has ended, revert first so the item will start over again
if (exoPlayer.playbackState == Player.STATE_ENDED) exoPlayer.seekTo(0)
exoPlayer.play()
}