Highlight a cell on the arrangement roll and Play now begins at that selection's first beat instead of always from the top. Stop clears the highlight, so the next Play resumes from the beginning. The rectangular selection is hoisted from ArrangementRoll to the ViewModel (four ints) so the transport can read/clear it; engine.play() gains a startBeat that seeks playlistIndex in the built playlist (A/B expansion respected; falls back to the top if the beat isn't in it) or currentLine in pattern-loop mode. Loading/importing a project also clears the selection so a stale one can't apply to a new arrangement. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
138 lines
5.1 KiB
Kotlin
138 lines
5.1 KiB
Kotlin
// Build configuration for the single application module. This is where we turn
|
|
// on Compose, set the min/target Android versions, and list dependencies.
|
|
|
|
plugins {
|
|
alias(libs.plugins.android.application)
|
|
alias(libs.plugins.kotlin.android)
|
|
alias(libs.plugins.kotlin.compose)
|
|
}
|
|
|
|
android {
|
|
namespace = "space.rcmd.android.sizzle"
|
|
compileSdk = 34
|
|
|
|
// Native (Oboe) low-latency output backend; see src/main/cpp.
|
|
// NDK r27+ builds native libs 16 KB-page-aligned by default and ships a
|
|
// 16 KB-aligned libc++_shared.so (required for Android 15 / Google Play).
|
|
ndkVersion = "27.2.12479018"
|
|
|
|
defaultConfig {
|
|
applicationId = "space.rcmd.android.sizzle"
|
|
// minSdk 26 (Android 8.0) is the floor for the native MIDI API
|
|
// (android.media.midi) and AAudio low-latency audio we rely on.
|
|
minSdk = 26
|
|
targetSdk = 34
|
|
versionCode = 45
|
|
versionName = "0.19.0"
|
|
|
|
// We provide our own instrumentation runner if/when tests are added.
|
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
|
|
externalNativeBuild {
|
|
cmake { arguments += "-DANDROID_STL=c++_shared" }
|
|
}
|
|
}
|
|
|
|
externalNativeBuild {
|
|
cmake {
|
|
path = file("src/main/cpp/CMakeLists.txt")
|
|
version = "3.22.1"
|
|
}
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
// Shrinking is off by default so newcomers get readable stack traces.
|
|
// Flip to true once the app stabilises.
|
|
isMinifyEnabled = false
|
|
proguardFiles(
|
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
"proguard-rules.pro",
|
|
)
|
|
}
|
|
|
|
// A realistic-performance "staging" variant for testing UI responsiveness
|
|
// on-device. The `debug` build is `debuggable = true`, which makes ART run
|
|
// the app un-optimised and makes Compose several times slower — so measuring
|
|
// UI "snappiness" on a debug build is misleading. This variant flips
|
|
// debuggability off (the single biggest perf lever) while reusing the debug
|
|
// signing key, so it still installs without a release keystore. R8/shrinking
|
|
// stays off to avoid needing JNI/Compose keep-rules for now.
|
|
create("staging") {
|
|
initWith(getByName("debug"))
|
|
isDebuggable = false
|
|
isJniDebuggable = false
|
|
signingConfig = signingConfigs.getByName("debug")
|
|
matchingFallbacks += "debug"
|
|
}
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
|
|
kotlinOptions {
|
|
jvmTarget = "17"
|
|
}
|
|
|
|
buildFeatures {
|
|
compose = true
|
|
prefab = true // exposes the Oboe AAR's native headers/lib to CMake
|
|
}
|
|
|
|
packaging {
|
|
resources.excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
|
}
|
|
}
|
|
|
|
// Give the release APK a predictable, versionCode-stamped name so it drops straight
|
|
// into the private F-Droid repo: space.rcmd.android.sizzle_<versionCode>.apk. Uses
|
|
// the legacy variant API (the Kotlin-DSL `android {}` receiver doesn't expose it).
|
|
(extensions.getByName("android") as com.android.build.gradle.AbstractAppExtension)
|
|
.applicationVariants.all {
|
|
if (buildType.name == "release") {
|
|
val vc = versionCode
|
|
outputs.all {
|
|
(this as com.android.build.gradle.internal.api.BaseVariantOutputImpl)
|
|
.outputFileName = "space.rcmd.android.sizzle_$vc.apk"
|
|
}
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
implementation(libs.androidx.core.ktx)
|
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
|
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
|
implementation(libs.androidx.activity.compose)
|
|
|
|
// Compose UI toolkit — the BOM keeps every Compose artifact on one version.
|
|
implementation(platform(libs.androidx.compose.bom))
|
|
implementation(libs.androidx.compose.ui)
|
|
implementation(libs.androidx.compose.ui.graphics)
|
|
implementation(libs.androidx.compose.ui.tooling.preview)
|
|
implementation(libs.androidx.compose.foundation)
|
|
implementation(libs.androidx.compose.material3)
|
|
implementation(libs.androidx.compose.material.icons.extended)
|
|
debugImplementation(libs.androidx.compose.ui.tooling)
|
|
|
|
// Background playback + media-style notification transport controls.
|
|
implementation(libs.androidx.media3.session)
|
|
implementation(libs.androidx.media3.common)
|
|
|
|
// Persistence for settings & themes.
|
|
implementation(libs.androidx.datastore.preferences)
|
|
|
|
// Coroutines for the audio/sequencer background work.
|
|
implementation(libs.kotlinx.coroutines.android)
|
|
|
|
// Oboe: low-latency native audio (AAudio) — the native output backend.
|
|
// 1.9.3+ ships 16 KB-page-aligned .so files (required by Android 15 / Play).
|
|
implementation("com.google.oboe:oboe:1.10.0")
|
|
|
|
// JVM unit tests for the pure model/io logic (no device needed).
|
|
testImplementation("junit:junit:4.13.2")
|
|
// Virtual-time coroutine testing (drives the input hold-to-repeat schedule).
|
|
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
|
|
}
|