Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 0 additions & 82 deletions .github/actions/native-build/action.yml

This file was deleted.

7 changes: 3 additions & 4 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,15 @@ jobs:
submodules: true # Need the submodules to build
- name: Setup
uses: ./.github/actions/setup
- name: Native build
uses: ./.github/actions/native-build
with:
cache: true
- name: Build app
id: buildapp
run: |
./gradlew clean assembleDebug testDebugUnitTest --no-daemon
apks=$(find app/build/outputs/apk -name '*.apk' -print0 | tr '\0' ',' | sed 's/,$//')
echo "apks=$apks" >> "$GITHUB_OUTPUT"
env:
ORG_GRADLE_PROJECT_WholphinExtensionsUsername: "${{ secrets.EXTENSIONS_USERNAME }}"
ORG_GRADLE_PROJECT_WholphinExtensionsPassword: "${{ secrets.EXTENSIONS_PASSWORD }}"
- name: Tar build dirs
run: |
tar -czf build.tgz ./app/.
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,15 @@ jobs:
submodules: true # Need the submodules to build
- name: Setup
uses: ./.github/actions/setup
- name: Native build
uses: ./.github/actions/native-build
with:
cache: false
- name: Build app
id: buildapp
env:
KEY_ALIAS: "${{ secrets.KEY_ALIAS }}"
KEY_PASSWORD: "${{ secrets.KEY_PASSWORD }}"
KEY_STORE_PASSWORD: "${{ secrets.KEY_STORE_PASSWORD }}"
SIGNING_KEY: "${{ secrets.SIGNING_KEY }}"
ORG_GRADLE_PROJECT_WholphinExtensionsUsername: "${{ secrets.EXTENSIONS_USERNAME }}"
ORG_GRADLE_PROJECT_WholphinExtensionsPassword: "${{ secrets.EXTENSIONS_PASSWORD }}"
run: |
./gradlew clean assembleRelease --no-daemon
- name: Verify signatures
Expand Down
72 changes: 37 additions & 35 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@

import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.variant.FilterConfiguration
import com.android.build.gradle.internal.cxx.io.writeTextIfDifferent
import com.android.build.gradle.internal.tasks.factory.dependsOn
import com.google.protobuf.gradle.id
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import java.util.Base64

val isCI = if (System.getenv("CI") != null) System.getenv("CI").toBoolean() else false
val ffmpegModuleExists = project.file("libs/lib-decoder-ffmpeg-release.aar").exists()
val av1ModuleExists = project.file("libs/lib-decoder-av1-release.aar").exists()
val shouldSign = isCI && System.getenv("KEY_ALIAS") != null
val extensionsRepoActive = project.hasProperty("WholphinExtensionsUsername")

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.ksp)
id("kotlin-parcelize")
alias(libs.plugins.apollo)
Expand All @@ -34,7 +33,15 @@ val gitDescribe =
.standardOutput.asText
.getOrElse("v0.0.0")

android {
kotlin {
compilerOptions {
languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_3
jvmTarget = JvmTarget.JVM_11
javaParameters = true
}
}

configure<ApplicationExtension> {
namespace = "com.github.damontecres.stashapp"
compileSdk = 36

Expand Down Expand Up @@ -99,18 +106,6 @@ android {
signingConfig = signingConfigs.getByName("ci")
}
}

applicationVariants.all {
val variant = this
variant.outputs
.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
.forEach { output ->
val abi = output.getFilter("ABI").let { if (it != null) "-$it" else "" }
val outputFileName =
"StashAppAndroidTV-${variant.baseName}-${variant.versionName}-${variant.versionCode}$abi.apk"
output.outputFileName = outputFileName
}
}
}
splits {
abi {
Expand All @@ -125,18 +120,29 @@ android {
targetCompatibility = JavaVersion.VERSION_11
isCoreLibraryDesugaringEnabled = true
}
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_11
javaParameters = true
}
}
lint {
disable.add("MissingTranslation")
disable.add("LocalContextGetResourceValueCall") // TODO
}
room {
schemaDirectory("$projectDir/schemas")
}

room {
schemaDirectory("$projectDir/schemas")
}

androidComponents {
onVariants(selector().all()) { variant ->
variant.outputs
.map { it as com.android.build.api.variant.impl.VariantOutputImpl }
.forEach { output ->
val abi =
output
.getFilter(FilterConfiguration.FilterType.ABI)
.let { if (it != null) "-${it.identifier}" else "" }
val outputFileName =
"StashAppAndroidTV-${variant.flavorName}-${variant.buildType}-${output.versionName.get()}-${output.versionCode.get()}$abi.apk"
output.outputFileName = outputFileName
}
}
}

Expand Down Expand Up @@ -172,11 +178,6 @@ apollo {
packageName.set("com.github.damontecres.stashapp.api")
schemaFile = File("$projectDir/src/main/graphql/schema.graphqls")
generateOptionalOperationVariables.set(false)
outputDirConnection {
// Fixes where classes aren't detected in unit tests
// See: https://community.apollographql.com/t/android-warning-duplicate-content-roots-detected-after-just-adding-apollo3-kotlin-client/4529/6
connectToKotlinSourceSet("main")
}
plugin(project(":apollo-compiler"))
}
}
Expand Down Expand Up @@ -299,11 +300,12 @@ dependencies {
implementation(libs.multiplatform.markdown.renderer)
implementation(libs.multiplatform.markdown.renderer.m3)

if (ffmpegModuleExists || isCI) {
implementation(files("libs/lib-decoder-ffmpeg-release.aar"))
}
if (av1ModuleExists || isCI) {
implementation(files("libs/lib-decoder-av1-release.aar"))
implementation(libs.timber)
implementation(libs.slf4j2.timber)
if (extensionsRepoActive) {
implementation(libs.wholphin.extensions.mpv)
implementation(libs.wholphin.extensions.ffmpeg)
implementation(libs.wholphin.extensions.av1)
}

testImplementation(libs.androidx.test.core.ktx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import org.acra.ReportField
import org.acra.config.dialog
import org.acra.data.StringFormat
import org.acra.ktx.initAcra
import timber.log.Timber

class StashApplication : Application() {
@OptIn(ExperimentalComposeRuntimeApi::class)
Expand All @@ -52,6 +53,8 @@ class StashApplication : Application() {
// )
}

Timber.plant(Timber.DebugTree())

application = this

val pkgInfo = packageManager.getPackageInfo(packageName, 0)
Expand Down
78 changes: 43 additions & 35 deletions app/src/main/java/com/github/damontecres/stashapp/StashExoPlayer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ import androidx.media3.extractor.ts.TsExtractor
import androidx.preference.PreferenceManager
import com.github.damontecres.stashapp.StashExoPlayer.Companion.getInstance
import com.github.damontecres.stashapp.proto.PlaybackBackend
import com.github.damontecres.stashapp.proto.PlaybackHttpClient
import com.github.damontecres.stashapp.proto.PlaybackPreferences
import com.github.damontecres.stashapp.proto.copy
import com.github.damontecres.stashapp.util.Constants
import com.github.damontecres.stashapp.util.SkipParams
import com.github.damontecres.stashapp.util.StashClient
import com.github.damontecres.stashapp.util.StashServer
import com.github.damontecres.stashapp.util.getPreference
import com.github.damontecres.stashapp.util.isNotNullOrBlank
import com.github.damontecres.stashapp.util.mpv.MpvPlayer
import timber.log.Timber

/**
* Manages a static [ExoPlayer] which might be reused between views
Expand All @@ -41,46 +44,40 @@ class StashExoPlayer private constructor() {
private var instance: Player? = null // Volatile modifier is necessary

@Volatile
private var skipParams: SkipParams? = null
private var playbackPreferences: PlaybackPreferences? = null

@OptIn(UnstableApi::class)
fun getInstance(
fun getInstanceForCard(
context: Context,
server: StashServer,
): Player = getInstance(context, server, SkipParams.Default)
): Player =
getInstance(
context,
server,
PlaybackPreferences
.newBuilder()
.apply {
playbackBackend = PlaybackBackend.EXO_PLAYER
skipForwardMs = 30_000
skipBackwardMs = 30_000
}.build(),
)

@OptIn(UnstableApi::class)
fun getInstance(
context: Context,
server: StashServer,
skipParams: SkipParams,
httpClientChoice: String =
getPreference(
context,
R.string.pref_key_playback_http_client,
context.getString(R.string.playback_http_client_okhttp),
)!!,
debugLogging: Boolean =
getPreference(
context,
R.string.pref_key_playback_debug_logging,
false,
),
backend: PlaybackBackend = PlaybackBackend.EXO_PLAYER,
playbackPreferences: PlaybackPreferences,
): Player {
if (instance == null || skipParams != this.skipParams) {
if (instance == null || playbackPreferences != this.playbackPreferences) {
synchronized(this) {
// synchronized to avoid concurrency problem
if (instance == null || skipParams != this.skipParams) {
this.skipParams = skipParams
if (instance == null || playbackPreferences != this.playbackPreferences) {
instance =
createInstance(
context,
server,
skipParams,
httpClientChoice,
debugLogging,
backend,
playbackPreferences,
)
}
}
Expand All @@ -95,19 +92,30 @@ class StashExoPlayer private constructor() {
fun createInstance(
context: Context,
server: StashServer,
skipParams: SkipParams,
httpClientChoice: String,
debugLogging: Boolean,
backend: PlaybackBackend = PlaybackBackend.EXO_PLAYER,
playbackPreferences: PlaybackPreferences,
): Player {
releasePlayer()
Log.i(TAG, "backend=$backend")
return if (backend == PlaybackBackend.MPV) {
MpvPlayer(context, true, false)
Timber.i("backend=%s", playbackPreferences.playbackBackend)
val skipParams =
playbackPreferences.let {
SkipParams.Values(
it.skipForwardMs,
it.skipBackwardMs,
)
}
val httpClient = playbackPreferences.playbackHttpClient
val debugLogging = playbackPreferences.debugLoggingEnabled
this.playbackPreferences = playbackPreferences.copy {}
return if (playbackPreferences.playbackBackend == PlaybackBackend.MPV) {
MpvPlayer(
context,
playbackPreferences.mpvPreferences.hardwareDecoding,
playbackPreferences.mpvPreferences.gpuNext,
)
} else {
val dataSourceFactory =
when (httpClientChoice.lowercase()) {
context.getString(R.string.playback_http_client_okhttp) -> {
when (httpClient) {
PlaybackHttpClient.OKHTTP -> {
OkHttpDataSource
.Factory(server.streamingOkHttpClient)
}
Expand Down Expand Up @@ -215,7 +223,7 @@ class StashExoPlayer private constructor() {
instance!!.release()
}
instance = null
skipParams = null
playbackPreferences = null
}
}
}
Expand Down
Loading
Loading