From 526e4246211880085d08a7c562eb796ec11a8632 Mon Sep 17 00:00:00 2001 From: meowarex Date: Fri, 14 Aug 2026 06:21:00 +0000 Subject: [PATCH] Kawarp Shader <3 --- .gitignore | 3 + Manager/app/build.gradle.kts | 4 +- .../app/src/main/assets/patches-manifest.json | 218 ++- .../components/PatchAdvancedOptionsSheet.kt | 3 + .../ui/screens/patchopts/PatchSpec.kt | 29 +- .../components/PatchAdvancedOptionsSheet.kt | 3 + README.md | 18 + .../extension/dev/kawarp/KawarpEngine.smali | 1300 +++++++++++++++++ patches/extension/radiant/HomeBackdrop.smali | 22 +- patches/extension/radiant/Kawarp.smali | 847 +++++++++++ patches/manifest.json | 218 ++- patches/player-backdrop-animated.patch | 121 -- patches/player-backdrop-kawarp.patch | 79 + patches/player-backdrop-static.patch | 121 -- tools/kawarp-build/build.sh | 89 ++ tools/kawarp-build/src/radiant/Kawarp.java | 225 +++ tools/kawarp-build/stubs/am0/a.java | 3 + tools/kawarp-build/stubs/am0/l.java | 3 + .../compose/foundation/layout/SizeKt.java | 5 + .../compose/foundation/layout/SpacerKt.java | 6 + .../androidx/compose/runtime/Composer.java | 5 + .../compose/runtime/MutableState.java | 2 + .../runtime/SnapshotMutationPolicy.java | 2 + .../compose/runtime/SnapshotStateKt.java | 4 + .../stubs/androidx/compose/runtime/State.java | 2 + .../stubs/androidx/compose/ui/Modifier.java | 6 + .../compose/ui/draw/DrawModifierKt.java | 5 + .../androidx/compose/ui/geometry/Size.java | 7 + .../ui/graphics/AndroidCanvas_androidKt.java | 4 + .../androidx/compose/ui/graphics/Canvas.java | 2 + .../ui/graphics/drawscope/DrawContext.java | 3 + .../ui/graphics/drawscope/DrawScope.java | 6 + .../playerscreen/ui/composables/p3.java | 8 + .../ui/model/PlayerBackgroundStyle.java | 2 + tools/kawarp-build/stubs/kotlin/u.java | 3 + 35 files changed, 3051 insertions(+), 327 deletions(-) create mode 100644 patches/extension/dev/kawarp/KawarpEngine.smali create mode 100644 patches/extension/radiant/Kawarp.smali delete mode 100644 patches/player-backdrop-animated.patch create mode 100644 patches/player-backdrop-kawarp.patch delete mode 100644 patches/player-backdrop-static.patch create mode 100755 tools/kawarp-build/build.sh create mode 100644 tools/kawarp-build/src/radiant/Kawarp.java create mode 100644 tools/kawarp-build/stubs/am0/a.java create mode 100644 tools/kawarp-build/stubs/am0/l.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/foundation/layout/SizeKt.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/foundation/layout/SpacerKt.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/runtime/Composer.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/runtime/MutableState.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotMutationPolicy.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotStateKt.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/runtime/State.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/ui/Modifier.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/ui/draw/DrawModifierKt.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/ui/geometry/Size.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/ui/graphics/AndroidCanvas_androidKt.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/ui/graphics/Canvas.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawContext.java create mode 100644 tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawScope.java create mode 100644 tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/composables/p3.java create mode 100644 tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle.java create mode 100644 tools/kawarp-build/stubs/kotlin/u.java diff --git a/.gitignore b/.gitignore index d792100..abc558d 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ Reference/ !tidal-apk/*.apk !tidal-apk/*.apkm tidal-apk/*/ + +# Kawarp-AGSL library (CLONE HERE! the build tooling in tools/kawarp-build expects it) +tools/kawarp-agsl diff --git a/Manager/app/build.gradle.kts b/Manager/app/build.gradle.kts index f90d15d..4094cd7 100644 --- a/Manager/app/build.gradle.kts +++ b/Manager/app/build.gradle.kts @@ -31,8 +31,8 @@ android { defaultConfig { minSdk = 24 targetSdk = 36 - versionCode = 53 - versionName = "1.0.1" + versionCode = 62 + versionName = "1.7.7" vectorDrawables { useSupportLibrary = true diff --git a/Manager/app/src/main/assets/patches-manifest.json b/Manager/app/src/main/assets/patches-manifest.json index 333c5f4..48649cd 100644 --- a/Manager/app/src/main/assets/patches-manifest.json +++ b/Manager/app/src/main/assets/patches-manifest.json @@ -14,17 +14,16 @@ "DebugMenuUnlock" ], "disables": [ - "LyricsDisableCover", - "LyricsReplaceLyricsButton", - "LyricsReplaceShareButton", "LyricsRlApi", - "LyricsKeepControlsVisible", "PlayerBackdrop", "QualityBadgeColors", "PlayerMovePlayingFrom", "PlayerOneHanded", "LyricsProgressPill", - "MiniPlayerRedesign" + "LyricsDisableCover", + "LyricsReplaceLyricsButton", + "LyricsReplaceShareButton", + "LyricsKeepControlsVisible" ] }, { @@ -119,36 +118,29 @@ "order": 30, "fileNames": [], "title": "Player Backdrop", - "description": "Lets you fully adjust how the player backdrop blur looks and behaves", + "description": "Swap the player backdrop for the Kawarp shader, or fine-tune TIDAL's own blurred cover", "default": true, - "defaultVariantIndex": 2, + "defaultVariantIndex": 1, "variants": [ { - "title": "Static", - "fileNames": [ - "player-backdrop-static.patch" - ], - "extensionFiles": [ - "radiant/BackdropFx.smali" - ] - }, - { - "title": "Animated", - "fileNames": [ - "player-backdrop-animated.patch" - ], - "extensionFiles": [ - "radiant/BackdropFx.smali" - ] - }, - { - "title": "Playback", + "title": "Tidal", "fileNames": [ "player-backdrop-playback.patch" ], "extensionFiles": [ "radiant/BackdropFx.smali" ] + }, + { + "title": "Radiant", + "fileNames": [ + "player-backdrop-kawarp.patch" + ], + "extensionFiles": [ + "radiant/Kawarp.smali", + "dev/kawarp/KawarpEngine.smali" + ], + "minSdk": 33 } ], "advancedOptions": [ @@ -166,7 +158,8 @@ "encode": { "kind": "int", "scale": 1.0 - } + }, + "requiresVariant": 0 }, { "type": "slider", @@ -182,7 +175,8 @@ "encode": { "kind": "floatBits", "scale": 0.02 - } + }, + "requiresVariant": 0 }, { "type": "slider", @@ -198,7 +192,8 @@ "encode": { "kind": "floatBits", "scale": 0.02 - } + }, + "requiresVariant": 0 }, { "type": "slider", @@ -214,7 +209,170 @@ "encode": { "kind": "floatBits", "scale": 0.02 - } + }, + "requiresVariant": 0 + }, + { + "type": "toggle", + "key": "kawarp_reactive", + "title": "Playback Reactive", + "description": "Cover shader reacts to playback state by freezing/resuming", + "default": true, + "token": "RL_KW_REACTIVE", + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_blur", + "title": "Blur Passes", + "description": "Kawase blur passes, higher is softer but costs more GPU", + "default": 5, + "min": 1, + "max": 40, + "steps": 38, + "displayAsPercent": false, + "token": "RL_KW_BLUR", + "encode": { + "kind": "int", + "scale": 1.0 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_warp", + "title": "Warp Intensity", + "description": "Strength of the fluidity effect", + "default": 100, + "min": 0, + "max": 100, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_WARP", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_speed", + "title": "Animation Speed", + "description": "How fast the backdrop flows", + "default": 175, + "min": 0, + "max": 500, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_SPEED", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_scale", + "title": "Backdrop Scale", + "description": "Zoom level of the effect", + "default": 100, + "min": 10, + "max": 400, + "steps": 12, + "displayAsPercent": true, + "token": "RL_KW_SCALE", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_contrast", + "title": "Contrast", + "description": "Contrast of the backdrop", + "default": 125, + "min": 0, + "max": 300, + "steps": 11, + "displayAsPercent": true, + "token": "RL_KW_CONTRAST", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_saturation", + "title": "Saturation", + "description": "Colour intensity of the backdrop", + "default": 125, + "min": 0, + "max": 400, + "steps": 15, + "displayAsPercent": true, + "token": "RL_KW_SAT", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_brightness", + "title": "Brightness", + "description": "The value of Brightness applied to the backdrop", + "default": 100, + "min": 0, + "max": 200, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_BRIGHT", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_darken", + "title": "Auto Darken Bright Covers", + "description": "Prevents bright covers from making text unreadable", + "default": 80, + "min": 0, + "max": 100, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_DARKEN", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_dither", + "title": "Dithering", + "description": "Breaks up color banding in smooth gradients", + "default": 15, + "min": 0, + "max": 100, + "steps": 19, + "displayAsPercent": false, + "token": "RL_KW_DITHER", + "encode": { + "kind": "floatBits", + "scale": 0.001 + }, + "requiresVariant": 1 }, { "type": "toggle", diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/legacy/screens/patchopts/components/PatchAdvancedOptionsSheet.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/legacy/screens/patchopts/components/PatchAdvancedOptionsSheet.kt index bedc50b..ea29b2e 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/legacy/screens/patchopts/components/PatchAdvancedOptionsSheet.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/legacy/screens/patchopts/components/PatchAdvancedOptionsSheet.kt @@ -37,6 +37,7 @@ import com.meowarex.rlmobile.ui.legacy.components.ResetToDefaultButton import com.meowarex.rlmobile.ui.screens.patchopts.OptionLock import com.meowarex.rlmobile.ui.screens.patchopts.OptionSpec import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionState +import com.meowarex.rlmobile.ui.screens.patchopts.hiddenForVariant import com.meowarex.rlmobile.ui.screens.patchopts.optionLock import com.meowarex.rlmobile.ui.screens.patchopts.PatchSpec import kotlinx.coroutines.launch @@ -109,6 +110,8 @@ fun PatchAdvancedOptionsSheet( when { option is OptionSpec.Toggle && option.inline -> false option is OptionSpec.Toggle && option.requiresOption in parentKeys -> false + // Options belonging to another variant are hidden, not greyed out. + option.hiddenForVariant(selectedVariant) -> false else -> true } } diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt index 206b1f2..3b945e6 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/PatchSpec.kt @@ -1,6 +1,7 @@ package com.meowarex.rlmobile.ui.screens.patchopts import android.content.Context +import android.os.Build import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable import kotlinx.serialization.SerialName @@ -49,7 +50,13 @@ data class VariantSpec( val fileNames: List = emptyList(), val extensionFiles: List = emptyList(), val enabled: Boolean = true, -) + /** + * Hidden from the picker on devices below this API level (AGSL needs 33) + */ + val minSdk: Int = 0, +) { + val supportedHere: Boolean get() = Build.VERSION.SDK_INT >= minSdk +} /** A single advanced option. Discriminated by `"type"` in JSON. */ @Serializable @@ -101,6 +108,8 @@ sealed interface OptionSpec { val token: String? = null, /** How the chosen value becomes the smali literal that replaces the token. */ val encode: SmaliEncode? = null, + /** Hidden unless this variant index is the selected one. */ + val requiresVariant: Int? = null, ) : OptionSpec { val valueRange: ClosedFloatingPointRange get() = min..max } @@ -187,7 +196,9 @@ fun PatchSpec.effectiveVariants(isOptionOn: (OptionSpec.Toggle) -> Boolean): Lis } } return variants.mapIndexedNotNull { index, variant -> - if (index in hidden) null + // Everything downstream (variantIndex -> resolveVariantIndex) picks from this list, so + // dropping an unsupported variant here also keeps the patcher from ever applying it. + if (index in hidden || !variant.supportedHere) null else EffectiveVariant(index, relabel[index] ?: variant.title, variant.enabled) } } @@ -206,6 +217,20 @@ fun PatchSpec.resolveVariantIndex(stored: Int, isOptionOn: (OptionSpec.Toggle) - ?: visible.first().originalIndex } +/** + * The variant this option belongs to + */ +val OptionSpec.variantGate: Int? + get() = when (this) { + is OptionSpec.Toggle -> requiresVariant + is OptionSpec.Slider -> requiresVariant + is OptionSpec.Choice -> null + is OptionSpec.Color -> null + } + +fun OptionSpec.hiddenForVariant(selectedVariant: Int): Boolean = + variantGate.let { it != null && it != selectedVariant } + sealed interface OptionLock { data object Free : OptionLock data class NeedsVariant(val title: String) : OptionLock diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchAdvancedOptionsSheet.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchAdvancedOptionsSheet.kt index 5435750..6a34223 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchAdvancedOptionsSheet.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/components/PatchAdvancedOptionsSheet.kt @@ -43,6 +43,7 @@ import com.meowarex.rlmobile.ui.components.ResetToDefaultButton import com.meowarex.rlmobile.ui.screens.patchopts.OptionLock import com.meowarex.rlmobile.ui.screens.patchopts.OptionSpec import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionState +import com.meowarex.rlmobile.ui.screens.patchopts.hiddenForVariant import com.meowarex.rlmobile.ui.screens.patchopts.optionLock import com.meowarex.rlmobile.ui.screens.patchopts.PatchSpec import kotlinx.coroutines.launch @@ -115,6 +116,8 @@ fun PatchAdvancedOptionsSheet( when { option is OptionSpec.Toggle && option.inline -> false option is OptionSpec.Toggle && option.requiresOption in parentKeys -> false + // Options belonging to another variant are hidden, not greyed out. + option.hiddenForVariant(selectedVariant) -> false else -> true } } diff --git a/README.md b/README.md index f05b4a9..a8d85d0 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,24 @@ Each patch file targets a specific class via its `--- a/` header — the filenam - Comment EACH patch line on the end with a simple 1-5 word description of what it does/or is for - Make sure the patch file name is descriptive of what it does +### The Kawarp extension (generated smali) + +`patches/extension/radiant/Kawarp.smali` and `patches/extension/dev/kawarp/KawarpEngine.smali` +are **generated — don't hand-edit them**. The engine comes from the +[Kawarp-AGSL](https://github.com/meowarex/kawarp-agsl) library, which the build tooling expects +cloned inside `tools/` (the clone is gitignored): + +```bash +git clone https://github.com/meowarex/kawarp-agsl tools/kawarp-agsl +``` + +To change the TIDAL glue, edit `tools/kawarp-build/src/radiant/Kawarp.java`; to change the +effect itself, PR the Kawarp-AGSL repo. Then regenerate and commit the refreshed smali: + +```bash +./tools/kawarp-build/build.sh +``` + ### Submitting Fork the repo, add your patch to `patches/`, and open a PR describing what it changes and why. - Patch PR should be prefixed with `[patch]` in the title diff --git a/patches/extension/dev/kawarp/KawarpEngine.smali b/patches/extension/dev/kawarp/KawarpEngine.smali new file mode 100644 index 0000000..168027e --- /dev/null +++ b/patches/extension/dev/kawarp/KawarpEngine.smali @@ -0,0 +1,1300 @@ +.class public final Ldev/kawarp/KawarpEngine; +.super Ljava/lang/Object; + +# interfaces +.implements Ljava/lang/Runnable; + + +# static fields +.field private static final AGSL:Ljava/lang/String; = "uniform shader texA;\nuniform shader texB;\nuniform float2 uRes;\nuniform float uTime;\nuniform float uBlend;\nuniform float uWarp;\nuniform float uSat;\nuniform float uDither;\nuniform float uScale;\nuniform float uBright;\nuniform float uContrast;\n\nfloat3 m289_3(float3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nfloat2 m289_2(float2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nfloat3 permute(float3 x) { return m289_3(((x * 34.0) + 1.0) * x); }\n\nfloat snoise(float2 v) {\n float4 C = float4(0.211324865405187, 0.366025403784439,\n -0.577350269189626, 0.024390243902439);\n float2 i = floor(v + dot(v, C.yy));\n float2 x0 = v - i + dot(i, C.xx);\n float2 i1 = (x0.x > x0.y) ? float2(1.0, 0.0) : float2(0.0, 1.0);\n float4 x12 = x0.xyxy + C.xxzz;\n x12.xy -= i1;\n i = m289_2(i);\n float3 p = permute(permute(i.y + float3(0.0, i1.y, 1.0)) + i.x + float3(0.0, i1.x, 1.0));\n float3 m = max(0.5 - float3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);\n m = m * m;\n m = m * m;\n float3 x = 2.0 * fract(p * C.www) - 1.0;\n float3 h = abs(x) - 0.5;\n float3 ox = floor(x + 0.5);\n float3 a0 = x - ox;\n m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);\n float3 g;\n g.x = a0.x * x0.x + h.x * x0.y;\n g.yz = a0.yz * x12.xz + h.yz * x12.yw;\n return 130.0 * dot(m, g);\n}\n\nfloat hash13(float3 seed) {\n float3 q = fract(seed * 0.1031);\n q += dot(q, q.zyx + 31.32);\n return fract((q.x + q.y) * q.z);\n}\n\nhalf4 main(float2 fragCoord) {\n float2 uv0 = fragCoord / uRes;\n float2 uv = clamp((uv0 - 0.5) / uScale + 0.5, 0.0, 1.0);\n\n float t = uTime * 0.05;\n float2 c = uv - 0.5;\n float centerWeight = 1.0 - smoothstep(0.0, 0.7, length(c));\n float n1 = snoise(uv * 0.35 + float2(t, t * 0.7));\n float n2 = snoise(uv * 0.35 + float2(-t * 0.8, t * 0.5) + float2(50.0, 50.0));\n float n3 = snoise(uv * 0.9 + float2(t * 1.2, -t) + float2(100.0, 0.0));\n float n4 = snoise(uv * 0.9 + float2(-t, t * 1.1) + float2(0.0, 100.0));\n float2 warp = float2(n1 * 0.65 + n3 * 0.35, n2 * 0.65 + n4 * 0.35) * centerWeight;\n float2 wuv = clamp(uv + warp * uWarp, 0.0, 1.0);\n\n float2 sp = wuv * 128.0;\n float3 col = mix(float3(texA.eval(sp).rgb), float3(texB.eval(sp).rgb), uBlend);\n\n float2 c2 = uv0 - 0.5;\n col *= 1.0 - dot(c2, c2) * 0.3;\n float gray = dot(col, float3(0.299, 0.587, 0.114));\n col = mix(float3(gray), col, uSat);\n float n = hash13(float3(floor(uv0 * uRes), floor(uTime * 60.0)));\n col += (n - 0.5) * uDither;\n\n col = (col - 0.5) * uContrast + 0.5;\n col *= uBright;\n return half4(half3(clamp(col, 0.0, 1.0)), 1.0);\n}\n" + +.field private static final BLUR_SIZE:I = 0x80 + +.field private static final CEIL_MAX:F = 0.15f + +.field private static final CEIL_MIN:F = 0.9f + +.field private static final LOADER:Ljava/util/concurrent/ExecutorService; + +.field private static final MIN_BRIGHTNESS:F = 0.15f + +.field private static final RAMP_SECONDS:F = 1.8f + + +# instance fields +.field private volatile animationSpeed:F + +.field private volatile autoDarken:F + +.field private volatile blurPasses:I + +.field private volatile brightness:F + +.field private volatile contrast:F + +.field private volatile coverToken:I + +.field private volatile darkenBrightness:F + +.field private volatile dithering:F + +.field private lastFrameUptime:J + +.field private volatile nextShader:Landroid/graphics/BitmapShader; + +.field private final paint:Landroid/graphics/Paint; + +.field private volatile pendingCover:Landroid/graphics/Bitmap; + +.field private volatile playbackReactive:Z + +.field private volatile playing:Z + +.field private volatile prevShader:Landroid/graphics/BitmapShader; + +.field private volatile saturation:F + +.field private volatile scale:F + +.field private final shader:Landroid/graphics/RuntimeShader; + +.field private shaderTime:F + +.field private speedFactor:F + +.field private volatile tintB:F + +.field private volatile tintG:F + +.field private volatile tintIntensity:F + +.field private volatile tintR:F + +.field private volatile transitionMs:I + +.field private volatile transitionStart:J + +.field private volatile warpIntensity:F + + +# direct methods +.method static constructor ()V + .registers 1 + + invoke-static {}, Ljava/util/concurrent/Executors;->newSingleThreadExecutor()Ljava/util/concurrent/ExecutorService; + + move-result-object v0 + + sput-object v0, Ldev/kawarp/KawarpEngine;->LOADER:Ljava/util/concurrent/ExecutorService; + + return-void +.end method + +.method public constructor ()V + .registers 3 + + invoke-direct {p0}, Ljava/lang/Object;->()V + + const/high16 v0, 0x3f800000 # 1.0f + + iput v0, p0, Ldev/kawarp/KawarpEngine;->warpIntensity:F + + const/16 v1, 0x8 + + iput v1, p0, Ldev/kawarp/KawarpEngine;->blurPasses:I + + iput v0, p0, Ldev/kawarp/KawarpEngine;->animationSpeed:F + + const/high16 v1, 0x3fc00000 # 1.5f + + iput v1, p0, Ldev/kawarp/KawarpEngine;->saturation:F + + const v1, 0x3c03126f # 0.008f + + iput v1, p0, Ldev/kawarp/KawarpEngine;->dithering:F + + iput v0, p0, Ldev/kawarp/KawarpEngine;->scale:F + + iput v0, p0, Ldev/kawarp/KawarpEngine;->contrast:F + + iput v0, p0, Ldev/kawarp/KawarpEngine;->brightness:F + + const/4 v1, 0x0 + + iput v1, p0, Ldev/kawarp/KawarpEngine;->autoDarken:F + + const/16 v1, 0x3e8 + + iput v1, p0, Ldev/kawarp/KawarpEngine;->transitionMs:I + + const v1, 0x3e20c49c # 0.157f + + iput v1, p0, Ldev/kawarp/KawarpEngine;->tintR:F + + iput v1, p0, Ldev/kawarp/KawarpEngine;->tintG:F + + const v1, 0x3e70a3d7 # 0.235f + + iput v1, p0, Ldev/kawarp/KawarpEngine;->tintB:F + + const v1, 0x3e19999a # 0.15f + + iput v1, p0, Ldev/kawarp/KawarpEngine;->tintIntensity:F + + const/4 v1, 0x0 + + iput-boolean v1, p0, Ldev/kawarp/KawarpEngine;->playbackReactive:Z + + const/4 v1, 0x1 + + iput-boolean v1, p0, Ldev/kawarp/KawarpEngine;->playing:Z + + new-instance v1, Landroid/graphics/Paint; + + invoke-direct {v1}, Landroid/graphics/Paint;->()V + + iput-object v1, p0, Ldev/kawarp/KawarpEngine;->paint:Landroid/graphics/Paint; + + iput v0, p0, Ldev/kawarp/KawarpEngine;->darkenBrightness:F + + iput v0, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F + + invoke-static {}, Ldev/kawarp/KawarpEngine;->isSupported()Z + + move-result v0 + + if-eqz v0, :cond_55 + + new-instance v0, Landroid/graphics/RuntimeShader; + + const-string v1, "uniform shader texA;\nuniform shader texB;\nuniform float2 uRes;\nuniform float uTime;\nuniform float uBlend;\nuniform float uWarp;\nuniform float uSat;\nuniform float uDither;\nuniform float uScale;\nuniform float uBright;\nuniform float uContrast;\n\nfloat3 m289_3(float3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nfloat2 m289_2(float2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }\nfloat3 permute(float3 x) { return m289_3(((x * 34.0) + 1.0) * x); }\n\nfloat snoise(float2 v) {\n float4 C = float4(0.211324865405187, 0.366025403784439,\n -0.577350269189626, 0.024390243902439);\n float2 i = floor(v + dot(v, C.yy));\n float2 x0 = v - i + dot(i, C.xx);\n float2 i1 = (x0.x > x0.y) ? float2(1.0, 0.0) : float2(0.0, 1.0);\n float4 x12 = x0.xyxy + C.xxzz;\n x12.xy -= i1;\n i = m289_2(i);\n float3 p = permute(permute(i.y + float3(0.0, i1.y, 1.0)) + i.x + float3(0.0, i1.x, 1.0));\n float3 m = max(0.5 - float3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);\n m = m * m;\n m = m * m;\n float3 x = 2.0 * fract(p * C.www) - 1.0;\n float3 h = abs(x) - 0.5;\n float3 ox = floor(x + 0.5);\n float3 a0 = x - ox;\n m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);\n float3 g;\n g.x = a0.x * x0.x + h.x * x0.y;\n g.yz = a0.yz * x12.xz + h.yz * x12.yw;\n return 130.0 * dot(m, g);\n}\n\nfloat hash13(float3 seed) {\n float3 q = fract(seed * 0.1031);\n q += dot(q, q.zyx + 31.32);\n return fract((q.x + q.y) * q.z);\n}\n\nhalf4 main(float2 fragCoord) {\n float2 uv0 = fragCoord / uRes;\n float2 uv = clamp((uv0 - 0.5) / uScale + 0.5, 0.0, 1.0);\n\n float t = uTime * 0.05;\n float2 c = uv - 0.5;\n float centerWeight = 1.0 - smoothstep(0.0, 0.7, length(c));\n float n1 = snoise(uv * 0.35 + float2(t, t * 0.7));\n float n2 = snoise(uv * 0.35 + float2(-t * 0.8, t * 0.5) + float2(50.0, 50.0));\n float n3 = snoise(uv * 0.9 + float2(t * 1.2, -t) + float2(100.0, 0.0));\n float n4 = snoise(uv * 0.9 + float2(-t, t * 1.1) + float2(0.0, 100.0));\n float2 warp = float2(n1 * 0.65 + n3 * 0.35, n2 * 0.65 + n4 * 0.35) * centerWeight;\n float2 wuv = clamp(uv + warp * uWarp, 0.0, 1.0);\n\n float2 sp = wuv * 128.0;\n float3 col = mix(float3(texA.eval(sp).rgb), float3(texB.eval(sp).rgb), uBlend);\n\n float2 c2 = uv0 - 0.5;\n col *= 1.0 - dot(c2, c2) * 0.3;\n float gray = dot(col, float3(0.299, 0.587, 0.114));\n col = mix(float3(gray), col, uSat);\n float n = hash13(float3(floor(uv0 * uRes), floor(uTime * 60.0)));\n col += (n - 0.5) * uDither;\n\n col = (col - 0.5) * uContrast + 0.5;\n col *= uBright;\n return half4(half3(clamp(col, 0.0, 1.0)), 1.0);\n}\n" + + invoke-direct {v0, v1}, Landroid/graphics/RuntimeShader;->(Ljava/lang/String;)V + + iput-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + return-void + + :cond_55 + new-instance v0, Ljava/lang/IllegalStateException; + + const-string v1, "KawarpEngine needs API 33+ (AGSL)" + + invoke-direct {v0, v1}, Ljava/lang/IllegalStateException;->(Ljava/lang/String;)V + + throw v0 +.end method + +.method private brightnessFor(F)F + .registers 6 + + iget v0, p0, Ldev/kawarp/KawarpEngine;->autoDarken:F + + const/4 v1, 0x0 + + cmpg-float v2, v0, v1 + + const/high16 v3, 0x3f800000 # 1.0f + + if-lez v2, :cond_23 + + cmpg-float v1, p1, v1 + + if-gtz v1, :cond_e + + goto :goto_23 + + :cond_e + const/high16 v1, 0x3f400000 # 0.75f + + mul-float/2addr v0, v1 + + const v1, 0x3f666666 # 0.9f + + sub-float/2addr v1, v0 + + cmpg-float v0, p1, v1 + + if-gtz v0, :cond_1a + + return v3 + + :cond_1a + div-float/2addr v1, p1 + + const p1, 0x3e19999a # 0.15f + + invoke-static {v1, p1}, Ljava/lang/Math;->max(FF)F + + move-result p1 + + return p1 + + :cond_23 + :goto_23 + return v3 +.end method + +.method private static channel(F)I + .registers 2 + + const/high16 v0, 0x437f0000 # 255.0f + + mul-float/2addr p0, v0 + + const/high16 v0, 0x3f000000 # 0.5f + + add-float/2addr p0, v0 + + float-to-int p0, p0 + + if-gez p0, :cond_b + + const/4 p0, 0x0 + + goto :goto_10 + + :cond_b + const/16 v0, 0xff + + if-le p0, v0, :cond_10 + + move p0, v0 + + :cond_10 + :goto_10 + return p0 +.end method + +.method private static clamp(I)I + .registers 2 + + if-gez p0, :cond_4 + + const/4 p0, 0x0 + + goto :goto_a + + :cond_4 + const/16 v0, 0x80 + + if-lt p0, v0, :cond_a + + const/16 p0, 0x7f + + :cond_a + :goto_a + return p0 +.end method + +.method public static isSupported()Z + .registers 2 + + sget v0, Landroid/os/Build$VERSION;->SDK_INT:I + + const/16 v1, 0x21 + + if-lt v0, v1, :cond_8 + + const/4 v0, 0x1 + + goto :goto_9 + + :cond_8 + const/4 v0, 0x0 + + :goto_9 + return v0 +.end method + +.method private static kawasePass([F[FI)V + .registers 16 + + add-int/lit8 v0, p2, 0x1 + + neg-int v1, v0 + + neg-int v2, p2 + + filled-new-array {v1, v2, p2, v0}, [I + + move-result-object p2 + + const/4 v0, 0x0 + + move v1, v0 + + :goto_a + const/16 v2, 0x80 + + if-ge v1, v2, :cond_5b + + move v3, v0 + + :goto_f + if-ge v3, v2, :cond_58 + + const/4 v4, 0x0 + + move v7, v0 + + move v5, v4 + + move v6, v5 + + :goto_15 + const/4 v8, 0x4 + + if-ge v7, v8, :cond_41 + + aget v9, p2, v7 + + add-int/2addr v9, v1 + + invoke-static {v9}, Ldev/kawarp/KawarpEngine;->clamp(I)I + + move-result v9 + + move v10, v0 + + :goto_20 + if-ge v10, v8, :cond_3e + + aget v11, p2, v10 + + mul-int/lit16 v12, v9, 0x80 + + add-int/2addr v11, v3 + + invoke-static {v11}, Ldev/kawarp/KawarpEngine;->clamp(I)I + + move-result v11 + + add-int/2addr v12, v11 + + mul-int/lit8 v12, v12, 0x3 + + aget v11, p0, v12 + + add-float/2addr v4, v11 + + add-int/lit8 v11, v12, 0x1 + + aget v11, p0, v11 + + add-float/2addr v5, v11 + + add-int/lit8 v12, v12, 0x2 + + aget v11, p0, v12 + + add-float/2addr v6, v11 + + add-int/lit8 v10, v10, 0x1 + + goto :goto_20 + + :cond_3e + add-int/lit8 v7, v7, 0x1 + + goto :goto_15 + + :cond_41 + mul-int/lit16 v7, v1, 0x80 + + add-int/2addr v7, v3 + + mul-int/lit8 v7, v7, 0x3 + + const/high16 v8, 0x41800000 # 16.0f + + div-float/2addr v4, v8 + + aput v4, p1, v7 + + add-int/lit8 v4, v7, 0x1 + + div-float/2addr v5, v8 + + aput v5, p1, v4 + + add-int/lit8 v7, v7, 0x2 + + div-float/2addr v6, v8 + + aput v6, p1, v7 + + add-int/lit8 v3, v3, 0x1 + + goto :goto_f + + :cond_58 + add-int/lit8 v1, v1, 0x1 + + goto :goto_a + + :cond_5b + return-void +.end method + +.method private process(Landroid/graphics/Bitmap;I)V + .registers 25 + + move-object/from16 v0, p0 + + const/16 v1, 0x4000 + + new-array v3, v1, [I + + const/16 v8, 0x80 + + const/16 v9, 0x80 + + const/4 v4, 0x0 + + const/16 v5, 0x80 + + const/4 v6, 0x0 + + const/4 v7, 0x0 + + move-object/from16 v2, p1 + + invoke-virtual/range {v2 .. v9}, Landroid/graphics/Bitmap;->getPixels([IIIIIII)V + + const v2, 0xc000 + + new-array v4, v2, [F + + new-array v2, v2, [F + + iget v5, v0, Ldev/kawarp/KawarpEngine;->tintR:F + + iget v6, v0, Ldev/kawarp/KawarpEngine;->tintG:F + + iget v7, v0, Ldev/kawarp/KawarpEngine;->tintB:F + + iget v8, v0, Ldev/kawarp/KawarpEngine;->tintIntensity:F + + const/4 v10, 0x0 + + move v11, v10 + + const/4 v12, 0x0 + + :goto_26 + const/4 v13, 0x2 + + if-ge v11, v1, :cond_ac + + aget v14, v3, v11 + + shr-int/lit8 v15, v14, 0x10 + + and-int/lit16 v15, v15, 0xff + + int-to-float v15, v15 + + const/high16 v16, 0x437f0000 # 255.0f + + div-float v15, v15, v16 + + const/16 p1, 0x0 + + shr-int/lit8 v9, v14, 0x8 + + and-int/lit16 v9, v9, 0xff + + int-to-float v9, v9 + + div-float v9, v9, v16 + + and-int/lit16 v14, v14, 0xff + + int-to-float v14, v14 + + div-float v14, v14, v16 + + const v16, 0x3e59b3d0 # 0.2126f + + mul-float v16, v16, v15 + + const v17, 0x3f371759 # 0.7152f + + mul-float v17, v17, v9 + + add-float v16, v16, v17 + + const v17, 0x3d93dd98 # 0.0722f + + mul-float v17, v17, v14 + + add-float v16, v16, v17 + + add-float v12, v12, v16 + + const v16, 0x3e991687 # 0.299f + + mul-float v16, v16, v15 + + const v17, 0x3f1645a2 # 0.587f + + mul-float v17, v17, v9 + + add-float v16, v16, v17 + + const v17, 0x3de978d5 # 0.114f + + mul-float v17, v17, v14 + + add-float v16, v16, v17 + + const/high16 v17, 0x40000000 # 2.0f + + mul-float v16, v16, v17 + + cmpg-float v18, v16, p1 + + const/high16 v19, 0x3f800000 # 1.0f + + if-gez v18, :cond_77 + + move/from16 v16, p1 + + goto :goto_7d + + :cond_77 + cmpl-float v18, v16, v19 + + if-lez v18, :cond_7d + + move/from16 v16, v19 + + :cond_7d + :goto_7d + mul-float v18, v16, v16 + + const/high16 v20, 0x40400000 # 3.0f + + mul-float v16, v16, v17 + + sub-float v20, v20, v16 + + mul-float v18, v18, v20 + + sub-float v19, v19, v18 + + mul-float v19, v19, v8 + + mul-int/lit8 v16, v11, 0x3 + + sub-float v17, v5, v15 + + mul-float v17, v17, v19 + + add-float v15, v15, v17 + + aput v15, v4, v16 + + add-int/lit8 v15, v16, 0x1 + + sub-float v17, v6, v9 + + mul-float v17, v17, v19 + + add-float v9, v9, v17 + + aput v9, v4, v15 + + add-int/lit8 v16, v16, 0x2 + + sub-float v9, v7, v14 + + mul-float v9, v9, v19 + + add-float/2addr v14, v9 + + aput v14, v4, v16 + + add-int/lit8 v11, v11, 0x1 + + goto/16 :goto_26 + + :cond_ac + const/high16 v5, 0x46800000 # 16384.0f + + div-float/2addr v12, v5 + + iget v5, v0, Ldev/kawarp/KawarpEngine;->blurPasses:I + + move v6, v10 + + :goto_b2 + if-ge v6, v5, :cond_bf + + invoke-static {v4, v2, v6}, Ldev/kawarp/KawarpEngine;->kawasePass([F[FI)V + + add-int/lit8 v6, v6, 0x1 + + move-object/from16 v21, v4 + + move-object v4, v2 + + move-object/from16 v2, v21 + + goto :goto_b2 + + :cond_bf + :goto_bf + if-ge v10, v1, :cond_e6 + + mul-int/lit8 v2, v10, 0x3 + + aget v5, v4, v2 + + invoke-static {v5}, Ldev/kawarp/KawarpEngine;->channel(F)I + + move-result v5 + + shl-int/lit8 v5, v5, 0x10 + + const/high16 v6, -0x1000000 + + or-int/2addr v5, v6 + + add-int/lit8 v6, v2, 0x1 + + aget v6, v4, v6 + + invoke-static {v6}, Ldev/kawarp/KawarpEngine;->channel(F)I + + move-result v6 + + shl-int/lit8 v6, v6, 0x8 + + or-int/2addr v5, v6 + + add-int/2addr v2, v13 + + aget v2, v4, v2 + + invoke-static {v2}, Ldev/kawarp/KawarpEngine;->channel(F)I + + move-result v2 + + or-int/2addr v2, v5 + + aput v2, v3, v10 + + add-int/lit8 v10, v10, 0x1 + + goto :goto_bf + + :cond_e6 + sget-object v1, Landroid/graphics/Bitmap$Config;->ARGB_8888:Landroid/graphics/Bitmap$Config; + + const/16 v2, 0x80 + + invoke-static {v2, v2, v1}, Landroid/graphics/Bitmap;->createBitmap(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap; + + move-result-object v2 + + const/16 v8, 0x80 + + const/16 v9, 0x80 + + const/4 v4, 0x0 + + const/16 v5, 0x80 + + const/4 v6, 0x0 + + const/4 v7, 0x0 + + invoke-virtual/range {v2 .. v9}, Landroid/graphics/Bitmap;->setPixels([IIIIIII)V + + iget v1, v0, Ldev/kawarp/KawarpEngine;->coverToken:I + + move/from16 v3, p2 + + if-eq v3, v1, :cond_101 + + return-void + + :cond_101 + new-instance v1, Landroid/graphics/BitmapShader; + + sget-object v3, Landroid/graphics/Shader$TileMode;->CLAMP:Landroid/graphics/Shader$TileMode; + + sget-object v4, Landroid/graphics/Shader$TileMode;->CLAMP:Landroid/graphics/Shader$TileMode; + + invoke-direct {v1, v2, v3, v4}, Landroid/graphics/BitmapShader;->(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V + + invoke-virtual {v1, v13}, Landroid/graphics/BitmapShader;->setFilterMode(I)V + + iget-object v2, v0, Ldev/kawarp/KawarpEngine;->nextShader:Landroid/graphics/BitmapShader; + + iput-object v2, v0, Ldev/kawarp/KawarpEngine;->prevShader:Landroid/graphics/BitmapShader; + + iput-object v1, v0, Ldev/kawarp/KawarpEngine;->nextShader:Landroid/graphics/BitmapShader; + + invoke-direct {v0, v12}, Ldev/kawarp/KawarpEngine;->brightnessFor(F)F + + move-result v1 + + iput v1, v0, Ldev/kawarp/KawarpEngine;->darkenBrightness:F + + invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J + + move-result-wide v1 + + iput-wide v1, v0, Ldev/kawarp/KawarpEngine;->transitionStart:J + + return-void +.end method + + +# virtual methods +.method public draw(Landroid/graphics/Canvas;FF)Z + .registers 13 + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->nextShader:Landroid/graphics/BitmapShader; + + if-eqz v0, :cond_ee + + const/4 v1, 0x0 + + cmpg-float v2, p2, v1 + + if-lez v2, :cond_ee + + cmpg-float v2, p3, v1 + + if-gtz v2, :cond_f + + goto/16 :goto_ee + + :cond_f + invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J + + move-result-wide v2 + + iget-wide v4, p0, Ldev/kawarp/KawarpEngine;->lastFrameUptime:J + + const-wide/16 v6, 0x0 + + cmp-long v4, v4, v6 + + if-nez v4, :cond_1d + + move v4, v1 + + goto :goto_2c + + :cond_1d + iget-wide v4, p0, Ldev/kawarp/KawarpEngine;->lastFrameUptime:J + + sub-long v4, v2, v4 + + long-to-float v4, v4 + + const/high16 v5, 0x447a0000 # 1000.0f + + div-float/2addr v4, v5 + + const v5, 0x3dcccccd # 0.1f + + invoke-static {v4, v5}, Ljava/lang/Math;->min(FF)F + + move-result v4 + + :goto_2c + iput-wide v2, p0, Ldev/kawarp/KawarpEngine;->lastFrameUptime:J + + iget-boolean v5, p0, Ldev/kawarp/KawarpEngine;->playbackReactive:Z + + const/high16 v6, 0x3f800000 # 1.0f + + if-eqz v5, :cond_38 + + iget-boolean v5, p0, Ldev/kawarp/KawarpEngine;->playing:Z + + if-eqz v5, :cond_39 + + :cond_38 + move v1, v6 + + :cond_39 + const v5, 0x3fe66666 # 1.8f + + div-float v5, v4, v5 + + iget v7, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F + + cmpg-float v7, v7, v1 + + iget v8, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F + + if-gez v7, :cond_4e + + add-float/2addr v8, v5 + + invoke-static {v1, v8}, Ljava/lang/Math;->min(FF)F + + move-result v1 + + :goto_4b + iput v1, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F + + goto :goto_5a + + :cond_4e + cmpl-float v7, v8, v1 + + if-lez v7, :cond_5a + + iget v7, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F + + sub-float/2addr v7, v5 + + invoke-static {v1, v7}, Ljava/lang/Math;->max(FF)F + + move-result v1 + + goto :goto_4b + + :cond_5a + :goto_5a + iget v1, p0, Ldev/kawarp/KawarpEngine;->shaderTime:F + + iget v5, p0, Ldev/kawarp/KawarpEngine;->animationSpeed:F + + mul-float/2addr v4, v5 + + iget v5, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F + + mul-float/2addr v4, v5 + + add-float/2addr v1, v4 + + iput v1, p0, Ldev/kawarp/KawarpEngine;->shaderTime:F + + iget v1, p0, Ldev/kawarp/KawarpEngine;->transitionMs:I + + iget-wide v4, p0, Ldev/kawarp/KawarpEngine;->transitionStart:J + + sub-long/2addr v2, v4 + + if-lez v1, :cond_75 + + int-to-long v4, v1 + + cmp-long v4, v2, v4 + + if-gez v4, :cond_75 + + long-to-float v2, v2 + + int-to-float v1, v1 + + div-float v6, v2, v1 + + :cond_75 + iget-object v1, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + iget-object v2, p0, Ldev/kawarp/KawarpEngine;->prevShader:Landroid/graphics/BitmapShader; + + if-eqz v2, :cond_7e + + iget-object v2, p0, Ldev/kawarp/KawarpEngine;->prevShader:Landroid/graphics/BitmapShader; + + goto :goto_7f + + :cond_7e + move-object v2, v0 + + :goto_7f + const-string v3, "texA" + + invoke-virtual {v1, v3, v2}, Landroid/graphics/RuntimeShader;->setInputShader(Ljava/lang/String;Landroid/graphics/Shader;)V + + iget-object v1, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v2, "texB" + + invoke-virtual {v1, v2, v0}, Landroid/graphics/RuntimeShader;->setInputShader(Ljava/lang/String;Landroid/graphics/Shader;)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uRes" + + invoke-virtual {v0, v1, p2, p3}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;FF)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uTime" + + iget v2, p0, Ldev/kawarp/KawarpEngine;->shaderTime:F + + invoke-virtual {v0, v1, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uBlend" + + invoke-virtual {v0, v1, v6}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uWarp" + + iget v2, p0, Ldev/kawarp/KawarpEngine;->warpIntensity:F + + invoke-virtual {v0, v1, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uSat" + + iget v2, p0, Ldev/kawarp/KawarpEngine;->saturation:F + + invoke-virtual {v0, v1, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uDither" + + iget v2, p0, Ldev/kawarp/KawarpEngine;->dithering:F + + invoke-virtual {v0, v1, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uScale" + + iget v2, p0, Ldev/kawarp/KawarpEngine;->scale:F + + invoke-virtual {v0, v1, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + iget v1, p0, Ldev/kawarp/KawarpEngine;->brightness:F + + iget v2, p0, Ldev/kawarp/KawarpEngine;->darkenBrightness:F + + mul-float/2addr v1, v2 + + const-string v2, "uBright" + + invoke-virtual {v0, v2, v1}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + const-string v1, "uContrast" + + iget v2, p0, Ldev/kawarp/KawarpEngine;->contrast:F + + invoke-virtual {v0, v1, v2}, Landroid/graphics/RuntimeShader;->setFloatUniform(Ljava/lang/String;F)V + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->paint:Landroid/graphics/Paint; + + iget-object v1, p0, Ldev/kawarp/KawarpEngine;->shader:Landroid/graphics/RuntimeShader; + + invoke-virtual {v0, v1}, Landroid/graphics/Paint;->setShader(Landroid/graphics/Shader;)Landroid/graphics/Shader; + + const/4 v4, 0x0 + + iget-object v7, p0, Ldev/kawarp/KawarpEngine;->paint:Landroid/graphics/Paint; + + const/4 v3, 0x0 + + move-object v2, p1 + + move v5, p2 + + move v6, p3 + + invoke-virtual/range {v2 .. v7}, Landroid/graphics/Canvas;->drawRect(FFFFLandroid/graphics/Paint;)V + + const/4 p1, 0x1 + + return p1 + + :cond_ee + :goto_ee + const/4 p1, 0x0 + + return p1 +.end method + +.method public isAnimating()Z + .registers 7 + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->nextShader:Landroid/graphics/BitmapShader; + + const/4 v1, 0x0 + + if-nez v0, :cond_6 + + return v1 + + :cond_6 + invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J + + move-result-wide v2 + + iget-wide v4, p0, Ldev/kawarp/KawarpEngine;->transitionStart:J + + sub-long/2addr v2, v4 + + iget v0, p0, Ldev/kawarp/KawarpEngine;->transitionMs:I + + int-to-long v4, v0 + + cmp-long v0, v2, v4 + + const/4 v2, 0x1 + + if-gez v0, :cond_16 + + return v2 + + :cond_16 + iget-boolean v0, p0, Ldev/kawarp/KawarpEngine;->playbackReactive:Z + + const/4 v3, 0x0 + + if-eqz v0, :cond_22 + + iget-boolean v0, p0, Ldev/kawarp/KawarpEngine;->playing:Z + + if-eqz v0, :cond_20 + + goto :goto_22 + + :cond_20 + move v0, v3 + + goto :goto_24 + + :cond_22 + :goto_22 + const/high16 v0, 0x3f800000 # 1.0f + + :goto_24 + iget v4, p0, Ldev/kawarp/KawarpEngine;->speedFactor:F + + cmpl-float v4, v4, v3 + + if-nez v4, :cond_2e + + cmpl-float v0, v0, v3 + + if-eqz v0, :cond_2f + + :cond_2e + move v1, v2 + + :cond_2f + return v1 +.end method + +.method public isReady()Z + .registers 2 + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->nextShader:Landroid/graphics/BitmapShader; + + if-eqz v0, :cond_6 + + const/4 v0, 0x1 + + goto :goto_7 + + :cond_6 + const/4 v0, 0x0 + + :goto_7 + return v0 +.end method + +.method public run()V + .registers 3 + + iget-object v0, p0, Ldev/kawarp/KawarpEngine;->pendingCover:Landroid/graphics/Bitmap; + + iget v1, p0, Ldev/kawarp/KawarpEngine;->coverToken:I + + if-nez v0, :cond_7 + + return-void + + :cond_7 + invoke-direct {p0, v0, v1}, Ldev/kawarp/KawarpEngine;->process(Landroid/graphics/Bitmap;I)V + + return-void +.end method + +.method public setAnimationSpeed(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->animationSpeed:F + + return-void +.end method + +.method public setAutoDarken(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->autoDarken:F + + return-void +.end method + +.method public setBlurPasses(I)V + .registers 3 + + const/16 v0, 0x28 + + invoke-static {v0, p1}, Ljava/lang/Math;->min(II)I + + move-result p1 + + const/4 v0, 0x1 + + invoke-static {v0, p1}, Ljava/lang/Math;->max(II)I + + move-result p1 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->blurPasses:I + + return-void +.end method + +.method public setBrightness(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->brightness:F + + return-void +.end method + +.method public setContrast(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->contrast:F + + return-void +.end method + +.method public setCover(Landroid/graphics/Bitmap;)V + .registers 4 + + if-nez p1, :cond_3 + + return-void + + :cond_3 + const/16 v0, 0x80 + + const/4 v1, 0x1 + + invoke-static {p1, v0, v0, v1}, Landroid/graphics/Bitmap;->createScaledBitmap(Landroid/graphics/Bitmap;IIZ)Landroid/graphics/Bitmap; + + move-result-object p1 + + iput-object p1, p0, Ldev/kawarp/KawarpEngine;->pendingCover:Landroid/graphics/Bitmap; + + iget p1, p0, Ldev/kawarp/KawarpEngine;->coverToken:I + + add-int/2addr p1, v1 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->coverToken:I + + sget-object p1, Ldev/kawarp/KawarpEngine;->LOADER:Ljava/util/concurrent/ExecutorService; + + invoke-interface {p1, p0}, Ljava/util/concurrent/ExecutorService;->execute(Ljava/lang/Runnable;)V + + return-void +.end method + +.method public setDithering(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->dithering:F + + return-void +.end method + +.method public setPlaybackReactive(Z)V + .registers 2 + + iput-boolean p1, p0, Ldev/kawarp/KawarpEngine;->playbackReactive:Z + + return-void +.end method + +.method public setPlaying(Z)V + .registers 2 + + iput-boolean p1, p0, Ldev/kawarp/KawarpEngine;->playing:Z + + return-void +.end method + +.method public setSaturation(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->saturation:F + + return-void +.end method + +.method public setScale(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->scale:F + + return-void +.end method + +.method public setTintColor(FFF)V + .registers 4 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->tintR:F + + iput p2, p0, Ldev/kawarp/KawarpEngine;->tintG:F + + iput p3, p0, Ldev/kawarp/KawarpEngine;->tintB:F + + return-void +.end method + +.method public setTintIntensity(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->tintIntensity:F + + return-void +.end method + +.method public setTransitionDuration(I)V + .registers 3 + + const/4 v0, 0x0 + + invoke-static {v0, p1}, Ljava/lang/Math;->max(II)I + + move-result p1 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->transitionMs:I + + return-void +.end method + +.method public setWarpIntensity(F)V + .registers 2 + + iput p1, p0, Ldev/kawarp/KawarpEngine;->warpIntensity:F + + return-void +.end method diff --git a/patches/extension/radiant/HomeBackdrop.smali b/patches/extension/radiant/HomeBackdrop.smali index c099921..cac08ee 100644 --- a/patches/extension/radiant/HomeBackdrop.smali +++ b/patches/extension/radiant/HomeBackdrop.smali @@ -5,7 +5,7 @@ # static fields .field public static volatile currentAlbumId:I -# 0 = Static, 1 = Animated (always rotate), 2 = Playback (follow live play state) +# 2 = Stock (TIDAL's blurred cover, follows live play state), 3 = Kawarp (AGSL shader) .field public static volatile mode:I # Live play state from the mini-player (t.c PlayState = Playing) @@ -73,26 +73,6 @@ return-void .end method -.method public static setModeStatic()V - .locals 1 - - const/4 v0, 0x0 - - sput v0, Lradiant/HomeBackdrop;->mode:I - - return-void -.end method - -.method public static setModeAnimated()V - .locals 1 - - const/4 v0, 0x1 - - sput v0, Lradiant/HomeBackdrop;->mode:I - - return-void -.end method - .method public static setModePlayback()V .locals 1 diff --git a/patches/extension/radiant/Kawarp.smali b/patches/extension/radiant/Kawarp.smali new file mode 100644 index 0000000..ce81000 --- /dev/null +++ b/patches/extension/radiant/Kawarp.smali @@ -0,0 +1,847 @@ +.class public final Lradiant/Kawarp; +.super Ljava/lang/Object; + +# interfaces +.implements Lam0/l; +.implements Ljava/lang/Runnable; +.implements Landroid/view/Choreographer$FrameCallback; + + +# static fields +.field private static final DRAW:Lradiant/Kawarp; + +.field private static final IDLE_STOP_MS:J = 0x1f4L + +.field private static final LOADER:Ljava/util/concurrent/ExecutorService; + +.field private static final TAG:Ljava/lang/String; = "RLKawarp" + +.field private static engine:Ldev/kawarp/KawarpEngine; + +.field private static final fallbackState:Landroidx/compose/runtime/MutableState; + +.field private static frameScheduled:Z + +.field private static final frameState:Landroidx/compose/runtime/MutableState; + +.field private static frameTick:I + +.field private static lastDrawUptime:J + +.field private static volatile loadToken:I + +.field private static loggedDraw:Z + +.field private static volatile requestedUuid:Ljava/lang/String; + + +# instance fields +.field private final token:I + +.field private final uuid:Ljava/lang/String; + + +# direct methods +.method static constructor ()V + .registers 4 + + invoke-static {}, Ljava/util/concurrent/Executors;->newSingleThreadExecutor()Ljava/util/concurrent/ExecutorService; + + move-result-object v0 + + sput-object v0, Lradiant/Kawarp;->LOADER:Ljava/util/concurrent/ExecutorService; + + const/4 v0, 0x0 + + invoke-static {v0}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; + + move-result-object v1 + + const/4 v2, 0x0 + + const/4 v3, 0x2 + + invoke-static {v1, v2, v3, v2}, Landroidx/compose/runtime/SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState; + + move-result-object v1 + + sput-object v1, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableState; + + sget-object v1, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; + + invoke-static {v1, v2, v3, v2}, Landroidx/compose/runtime/SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState; + + move-result-object v1 + + sput-object v1, Lradiant/Kawarp;->fallbackState:Landroidx/compose/runtime/MutableState; + + new-instance v1, Lradiant/Kawarp; + + invoke-direct {v1, v2, v0}, Lradiant/Kawarp;->(Ljava/lang/String;I)V + + sput-object v1, Lradiant/Kawarp;->DRAW:Lradiant/Kawarp; + + return-void +.end method + +.method private constructor (Ljava/lang/String;I)V + .registers 3 + + invoke-direct {p0}, Ljava/lang/Object;->()V + + iput-object p1, p0, Lradiant/Kawarp;->uuid:Ljava/lang/String; + + iput p2, p0, Lradiant/Kawarp;->token:I + + return-void +.end method + +.method public static b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V + .registers 11 + + invoke-static {p3, p4, p5, p8, p9}, Lradiant/Kawarp;->render(ILjava/lang/String;ZLandroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;)V + + return-void +.end method + +.method private static draw(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V + .registers 6 + + sget-object v0, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableState; + + invoke-interface {v0}, Landroidx/compose/runtime/MutableState;->getValue()Ljava/lang/Object; + + invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J + + move-result-wide v0 + + sput-wide v0, Lradiant/Kawarp;->lastDrawUptime:J + + invoke-static {}, Lradiant/Kawarp;->schedule()V + + invoke-interface {p0}, Landroidx/compose/ui/graphics/drawscope/DrawScope;->getSize-NH-jbRc()J + + move-result-wide v0 + + invoke-static {v0, v1}, Landroidx/compose/ui/geometry/Size;->getWidth-impl(J)F + + move-result v2 + + invoke-static {v0, v1}, Landroidx/compose/ui/geometry/Size;->getHeight-impl(J)F + + move-result v0 + + sget-boolean v1, Lradiant/Kawarp;->loggedDraw:Z + + const-string v3, "RLKawarp" + + if-nez v1, :cond_53 + + const/4 v1, 0x1 + + sput-boolean v1, Lradiant/Kawarp;->loggedDraw:Z + + new-instance v1, Ljava/lang/StringBuilder; + + invoke-direct {v1}, Ljava/lang/StringBuilder;->()V + + const-string v4, "first draw: " + + invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v1 + + invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(F)Ljava/lang/StringBuilder; + + move-result-object v1 + + const-string v4, "x" + + invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v1 + + invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(F)Ljava/lang/StringBuilder; + + move-result-object v1 + + const-string v4, " ready=" + + invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v1 + + sget-object v4, Lradiant/Kawarp;->engine:Ldev/kawarp/KawarpEngine; + + invoke-virtual {v4}, Ldev/kawarp/KawarpEngine;->isReady()Z + + move-result v4 + + invoke-virtual {v1, v4}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder; + + move-result-object v1 + + invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v1 + + invoke-static {v3, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I + + :cond_53 + :try_start_53 + sget-object v1, Lradiant/Kawarp;->engine:Ldev/kawarp/KawarpEngine; + + invoke-interface {p0}, Landroidx/compose/ui/graphics/drawscope/DrawScope;->getDrawContext()Landroidx/compose/ui/graphics/drawscope/DrawContext; + + move-result-object p0 + + invoke-interface {p0}, Landroidx/compose/ui/graphics/drawscope/DrawContext;->getCanvas()Landroidx/compose/ui/graphics/Canvas; + + move-result-object p0 + + invoke-static {p0}, Landroidx/compose/ui/graphics/AndroidCanvas_androidKt;->getNativeCanvas(Landroidx/compose/ui/graphics/Canvas;)Landroid/graphics/Canvas; + + move-result-object p0 + + invoke-virtual {v1, p0, v2, v0}, Ldev/kawarp/KawarpEngine;->draw(Landroid/graphics/Canvas;FF)Z + :try_end_64 + .catchall {:try_start_53 .. :try_end_64} :catchall_65 + + goto :goto_83 + + :catchall_65 + move-exception p0 + + new-instance v0, Ljava/lang/StringBuilder; + + invoke-direct {v0}, Ljava/lang/StringBuilder;->()V + + const-string v1, "AGSL draw failed, falling back: " + + invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v0 + + invoke-virtual {v0, p0}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder; + + move-result-object p0 + + invoke-virtual {p0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object p0 + + invoke-static {v3, p0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I + + sget-object p0, Lradiant/Kawarp;->fallbackState:Landroidx/compose/runtime/MutableState; + + sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean; + + invoke-interface {p0, v0}, Landroidx/compose/runtime/MutableState;->setValue(Ljava/lang/Object;)V + + :goto_83 + return-void +.end method + +.method private static ensureEngine()Z + .registers 4 + + sget-object v0, Lradiant/Kawarp;->engine:Ldev/kawarp/KawarpEngine; + + const/4 v1, 0x1 + + if-eqz v0, :cond_6 + + return v1 + + :cond_6 + invoke-static {}, Ldev/kawarp/KawarpEngine;->isSupported()Z + + move-result v0 + + const/4 v2, 0x0 + + if-nez v0, :cond_e + + return v2 + + :cond_e + :try_start_e + new-instance v0, Ldev/kawarp/KawarpEngine; + + invoke-direct {v0}, Ldev/kawarp/KawarpEngine;->()V + + const v3, __RL_KW_WARP__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setWarpIntensity(F)V + + const v3, __RL_KW_SPEED__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setAnimationSpeed(F)V + + const v3, __RL_KW_SCALE__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setScale(F)V + + const v3, __RL_KW_DITHER__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setDithering(F)V + + const v3, __RL_KW_DARKEN__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setAutoDarken(F)V + + const v3, __RL_KW_REACTIVE__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + if-eqz v3, :cond_64 + + move v3, v1 + + goto :goto_65 + + :cond_64 + move v3, v2 + + :goto_65 + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setPlaybackReactive(Z)V + + const v3, __RL_KW_BLUR__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setBlurPasses(I)V + + const v3, __RL_KW_CONTRAST__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setContrast(F)V + + const v3, __RL_KW_SAT__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setSaturation(F)V + + const v3, __RL_KW_BRIGHT__ + + invoke-static {v3}, Lradiant/Kawarp;->tk(I)I + + move-result v3 + + invoke-static {v3}, Ljava/lang/Float;->intBitsToFloat(I)F + + move-result v3 + + invoke-virtual {v0, v3}, Ldev/kawarp/KawarpEngine;->setBrightness(F)V + + sput-object v0, Lradiant/Kawarp;->engine:Ldev/kawarp/KawarpEngine; + :try_end_9e + .catchall {:try_start_e .. :try_end_9e} :catchall_9f + + return v1 + + :catchall_9f + move-exception v0 + + new-instance v1, Ljava/lang/StringBuilder; + + invoke-direct {v1}, Ljava/lang/StringBuilder;->()V + + const-string v3, "AGSL rejected, staying on the native backdrop: " + + invoke-virtual {v1, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v1 + + invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder; + + move-result-object v0 + + invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v0 + + const-string v1, "RLKawarp" + + invoke-static {v1, v0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I + + sget-object v0, Lradiant/Kawarp;->fallbackState:Landroidx/compose/runtime/MutableState; + + sget-object v1, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean; + + invoke-interface {v0, v1}, Landroidx/compose/runtime/MutableState;->setValue(Ljava/lang/Object;)V + + return v2 +.end method + +.method public static render(ILjava/lang/String;ZLandroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;)V + .registers 13 + + const v0, 0x52415750 + + invoke-interface {p4, v0}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V + + sget-object v0, Lradiant/Kawarp;->fallbackState:Landroidx/compose/runtime/MutableState; + + invoke-interface {v0}, Landroidx/compose/runtime/MutableState;->getValue()Ljava/lang/Object; + + move-result-object v0 + + check-cast v0, Ljava/lang/Boolean; + + invoke-virtual {v0}, Ljava/lang/Boolean;->booleanValue()Z + + move-result v0 + + if-nez v0, :cond_34 + + invoke-static {}, Lradiant/Kawarp;->ensureEngine()Z + + move-result v0 + + if-eqz v0, :cond_34 + + sget-object p0, Lradiant/Kawarp;->engine:Ldev/kawarp/KawarpEngine; + + invoke-virtual {p0, p2}, Ldev/kawarp/KawarpEngine;->setPlaying(Z)V + + invoke-static {p1}, Lradiant/Kawarp;->request(Ljava/lang/String;)V + + const/high16 p0, 0x3f800000 # 1.0f + + invoke-static {p3, p0}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxSize(Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier; + + move-result-object p0 + + sget-object p1, Lradiant/Kawarp;->DRAW:Lradiant/Kawarp; + + invoke-static {p0, p1}, Landroidx/compose/ui/draw/DrawModifierKt;->drawBehind(Landroidx/compose/ui/Modifier;Lam0/l;)Landroidx/compose/ui/Modifier; + + move-result-object p0 + + const/4 p1, 0x0 + + invoke-static {p0, p4, p1}, Landroidx/compose/foundation/layout/SpacerKt;->Spacer(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V + + move-object v6, p4 + + goto :goto_3f + + :cond_34 + const/4 v4, 0x0 + + const/4 v7, 0x0 + + const/4 v3, 0x0 + + move v0, p0 + + move-object v1, p1 + + move v2, p2 + + move-object v5, p3 + + move-object v6, p4 + + invoke-static/range {v0 .. v7}, Lcom/tidal/android/feature/playerscreen/ui/composables/p3;->a(ILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V + + :goto_3f + invoke-interface {v6}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V + + return-void +.end method + +.method private static request(Ljava/lang/String;)V + .registers 4 + + if-eqz p0, :cond_23 + + invoke-virtual {p0}, Ljava/lang/String;->length()I + + move-result v0 + + if-eqz v0, :cond_23 + + sget-object v0, Lradiant/Kawarp;->requestedUuid:Ljava/lang/String; + + invoke-virtual {p0, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z + + move-result v0 + + if-eqz v0, :cond_11 + + goto :goto_23 + + :cond_11 + sput-object p0, Lradiant/Kawarp;->requestedUuid:Ljava/lang/String; + + sget-object v0, Lradiant/Kawarp;->LOADER:Ljava/util/concurrent/ExecutorService; + + new-instance v1, Lradiant/Kawarp; + + sget v2, Lradiant/Kawarp;->loadToken:I + + add-int/lit8 v2, v2, 0x1 + + sput v2, Lradiant/Kawarp;->loadToken:I + + invoke-direct {v1, p0, v2}, Lradiant/Kawarp;->(Ljava/lang/String;I)V + + invoke-interface {v0, v1}, Ljava/util/concurrent/ExecutorService;->execute(Ljava/lang/Runnable;)V + + :cond_23 + :goto_23 + return-void +.end method + +.method private static schedule()V + .registers 2 + + sget-boolean v0, Lradiant/Kawarp;->frameScheduled:Z + + if-eqz v0, :cond_5 + + return-void + + :cond_5 + const/4 v0, 0x1 + + sput-boolean v0, Lradiant/Kawarp;->frameScheduled:Z + + invoke-static {}, Landroid/view/Choreographer;->getInstance()Landroid/view/Choreographer; + + move-result-object v0 + + sget-object v1, Lradiant/Kawarp;->DRAW:Lradiant/Kawarp; + + invoke-virtual {v0, v1}, Landroid/view/Choreographer;->postFrameCallback(Landroid/view/Choreographer$FrameCallback;)V + + return-void +.end method + +.method private static tk(I)I + .registers 1 + + return p0 +.end method + + +# virtual methods +.method public doFrame(J)V + .registers 5 + + const/4 p1, 0x0 + + sput-boolean p1, Lradiant/Kawarp;->frameScheduled:Z + + invoke-static {}, Landroid/os/SystemClock;->uptimeMillis()J + + move-result-wide p1 + + sget-wide v0, Lradiant/Kawarp;->lastDrawUptime:J + + sub-long/2addr p1, v0 + + const-wide/16 v0, 0x1f4 + + cmp-long p1, p1, v0 + + if-lez p1, :cond_11 + + return-void + + :cond_11 + sget-object p1, Lradiant/Kawarp;->frameState:Landroidx/compose/runtime/MutableState; + + sget p2, Lradiant/Kawarp;->frameTick:I + + add-int/lit8 p2, p2, 0x1 + + sput p2, Lradiant/Kawarp;->frameTick:I + + invoke-static {p2}, Ljava/lang/Integer;->valueOf(I)Ljava/lang/Integer; + + move-result-object p2 + + invoke-interface {p1, p2}, Landroidx/compose/runtime/MutableState;->setValue(Ljava/lang/Object;)V + + invoke-static {}, Lradiant/Kawarp;->schedule()V + + return-void +.end method + +.method public invoke(Ljava/lang/Object;)Ljava/lang/Object; + .registers 2 + + check-cast p1, Landroidx/compose/ui/graphics/drawscope/DrawScope; + + invoke-static {p1}, Lradiant/Kawarp;->draw(Landroidx/compose/ui/graphics/drawscope/DrawScope;)V + + sget-object p1, Lkotlin/u;->a:Lkotlin/u; + + return-object p1 +.end method + +.method public run()V + .registers 8 + + const-string v0, "RLKawarp" + + const/4 v1, 0x0 + + :try_start_3 + new-instance v2, Ljava/net/URL; + + new-instance v3, Ljava/lang/StringBuilder; + + invoke-direct {v3}, Ljava/lang/StringBuilder;->()V + + const-string v4, "https://resources.tidal.com/images/" + + invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v3 + + iget-object v4, p0, Lradiant/Kawarp;->uuid:Ljava/lang/String; + + const/16 v5, 0x2d + + const/16 v6, 0x2f + + invoke-virtual {v4, v5, v6}, Ljava/lang/String;->replace(CC)Ljava/lang/String; + + move-result-object v4 + + invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v3 + + const-string v4, "/640x640.jpg" + + invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v3 + + invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v3 + + invoke-direct {v2, v3}, Ljava/net/URL;->(Ljava/lang/String;)V + + invoke-virtual {v2}, Ljava/net/URL;->openConnection()Ljava/net/URLConnection; + + move-result-object v2 + + check-cast v2, Ljava/net/HttpURLConnection; + :try_end_31 + .catchall {:try_start_3 .. :try_end_31} :catchall_7f + + const/16 v3, 0x2710 + + :try_start_33 + invoke-virtual {v2, v3}, Ljava/net/HttpURLConnection;->setConnectTimeout(I)V + + const/16 v3, 0x3a98 + + invoke-virtual {v2, v3}, Ljava/net/HttpURLConnection;->setReadTimeout(I)V + + invoke-virtual {v2}, Ljava/net/HttpURLConnection;->getInputStream()Ljava/io/InputStream; + + move-result-object v3 + :try_end_3f + .catchall {:try_start_33 .. :try_end_3f} :catchall_7d + + :try_start_3f + invoke-static {v3}, Landroid/graphics/BitmapFactory;->decodeStream(Ljava/io/InputStream;)Landroid/graphics/Bitmap; + + move-result-object v4 + :try_end_43 + .catchall {:try_start_3f .. :try_end_43} :catchall_78 + + :try_start_43 + invoke-virtual {v3}, Ljava/io/InputStream;->close()V + + if-eqz v4, :cond_72 + + iget v3, p0, Lradiant/Kawarp;->token:I + + sget v5, Lradiant/Kawarp;->loadToken:I + + if-eq v3, v5, :cond_4f + + goto :goto_72 + + :cond_4f + sget-object v3, Lradiant/Kawarp;->engine:Ldev/kawarp/KawarpEngine; + + invoke-virtual {v3, v4}, Ldev/kawarp/KawarpEngine;->setCover(Landroid/graphics/Bitmap;)V + + invoke-virtual {v4}, Landroid/graphics/Bitmap;->recycle()V + + new-instance v3, Ljava/lang/StringBuilder; + + invoke-direct {v3}, Ljava/lang/StringBuilder;->()V + + const-string v4, "cover submitted: " + + invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v3 + + iget-object v4, p0, Lradiant/Kawarp;->uuid:Ljava/lang/String; + + invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v3 + + invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v3 + + invoke-static {v0, v3}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I + :try_end_6f + .catchall {:try_start_43 .. :try_end_6f} :catchall_7d + + if-eqz v2, :cond_a4 + + goto :goto_a1 + + :cond_72 + :goto_72 + if-eqz v2, :cond_77 + + invoke-virtual {v2}, Ljava/net/HttpURLConnection;->disconnect()V + + :cond_77 + return-void + + :catchall_78 + move-exception v4 + + :try_start_79 + invoke-virtual {v3}, Ljava/io/InputStream;->close()V + + throw v4 + :try_end_7d + .catchall {:try_start_79 .. :try_end_7d} :catchall_7d + + :catchall_7d + move-exception v3 + + goto :goto_81 + + :catchall_7f + move-exception v3 + + move-object v2, v1 + + :goto_81 + :try_start_81 + new-instance v4, Ljava/lang/StringBuilder; + + invoke-direct {v4}, Ljava/lang/StringBuilder;->()V + + const-string v5, "cover load failed: " + + invoke-virtual {v4, v5}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + move-result-object v4 + + invoke-virtual {v4, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/Object;)Ljava/lang/StringBuilder; + + move-result-object v3 + + invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v3 + + invoke-static {v0, v3}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I + + iget v0, p0, Lradiant/Kawarp;->token:I + + sget v3, Lradiant/Kawarp;->loadToken:I + + if-ne v0, v3, :cond_9f + + sput-object v1, Lradiant/Kawarp;->requestedUuid:Ljava/lang/String; + :try_end_9f + .catchall {:try_start_81 .. :try_end_9f} :catchall_a5 + + :cond_9f + if-eqz v2, :cond_a4 + + :goto_a1 + invoke-virtual {v2}, Ljava/net/HttpURLConnection;->disconnect()V + + :cond_a4 + return-void + + :catchall_a5 + move-exception v0 + + if-eqz v2, :cond_ab + + invoke-virtual {v2}, Ljava/net/HttpURLConnection;->disconnect()V + + :cond_ab + throw v0 +.end method diff --git a/patches/manifest.json b/patches/manifest.json index 333c5f4..48649cd 100644 --- a/patches/manifest.json +++ b/patches/manifest.json @@ -14,17 +14,16 @@ "DebugMenuUnlock" ], "disables": [ - "LyricsDisableCover", - "LyricsReplaceLyricsButton", - "LyricsReplaceShareButton", "LyricsRlApi", - "LyricsKeepControlsVisible", "PlayerBackdrop", "QualityBadgeColors", "PlayerMovePlayingFrom", "PlayerOneHanded", "LyricsProgressPill", - "MiniPlayerRedesign" + "LyricsDisableCover", + "LyricsReplaceLyricsButton", + "LyricsReplaceShareButton", + "LyricsKeepControlsVisible" ] }, { @@ -119,36 +118,29 @@ "order": 30, "fileNames": [], "title": "Player Backdrop", - "description": "Lets you fully adjust how the player backdrop blur looks and behaves", + "description": "Swap the player backdrop for the Kawarp shader, or fine-tune TIDAL's own blurred cover", "default": true, - "defaultVariantIndex": 2, + "defaultVariantIndex": 1, "variants": [ { - "title": "Static", - "fileNames": [ - "player-backdrop-static.patch" - ], - "extensionFiles": [ - "radiant/BackdropFx.smali" - ] - }, - { - "title": "Animated", - "fileNames": [ - "player-backdrop-animated.patch" - ], - "extensionFiles": [ - "radiant/BackdropFx.smali" - ] - }, - { - "title": "Playback", + "title": "Tidal", "fileNames": [ "player-backdrop-playback.patch" ], "extensionFiles": [ "radiant/BackdropFx.smali" ] + }, + { + "title": "Radiant", + "fileNames": [ + "player-backdrop-kawarp.patch" + ], + "extensionFiles": [ + "radiant/Kawarp.smali", + "dev/kawarp/KawarpEngine.smali" + ], + "minSdk": 33 } ], "advancedOptions": [ @@ -166,7 +158,8 @@ "encode": { "kind": "int", "scale": 1.0 - } + }, + "requiresVariant": 0 }, { "type": "slider", @@ -182,7 +175,8 @@ "encode": { "kind": "floatBits", "scale": 0.02 - } + }, + "requiresVariant": 0 }, { "type": "slider", @@ -198,7 +192,8 @@ "encode": { "kind": "floatBits", "scale": 0.02 - } + }, + "requiresVariant": 0 }, { "type": "slider", @@ -214,7 +209,170 @@ "encode": { "kind": "floatBits", "scale": 0.02 - } + }, + "requiresVariant": 0 + }, + { + "type": "toggle", + "key": "kawarp_reactive", + "title": "Playback Reactive", + "description": "Cover shader reacts to playback state by freezing/resuming", + "default": true, + "token": "RL_KW_REACTIVE", + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_blur", + "title": "Blur Passes", + "description": "Kawase blur passes, higher is softer but costs more GPU", + "default": 5, + "min": 1, + "max": 40, + "steps": 38, + "displayAsPercent": false, + "token": "RL_KW_BLUR", + "encode": { + "kind": "int", + "scale": 1.0 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_warp", + "title": "Warp Intensity", + "description": "Strength of the fluidity effect", + "default": 100, + "min": 0, + "max": 100, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_WARP", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_speed", + "title": "Animation Speed", + "description": "How fast the backdrop flows", + "default": 175, + "min": 0, + "max": 500, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_SPEED", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_scale", + "title": "Backdrop Scale", + "description": "Zoom level of the effect", + "default": 100, + "min": 10, + "max": 400, + "steps": 12, + "displayAsPercent": true, + "token": "RL_KW_SCALE", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_contrast", + "title": "Contrast", + "description": "Contrast of the backdrop", + "default": 125, + "min": 0, + "max": 300, + "steps": 11, + "displayAsPercent": true, + "token": "RL_KW_CONTRAST", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_saturation", + "title": "Saturation", + "description": "Colour intensity of the backdrop", + "default": 125, + "min": 0, + "max": 400, + "steps": 15, + "displayAsPercent": true, + "token": "RL_KW_SAT", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_brightness", + "title": "Brightness", + "description": "The value of Brightness applied to the backdrop", + "default": 100, + "min": 0, + "max": 200, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_BRIGHT", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_darken", + "title": "Auto Darken Bright Covers", + "description": "Prevents bright covers from making text unreadable", + "default": 80, + "min": 0, + "max": 100, + "steps": 19, + "displayAsPercent": true, + "token": "RL_KW_DARKEN", + "encode": { + "kind": "floatBits", + "scale": 0.01 + }, + "requiresVariant": 1 + }, + { + "type": "slider", + "key": "kawarp_dither", + "title": "Dithering", + "description": "Breaks up color banding in smooth gradients", + "default": 15, + "min": 0, + "max": 100, + "steps": 19, + "displayAsPercent": false, + "token": "RL_KW_DITHER", + "encode": { + "kind": "floatBits", + "scale": 0.001 + }, + "requiresVariant": 1 }, { "type": "toggle", diff --git a/patches/player-backdrop-animated.patch b/patches/player-backdrop-animated.patch deleted file mode 100644 index 8b9e350..0000000 --- a/patches/player-backdrop-animated.patch +++ /dev/null @@ -1,121 +0,0 @@ ---- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali -+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali -@@ -4433,6 +4433,14 @@ - - move-object/from16 v25, v10 - -+ sget-object v16, Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;->DARK_BLUR:Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle; # RL: force native Blur player background -+ -+ const/16 v21, 0x1 # RL: isPlaying=true (Animated — always rotate) -+ -+ const/16 v22, 0x0 # RL: isSeeking=false (Animated — ignore scrub) -+ -+ invoke-static {}, Lradiant/HomeBackdrop;->setModeAnimated()V # RL: mirror rotation to Cover Everywhere -+ - .line 171 - invoke-static/range {v16 .. v26}, Lcom/tidal/android/feature/playerscreen/ui/composables/p3;->b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V - ---- a/com/tidal/android/core/ui/composable/c0.smali -+++ b/com/tidal/android/core/ui/composable/c0.smali -@@ -16,7 +16,9 @@ - move-result p0 - - .line 5 -- invoke-virtual {p2, p0}, Landroid/view/Window;->setNavigationBarColor(I)V -+ const/4 v3, 0x0 # RL: force transparent nav bar so the native blur backdrop shows through (was p0 = extracted BG color; luminance below still uses p0 for icon light/dark) -+ -+ invoke-virtual {p2, v3}, Landroid/view/Window;->setNavigationBarColor(I)V - - .line 6 - .line 7 ---- a/de0/c.smali -+++ b/de0/c.smali -@@ -26,29 +26,26 @@ - .line 2 - .line 3 - .line 4 -- const-string v0, "HeavyBlurTransformation() " -- -- .line 5 -- .line 6 -- const-string v1, " " -- -- .line 7 -- .line 8 -- const/4 v2, 0x6 -- -- .line 9 -- const/16 v3, 0x19 -- -- .line 10 -- .line 11 -- invoke-static {v2, v3, v0, v1}, Landroidx/compose/foundation/text/input/a;->b(IILjava/lang/String;Ljava/lang/String;)Ljava/lang/String; -- -- .line 12 -- .line 13 -- .line 14 -+ new-instance v0, Ljava/lang/StringBuilder; -+ invoke-direct {v0}, Ljava/lang/StringBuilder;->()V -+ const-string v1, "RLBackdrop_b" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const/16 v1, __RL_BLUR__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ const-string v1, "c" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const v1, __RL_CONTRAST__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ const-string v1, "s" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const v1, __RL_SATURATION__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ const-string v1, "r" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const v1, __RL_BRIGHTNESS__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; - move-result-object v0 -- -- .line 15 - iput-object v0, p0, Lde0/c;->a:Ljava/lang/String; - - .line 16 -@@ -59,10 +56,17 @@ - - # virtual methods - .method public final a(Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap; -- .locals 2 -+ .locals 3 - - .line 1 -- const/4 v0, 0x6 -+ const/16 v2, __RL_BLUR__ -+ mul-int/lit8 v0, v2, 0x6 -+ const/16 v1, 0x32 -+ div-int v0, v0, v1 -+ const/4 v1, 0x1 -+ if-ge v0, v1, :rl_ds_ok -+ const/4 v0, 0x1 -+ :rl_ds_ok - - .line 2 - invoke-static {p1, v0}, Lcom/squareup/ui/market/layout/e;->c(Landroid/graphics/Bitmap;I)Landroid/graphics/Bitmap; -@@ -82,7 +86,7 @@ - .line 9 - .line 10 - .line 11 -- const/16 v1, 0x19 -+ div-int/lit8 v1, v2, 0x2 - - .line 12 - .line 13 -@@ -93,6 +97,10 @@ - .line 16 - move-result-object v1 - -+ invoke-static {v1}, Lradiant/BackdropFx;->apply(Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap; -+ -+ move-result-object v1 -+ - .line 17 - invoke-virtual {v0}, Landroid/graphics/Bitmap;->recycle()V - diff --git a/patches/player-backdrop-kawarp.patch b/patches/player-backdrop-kawarp.patch new file mode 100644 index 0000000..3bdb432 --- /dev/null +++ b/patches/player-backdrop-kawarp.patch @@ -0,0 +1,79 @@ +--- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali ++++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali +@@ -4613,8 +4613,10 @@ + + move-object/from16 v25, v10 + ++ invoke-static {}, Lradiant/HomeBackdrop;->setModeKawarp()V # RL: mirror the mode to Cover Everywhere ++ + .line 171 +- invoke-static/range {v16 .. v26}, Lcom/tidal/android/feature/playerscreen/ui/composables/p3;->b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V ++ invoke-static/range {v16 .. v26}, Lradiant/Kawarp;->b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V + + const/4 v4, 0x0 + +--- a/com/tidal/android/core/ui/composable/c0.smali ++++ b/com/tidal/android/core/ui/composable/c0.smali +@@ -16,7 +16,9 @@ + move-result p0 + + .line 5 +- invoke-virtual {p2, p0}, Landroid/view/Window;->setNavigationBarColor(I)V ++ const/4 v3, 0x0 # RL: force transparent nav bar so the AGSL backdrop shows through (was p0 = extracted BG color; luminance below still uses p0 for icon light/dark) ++ ++ invoke-virtual {p2, v3}, Landroid/view/Window;->setNavigationBarColor(I)V + + .line 6 + .line 7 +--- a/radiant/HomeBackdrop.smali ++++ b/radiant/HomeBackdrop.smali +@@ -83,6 +83,16 @@ + return-void + .end method + ++.method public static setModeKawarp()V ++ .locals 1 ++ ++ const/4 v0, 0x3 ++ ++ sput v0, Lradiant/HomeBackdrop;->mode:I ++ ++ return-void ++.end method ++ + # from the mini-player state ctor (t.) whenever play state changes. + .method public static onPlayState(Lcom/tidal/android/feature/appscaffold/ui/MiniPlayerContract$PlayState;)V + .locals 2 +@@ -363,8 +373,13 @@ + + const/4 v11, 0x2 + ++ if-eq v10, v11, :rl_live_play ++ ++ const/4 v11, 0x3 # RL: Kawarp follows live play state as well ++ + if-ne v10, v11, :rl_mode_done + ++ :rl_live_play + sget-object v10, Lradiant/HomeBackdrop;->isPlayingState:Landroidx/compose/runtime/MutableState; + + invoke-interface {v10}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object; +@@ -378,6 +393,18 @@ + move-result v10 + + :rl_mode_done ++ # RL: Kawarp renders its own AGSL backdrop rather than TIDAL's blurred cover ++ sget v11, Lradiant/HomeBackdrop;->mode:I ++ ++ const/4 v12, 0x3 ++ ++ if-ne v11, v12, :rl_native_backdrop ++ ++ invoke-static {v8, v9, v10, v13, v0}, Lradiant/Kawarp;->render(ILjava/lang/String;ZLandroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;)V ++ ++ goto :skip ++ ++ :rl_native_backdrop + const/4 v11, 0x0 # v11 = isSeeking = false + + const/4 v12, 0x0 # v12 = progress callback = null (unused while not seeking) diff --git a/patches/player-backdrop-static.patch b/patches/player-backdrop-static.patch deleted file mode 100644 index a72ceae..0000000 --- a/patches/player-backdrop-static.patch +++ /dev/null @@ -1,121 +0,0 @@ ---- a/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali -+++ b/com/tidal/android/feature/playerscreen/ui/PlayerScreenKt.smali -@@ -4433,6 +4433,14 @@ - - move-object/from16 v25, v10 - -+ sget-object v16, Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;->DARK_BLUR:Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle; # RL: force native Blur player background -+ -+ const/16 v21, 0x0 # RL: isPlaying=false (Static — no rotation) -+ -+ const/16 v22, 0x0 # RL: isSeeking=false (Static — no scrub rotation) -+ -+ invoke-static {}, Lradiant/HomeBackdrop;->setModeStatic()V # RL: mirror rotation to Cover Everywhere -+ - .line 171 - invoke-static/range {v16 .. v26}, Lcom/tidal/android/feature/playerscreen/ui/composables/p3;->b(Lcom/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle;JILjava/lang/String;ZZLam0/a;Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V - ---- a/com/tidal/android/core/ui/composable/c0.smali -+++ b/com/tidal/android/core/ui/composable/c0.smali -@@ -16,7 +16,9 @@ - move-result p0 - - .line 5 -- invoke-virtual {p2, p0}, Landroid/view/Window;->setNavigationBarColor(I)V -+ const/4 v3, 0x0 # RL: force transparent nav bar so the native blur backdrop shows through (was p0 = extracted BG color; luminance below still uses p0 for icon light/dark) -+ -+ invoke-virtual {p2, v3}, Landroid/view/Window;->setNavigationBarColor(I)V - - .line 6 - .line 7 ---- a/de0/c.smali -+++ b/de0/c.smali -@@ -26,29 +26,26 @@ - .line 2 - .line 3 - .line 4 -- const-string v0, "HeavyBlurTransformation() " -- -- .line 5 -- .line 6 -- const-string v1, " " -- -- .line 7 -- .line 8 -- const/4 v2, 0x6 -- -- .line 9 -- const/16 v3, 0x19 -- -- .line 10 -- .line 11 -- invoke-static {v2, v3, v0, v1}, Landroidx/compose/foundation/text/input/a;->b(IILjava/lang/String;Ljava/lang/String;)Ljava/lang/String; -- -- .line 12 -- .line 13 -- .line 14 -+ new-instance v0, Ljava/lang/StringBuilder; -+ invoke-direct {v0}, Ljava/lang/StringBuilder;->()V -+ const-string v1, "RLBackdrop_b" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const/16 v1, __RL_BLUR__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ const-string v1, "c" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const v1, __RL_CONTRAST__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ const-string v1, "s" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const v1, __RL_SATURATION__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ const-string v1, "r" -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; -+ const v1, __RL_BRIGHTNESS__ -+ invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; -+ invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; - move-result-object v0 -- -- .line 15 - iput-object v0, p0, Lde0/c;->a:Ljava/lang/String; - - .line 16 -@@ -59,10 +56,17 @@ - - # virtual methods - .method public final a(Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap; -- .locals 2 -+ .locals 3 - - .line 1 -- const/4 v0, 0x6 -+ const/16 v2, __RL_BLUR__ -+ mul-int/lit8 v0, v2, 0x6 -+ const/16 v1, 0x32 -+ div-int v0, v0, v1 -+ const/4 v1, 0x1 -+ if-ge v0, v1, :rl_ds_ok -+ const/4 v0, 0x1 -+ :rl_ds_ok - - .line 2 - invoke-static {p1, v0}, Lcom/squareup/ui/market/layout/e;->c(Landroid/graphics/Bitmap;I)Landroid/graphics/Bitmap; -@@ -82,7 +86,7 @@ - .line 9 - .line 10 - .line 11 -- const/16 v1, 0x19 -+ div-int/lit8 v1, v2, 0x2 - - .line 12 - .line 13 -@@ -93,6 +97,10 @@ - .line 16 - move-result-object v1 - -+ invoke-static {v1}, Lradiant/BackdropFx;->apply(Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap; -+ -+ move-result-object v1 -+ - .line 17 - invoke-virtual {v0}, Landroid/graphics/Bitmap;->recycle()V - diff --git a/tools/kawarp-build/build.sh b/tools/kawarp-build/build.sh new file mode 100755 index 0000000..06ab254 --- /dev/null +++ b/tools/kawarp-build/build.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# Compiles the Java-authored extension classes down to the hand-editable smali that the Manager +# injects. Everything under stubs/ exists only to satisfy javac - those classes are already in the +# TIDAL dex, so they are on the classpath but never compiled into the output. +# +# ./build.sh # regenerate ../../patches/extension/radiant/Kawarp*.smali +# +# Override JAVA_HOME / ANDROID_JAR / SMALI_TOOLS if your toolchain lives elsewhere. +set -euo pipefail + +here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repo="$(cd "$here/../.." && pwd)" + +JAVA_HOME="${JAVA_HOME:-/home/meow/toolchain/jdk-21.0.12+8}" +ANDROID_SDK="${ANDROID_SDK:-/home/meow/toolchain/android-sdk}" +ANDROID_JAR="${ANDROID_JAR:-$ANDROID_SDK/platforms/android-36/android.jar}" +D8="${D8:-$(ls -d "$ANDROID_SDK"/build-tools/*/d8 | sort | tail -1)}" +BAKSMALI="${BAKSMALI:-/home/meow/tools/baksmali.jar}" + +export PATH="$JAVA_HOME/bin:$PATH" +javac="$JAVA_HOME/bin/javac" +java="$JAVA_HOME/bin/java" +out="$here/build" + +rm -rf "$out" +mkdir -p "$out/stubs" "$out/classes" "$out/dex" "$out/smali" + +echo "==> javac stubs" +find "$here/stubs" -name '*.java' > "$out/stubs.list" +"$javac" -nowarn -g:none --release 8 -cp "$ANDROID_JAR" -d "$out/stubs" @"$out/stubs.list" 2>&1 | + grep -v 'bootstrap class path\|source value 8\|target value 8\|deprecat' || true + +# The Kawarp engine lives in the Kawarp-AGSL library repo and is compiled into this bundle. +# Expected checkout location (gitignored): tools/kawarp-agsl — clone it there, or point +# KAWARP_AGSL elsewhere. +KAWARP_AGSL="${KAWARP_AGSL:-$repo/tools/kawarp-agsl}" +ENGINE="$KAWARP_AGSL/kawarp/src/main/java/dev/kawarp/KawarpEngine.java" +[ -f "$ENGINE" ] || { echo "!! Kawarp-AGSL checkout not found at $KAWARP_AGSL" >&2 + echo " git clone https://github.com/meowarex/kawarp-agsl tools/kawarp-agsl" >&2 + exit 1; } + +echo "==> javac sources" +{ find "$here/src" -name '*.java'; echo "$ENGINE"; } > "$out/src.list" +"$javac" -nowarn -g:none --release 8 -cp "$ANDROID_JAR:$out/stubs" -d "$out/classes" @"$out/src.list" 2>&1 | + grep -v 'bootstrap class path\|source value 8\|target value 8\|deprecat' || true + +echo "==> d8" +find "$out/classes" -name '*.class' > "$out/class.list" +"$D8" --min-api 24 --no-desugaring --lib "$ANDROID_JAR" --classpath "$out/stubs" \ + --output "$out/dex" @"$out/class.list" + +echo "==> baksmali" +"$java" -jar "$BAKSMALI" d "$out/dex/classes.dex" -o "$out/smali" + +echo "==> post-process" +# Kotlin mangles value-class accessors with characters that are illegal in Java identifiers, so +# the stubs declare legal names and we restore the real ones here. +# The 0x5241xxxx sentinels are unfoldable stand-ins for the Manager's option placeholders. +find "$out/smali" -name '*.smali' -print0 | xargs -0 sed -i \ + -e 's/getSizeNHjbRc/getSize-NH-jbRc/g' \ + -e 's/getWidthImpl/getWidth-impl/g' \ + -e 's/getHeightImpl/getHeight-impl/g' \ + -e 's/0x52410001/__RL_KW_WARP__/g' \ + -e 's/0x52410002/__RL_KW_SPEED__/g' \ + -e 's/0x52410003/__RL_KW_SCALE__/g' \ + -e 's/0x52410004/__RL_KW_DITHER__/g' \ + -e 's/0x52410005/__RL_KW_DARKEN__/g' \ + -e 's/0x52410006/__RL_KW_REACTIVE__/g' \ + -e 's/0x52410007/__RL_KW_BLUR__/g' \ + -e 's/0x52410008/__RL_KW_CONTRAST__/g' \ + -e 's/0x52410009/__RL_KW_SAT__/g' \ + -e 's/0x5241000a/__RL_KW_BRIGHT__/g' + +leftover=$(grep -rl '0x5241000[0-9a-f]' "$out/smali" || true) +if [ -n "$leftover" ]; then + echo "!! un-tokenised sentinel left in: $leftover" >&2 + exit 1 +fi + +dest="$repo/patches/extension" +# Clear previous outputs first so a refactor that drops a class can't leave a stale file behind +# (stale extension smali still gets bundled and can break assembly). +rm -f "$dest"/radiant/Kawarp*.smali "$dest"/dev/kawarp/*.smali +mkdir -p "$dest/dev/kawarp" +for f in "$out"/smali/radiant/Kawarp*.smali "$out"/smali/dev/kawarp/*.smali; do + rel="${f#"$out"/smali/}" + cp "$f" "$dest/$rel" + echo " -> patches/extension/$rel" +done diff --git a/tools/kawarp-build/src/radiant/Kawarp.java b/tools/kawarp-build/src/radiant/Kawarp.java new file mode 100644 index 0000000..7eaad97 --- /dev/null +++ b/tools/kawarp-build/src/radiant/Kawarp.java @@ -0,0 +1,225 @@ +package radiant; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.SystemClock; +import android.util.Log; +import android.view.Choreographer; + +import androidx.compose.foundation.layout.SizeKt; +import androidx.compose.foundation.layout.SpacerKt; +import androidx.compose.runtime.Composer; +import androidx.compose.runtime.MutableState; +import androidx.compose.runtime.SnapshotStateKt; +import androidx.compose.ui.Modifier; +import androidx.compose.ui.draw.DrawModifierKt; +import androidx.compose.ui.geometry.Size; +import androidx.compose.ui.graphics.AndroidCanvas_androidKt; +import androidx.compose.ui.graphics.drawscope.DrawScope; + +import com.tidal.android.feature.playerscreen.ui.composables.p3; +import com.tidal.android.feature.playerscreen.ui.model.PlayerBackgroundStyle; + +import dev.kawarp.KawarpEngine; + +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * MARKER: Kawarp Backdrop - TIDAL glue over dev.kawarp.KawarpEngine (Kawarp-AGSL library) + * + * The engine (shader, blur pipeline, settings, crossfade) lives in the Kawarp-AGSL library + * (cloned at tools/kawarp-agsl) and is compiled into this bundle by tools/kawarp-build/build.sh; + * this class only holds what is TIDAL/Compose-specific: + * the patched-in composable entry points, cover fetching by TIDAL uuid, the Choreographer -> + * snapshot-state frame clock, the Manager's option tokens, and the fallback to TIDAL's own + * blurred backdrop. + * + * One class on purpose (its own draw lambda, frame callback and loader) - see the engine's + * class doc for the dex-injection constraints. + */ +public final class Kawarp implements am0.l, Runnable, Choreographer.FrameCallback { + + private static final String TAG = "RLKawarp"; + /** Stop the frame loop once nothing has drawn for this long (player left / backgrounded). */ + private static final long IDLE_STOP_MS = 500L; + + /** + * Patch option plumbing. The 0x5241xxxx literals are sentinels that build.sh rewrites into + * __RL_*__ placeholders for the Manager to substitute; routing them through tk() stops javac + * constant-folding them out of existence. + */ + private static int tk(int v) { return v; } + + private static final ExecutorService LOADER = Executors.newSingleThreadExecutor(); + + /** Bumped every frame so the draw lambda's snapshot read invalidates the draw phase. */ + private static final MutableState frameState = + SnapshotStateKt.mutableStateOf$default(Integer.valueOf(0), null, 2, null); + /** Flips true on any shader failure; read during composition so we recompose onto p3.a. */ + private static final MutableState fallbackState = + SnapshotStateKt.mutableStateOf$default(Boolean.FALSE, null, 2, null); + + /** The shared instance render passes to drawBehind (also serves as the frame callback). */ + private static final Kawarp DRAW = new Kawarp(null, 0); + + private static KawarpEngine engine; + private static volatile String requestedUuid; + private static volatile int loadToken; + + private static long lastDrawUptime; + private static boolean frameScheduled, loggedDraw; + private static int frameTick; + + /** Set when this instance is a queued cover load; null/0 on the shared DRAW instance. */ + private final String uuid; + private final int token; + + private Kawarp(String uuid, int token) { + this.uuid = uuid; + this.token = token; + } + + + // Composition + + + /** + * Drop-in replacement for TIDAL's PlayerBackground composable (p3.b) - the patch redirects + * the call site here so the whole backdrop works <3 + */ + public static void b(PlayerBackgroundStyle style, long color, int albumId, String coverUuid, + boolean isPlaying, boolean isSeeking, am0.a progress, Modifier modifier, + Composer composer, int changed) { + render(albumId, coverUuid, isPlaying, modifier, composer); + } + + /** Shared by the player screen and by Cover Everywhere (radiant/HomeBackdrop). */ + public static void render(int albumId, String coverUuid, boolean isPlaying, + Modifier modifier, Composer composer) { + composer.startReplaceGroup(0x52415750); + boolean ok = !((Boolean) fallbackState.getValue()).booleanValue() && ensureEngine(); + if (!ok) { + // No (working) AGSL here - fall back to TIDAL's own blurred backdrop. + p3.a(albumId, coverUuid, isPlaying, false, null, modifier, composer, 0); + } else { + engine.setPlaying(isPlaying); + request(coverUuid); + Modifier m = DrawModifierKt.drawBehind(SizeKt.fillMaxSize(modifier, 1.0f), DRAW); + SpacerKt.Spacer(m, composer, 0); + } + composer.endReplaceGroup(); + } + + /** Engine construction compiles the AGSL so this doubles as the support probe. */ + private static boolean ensureEngine() { + if (engine != null) return true; + if (!KawarpEngine.isSupported()) return false; + try { + KawarpEngine e = new KawarpEngine(); + e.setWarpIntensity(Float.intBitsToFloat(tk(0x52410001))); + e.setAnimationSpeed(Float.intBitsToFloat(tk(0x52410002))); + e.setScale(Float.intBitsToFloat(tk(0x52410003))); + e.setDithering(Float.intBitsToFloat(tk(0x52410004))); + e.setAutoDarken(Float.intBitsToFloat(tk(0x52410005))); + e.setPlaybackReactive(tk(0x52410006) != 0); + e.setBlurPasses(tk(0x52410007)); + e.setContrast(Float.intBitsToFloat(tk(0x52410008))); + e.setSaturation(Float.intBitsToFloat(tk(0x52410009))); + e.setBrightness(Float.intBitsToFloat(tk(0x5241000a))); + engine = e; + return true; + } catch (Throwable t) { + Log.i(TAG, "AGSL rejected, staying on the native backdrop: " + t); + fallbackState.setValue(Boolean.TRUE); + return false; + } + } + + + // Cover loading (Runnable on LOADER) + + + private static void request(String coverUuid) { + if (coverUuid == null || coverUuid.length() == 0 || coverUuid.equals(requestedUuid)) return; + requestedUuid = coverUuid; + LOADER.execute(new Kawarp(coverUuid, ++loadToken)); + } + + public void run() { + HttpURLConnection connection = null; + try { + // Same URL shape TIDAL itself builds in he0.a; 640 is plenty ahead of a 128 downscale. + URL url = new URL("https://resources.tidal.com/images/" + + uuid.replace('-', '/') + "/640x640.jpg"); + connection = (HttpURLConnection) url.openConnection(); + connection.setConnectTimeout(10000); + connection.setReadTimeout(15000); + InputStream stream = connection.getInputStream(); + Bitmap source; + try { + source = BitmapFactory.decodeStream(stream); + } finally { + stream.close(); + } + if (source == null || token != loadToken) return; + engine.setCover(source); + source.recycle(); + Log.i(TAG, "cover submitted: " + uuid); + } catch (Throwable t) { + Log.i(TAG, "cover load failed: " + t); + // Let the next track (or a re-entry into the player) retry this cover. + if (token == loadToken) requestedUuid = null; + } finally { + if (connection != null) connection.disconnect(); + } + } + + + // Frame loop + + + public void doFrame(long frameTimeNanos) { + frameScheduled = false; + // Nothing has drawn for a while: the backdrop is off-screen, so stop burning frames. + if (SystemClock.uptimeMillis() - lastDrawUptime > IDLE_STOP_MS) return; + frameState.setValue(Integer.valueOf(++frameTick)); + schedule(); + } + + private static void schedule() { + if (frameScheduled) return; + frameScheduled = true; + Choreographer.getInstance().postFrameCallback(DRAW); + } + + public Object invoke(Object scope) { + draw((DrawScope) scope); + return kotlin.u.a; + } + + private static void draw(DrawScope scope) { + // Snapshot read: this is what ties the draw phase to the frame clock. + frameState.getValue(); + lastDrawUptime = SystemClock.uptimeMillis(); + schedule(); + + long packed = scope.getSizeNHjbRc(); + float width = Size.getWidthImpl(packed); + float height = Size.getHeightImpl(packed); + if (!loggedDraw) { + loggedDraw = true; + Log.i(TAG, "first draw: " + width + "x" + height + " ready=" + engine.isReady()); + } + try { + engine.draw(AndroidCanvas_androidKt.getNativeCanvas(scope.getDrawContext().getCanvas()), + width, height); + } catch (Throwable t) { + Log.i(TAG, "AGSL draw failed, falling back: " + t); + fallbackState.setValue(Boolean.TRUE); + } + } +} diff --git a/tools/kawarp-build/stubs/am0/a.java b/tools/kawarp-build/stubs/am0/a.java new file mode 100644 index 0000000..8159754 --- /dev/null +++ b/tools/kawarp-build/stubs/am0/a.java @@ -0,0 +1,3 @@ +package am0; +/** kotlin.jvm.functions.Function0 (obfuscated in the TIDAL dex). */ +public interface a { Object invoke(); } diff --git a/tools/kawarp-build/stubs/am0/l.java b/tools/kawarp-build/stubs/am0/l.java new file mode 100644 index 0000000..beacc75 --- /dev/null +++ b/tools/kawarp-build/stubs/am0/l.java @@ -0,0 +1,3 @@ +package am0; +/** kotlin.jvm.functions.Function1 (obfuscated in the TIDAL dex). */ +public interface l { Object invoke(Object p1); } diff --git a/tools/kawarp-build/stubs/androidx/compose/foundation/layout/SizeKt.java b/tools/kawarp-build/stubs/androidx/compose/foundation/layout/SizeKt.java new file mode 100644 index 0000000..ef6dcff --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/foundation/layout/SizeKt.java @@ -0,0 +1,5 @@ +package androidx.compose.foundation.layout; +import androidx.compose.ui.Modifier; +public final class SizeKt { + public static Modifier fillMaxSize(Modifier modifier, float fraction) { return null; } +} diff --git a/tools/kawarp-build/stubs/androidx/compose/foundation/layout/SpacerKt.java b/tools/kawarp-build/stubs/androidx/compose/foundation/layout/SpacerKt.java new file mode 100644 index 0000000..edef3dc --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/foundation/layout/SpacerKt.java @@ -0,0 +1,6 @@ +package androidx.compose.foundation.layout; +import androidx.compose.runtime.Composer; +import androidx.compose.ui.Modifier; +public final class SpacerKt { + public static void Spacer(Modifier modifier, Composer composer, int changed) {} +} diff --git a/tools/kawarp-build/stubs/androidx/compose/runtime/Composer.java b/tools/kawarp-build/stubs/androidx/compose/runtime/Composer.java new file mode 100644 index 0000000..7c4015c --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/runtime/Composer.java @@ -0,0 +1,5 @@ +package androidx.compose.runtime; +public interface Composer { + void startReplaceGroup(int key); + void endReplaceGroup(); +} diff --git a/tools/kawarp-build/stubs/androidx/compose/runtime/MutableState.java b/tools/kawarp-build/stubs/androidx/compose/runtime/MutableState.java new file mode 100644 index 0000000..cce826a --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/runtime/MutableState.java @@ -0,0 +1,2 @@ +package androidx.compose.runtime; +public interface MutableState extends State { void setValue(Object value); } diff --git a/tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotMutationPolicy.java b/tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotMutationPolicy.java new file mode 100644 index 0000000..afb9f57 --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotMutationPolicy.java @@ -0,0 +1,2 @@ +package androidx.compose.runtime; +public interface SnapshotMutationPolicy {} diff --git a/tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotStateKt.java b/tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotStateKt.java new file mode 100644 index 0000000..8cedb22 --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/runtime/SnapshotStateKt.java @@ -0,0 +1,4 @@ +package androidx.compose.runtime; +public final class SnapshotStateKt { + public static MutableState mutableStateOf$default(Object value, SnapshotMutationPolicy policy, int flags, Object marker) { return null; } +} diff --git a/tools/kawarp-build/stubs/androidx/compose/runtime/State.java b/tools/kawarp-build/stubs/androidx/compose/runtime/State.java new file mode 100644 index 0000000..809f90d --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/runtime/State.java @@ -0,0 +1,2 @@ +package androidx.compose.runtime; +public interface State { Object getValue(); } diff --git a/tools/kawarp-build/stubs/androidx/compose/ui/Modifier.java b/tools/kawarp-build/stubs/androidx/compose/ui/Modifier.java new file mode 100644 index 0000000..6a11b4e --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/ui/Modifier.java @@ -0,0 +1,6 @@ +package androidx.compose.ui; +public interface Modifier { + /** Non-constant initialiser so javac emits a real sget-object. */ + Companion Companion = new Companion(); + final class Companion implements Modifier {} +} diff --git a/tools/kawarp-build/stubs/androidx/compose/ui/draw/DrawModifierKt.java b/tools/kawarp-build/stubs/androidx/compose/ui/draw/DrawModifierKt.java new file mode 100644 index 0000000..0d5ef27 --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/ui/draw/DrawModifierKt.java @@ -0,0 +1,5 @@ +package androidx.compose.ui.draw; +import androidx.compose.ui.Modifier; +public final class DrawModifierKt { + public static Modifier drawBehind(Modifier modifier, am0.l onDraw) { return null; } +} diff --git a/tools/kawarp-build/stubs/androidx/compose/ui/geometry/Size.java b/tools/kawarp-build/stubs/androidx/compose/ui/geometry/Size.java new file mode 100644 index 0000000..8dabcaa --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/ui/geometry/Size.java @@ -0,0 +1,7 @@ +package androidx.compose.ui.geometry; +public final class Size { + /** Renamed to getWidth-impl by build.sh (Kotlin value-class mangling). */ + public static float getWidthImpl(long packed) { return 0f; } + /** Renamed to getHeight-impl by build.sh (Kotlin value-class mangling). */ + public static float getHeightImpl(long packed) { return 0f; } +} diff --git a/tools/kawarp-build/stubs/androidx/compose/ui/graphics/AndroidCanvas_androidKt.java b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/AndroidCanvas_androidKt.java new file mode 100644 index 0000000..6ae5ef5 --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/AndroidCanvas_androidKt.java @@ -0,0 +1,4 @@ +package androidx.compose.ui.graphics; +public final class AndroidCanvas_androidKt { + public static android.graphics.Canvas getNativeCanvas(Canvas canvas) { return null; } +} diff --git a/tools/kawarp-build/stubs/androidx/compose/ui/graphics/Canvas.java b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/Canvas.java new file mode 100644 index 0000000..1bac6de --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/Canvas.java @@ -0,0 +1,2 @@ +package androidx.compose.ui.graphics; +public interface Canvas {} diff --git a/tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawContext.java b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawContext.java new file mode 100644 index 0000000..c6c3189 --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawContext.java @@ -0,0 +1,3 @@ +package androidx.compose.ui.graphics.drawscope; +import androidx.compose.ui.graphics.Canvas; +public interface DrawContext { Canvas getCanvas(); } diff --git a/tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawScope.java b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawScope.java new file mode 100644 index 0000000..08a6467 --- /dev/null +++ b/tools/kawarp-build/stubs/androidx/compose/ui/graphics/drawscope/DrawScope.java @@ -0,0 +1,6 @@ +package androidx.compose.ui.graphics.drawscope; +public interface DrawScope { + DrawContext getDrawContext(); + /** Renamed to getSize-NH-jbRc by build.sh (Kotlin value-class mangling). */ + long getSizeNHjbRc(); +} diff --git a/tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/composables/p3.java b/tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/composables/p3.java new file mode 100644 index 0000000..5976020 --- /dev/null +++ b/tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/composables/p3.java @@ -0,0 +1,8 @@ +package com.tidal.android.feature.playerscreen.ui.composables; +import androidx.compose.runtime.Composer; +import androidx.compose.ui.Modifier; +/** TIDAL's DarkBlurBackground composable (used as the pre-Android-13 fallback). */ +public final class p3 { + public static void a(int albumId, String coverUuid, boolean isPlaying, boolean isSeeking, + am0.a progress, Modifier modifier, Composer composer, int changed) {} +} diff --git a/tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle.java b/tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle.java new file mode 100644 index 0000000..1feca94 --- /dev/null +++ b/tools/kawarp-build/stubs/com/tidal/android/feature/playerscreen/ui/model/PlayerBackgroundStyle.java @@ -0,0 +1,2 @@ +package com.tidal.android.feature.playerscreen.ui.model; +public final class PlayerBackgroundStyle {} diff --git a/tools/kawarp-build/stubs/kotlin/u.java b/tools/kawarp-build/stubs/kotlin/u.java new file mode 100644 index 0000000..2ff176c --- /dev/null +++ b/tools/kawarp-build/stubs/kotlin/u.java @@ -0,0 +1,3 @@ +package kotlin; +/** kotlin.Unit (obfuscated in the TIDAL dex). */ +public final class u { public static final u a = null; }