Add support for cinema mode (#1305)

## Description
Adds support for cinema mode, which is enabled by default.

When enabled and if starting playback from the beginning, the server is
queried for any "intros", ie prerolls or trailers, to play first. These
are shown in the queue and can be skipped if desired.

The server has to provide the intros, so a plugin like
https://github.com/jellyfin/jellyfin-plugin-intros or
https://github.com/CherryFloors/jellyfin-plugin-cinemamode is required
server-side.

### Related issues
Closes #418
Closes #1180

### Testing
Emulator and server w/
https://github.com/CherryFloors/jellyfin-plugin-cinemamode

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Damontecres 2026-04-26 10:16:26 -04:00 • committed by GitHub
parent ea6a0227b0
commit edb37f5d69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 170 additions and 64 deletions

View file

@ -19,6 +19,7 @@ import com.github.damontecres.wholphin.preferences.updateMpvOptions
import com.github.damontecres.wholphin.preferences.updateMusicPreferences
import com.github.damontecres.wholphin.preferences.updatePhotoPreferences
import com.github.damontecres.wholphin.preferences.updatePlaybackOverrides
import com.github.damontecres.wholphin.preferences.updatePlaybackPreferences
import com.github.damontecres.wholphin.preferences.updateScreensaverPreferences
import com.github.damontecres.wholphin.preferences.updateSubtitlePreferences
import com.github.damontecres.wholphin.ui.preferences.PreferencesViewModel
@ -327,5 +328,11 @@ class AppUpgradeHandler
}
}
}
if (previous.isEqualOrBefore(Version.fromString("0.6.2-18-g0"))) {
appPreferences.updateData {
it.updatePlaybackPreferences { cinemaMode = AppPreference.CinemaMode.defaultValue }
}
}
}
}

View file

@ -7,12 +7,14 @@ import com.github.damontecres.wholphin.data.model.BaseItem
import com.github.damontecres.wholphin.data.model.GetItemsFilter
import com.github.damontecres.wholphin.data.model.Playlist
import com.github.damontecres.wholphin.data.model.PlaylistInfo
import com.github.damontecres.wholphin.data.model.PlaylistItem
import com.github.damontecres.wholphin.ui.DefaultItemFields
import com.github.damontecres.wholphin.ui.components.baseItemKinds
import com.github.damontecres.wholphin.ui.data.SortAndDirection
import com.github.damontecres.wholphin.ui.gt
import com.github.damontecres.wholphin.ui.indexOfFirstOrNull
import com.github.damontecres.wholphin.ui.playback.playable
import com.github.damontecres.wholphin.ui.toBaseItems
import com.github.damontecres.wholphin.ui.toServerString
import com.github.damontecres.wholphin.util.ApiRequestPager
import com.github.damontecres.wholphin.util.GetEpisodesRequestHandler
@ -22,6 +24,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.playlistsApi
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
import org.jellyfin.sdk.api.client.extensions.videosApi
import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind
@ -247,14 +250,14 @@ class PlaylistCreator
-> {
val list =
buildList {
add(BaseItem(item, false))
add(PlaylistItem.Media(BaseItem(item, false)))
if (item.partCount.gt(1)) {
api.videosApi
.getAdditionalPart(item.id)
.content.items
.map {
BaseItem(it, false)
PlaylistItem.Media(BaseItem(it, false))
}.let(::addAll)
}
}
@ -274,14 +277,14 @@ class PlaylistCreator
}
}
private suspend fun List<BaseItemDto>.convertAndAddParts(useSeriesForPrimary: Boolean = false): List<BaseItem> =
private suspend fun List<BaseItemDto>.convertAndAddParts(useSeriesForPrimary: Boolean = false): List<PlaylistItem> =
buildList {
this@convertAndAddParts.forEach { ep ->
add(BaseItem(ep, useSeriesForPrimary))
add(PlaylistItem.Media(BaseItem(ep, useSeriesForPrimary)))
if (ep.partCount.gt(1)) {
val parts =
api.videosApi.getAdditionalPart(ep.id).content.items.map { part ->
BaseItem(part, useSeriesForPrimary)
PlaylistItem.Media(BaseItem(part, useSeriesForPrimary))
}
addAll(parts)
}