From 2d459867bf3e926e23fb857a48b9aff43cbd1568 Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Sun, 8 Nov 2026 00:35:22 +0100 Subject: [PATCH 1/5] refactor(kotlin): keep the hand-written runtime free of Android APIs Prepares the split into a platform-independent core library (#2458): only the Android integration may depend on Android APIs. - EnvironmentPartials registers no Android render engine and prints no device details. AndroidEnvironment.initializeAndroid registers the "android" engine and the device lines instead; AlphaTabView calls it before it creates the API, so the log output is unchanged. - RegExp uses its own replacement loop on every API level instead of Matcher.replaceAll/replaceFirst(Function) on Android 14+. That path is what all JVM unit tests already ran. Unlike the JDK overloads it inserts the replacer result literally (JavaScript semantics), so a '$' or '\' in it no longer acts as a group reference on Android 14+. - The Java thread workers move to alphaTab.platform.jvm as they do not depend on Android. --- .../main/java/alphaTab/EnvironmentPartials.kt | 21 ++++----- .../java/alphaTab/core/ecmaScript/RegExp.kt | 46 +++++++------------ .../platform/android/AndroidEnvironment.kt | 13 ++++++ .../platform/android/AndroidUiFacade.kt | 2 + .../{android => jvm}/JavaThreadWorkers.kt | 2 +- 5 files changed, 41 insertions(+), 43 deletions(-) rename packages/kotlin/src/android/src/main/java/alphaTab/platform/{android => jvm}/JavaThreadWorkers.kt (99%) diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/EnvironmentPartials.kt b/packages/kotlin/src/android/src/main/java/alphaTab/EnvironmentPartials.kt index d2b5ee8f6e..25eb8ed2da 100644 --- a/packages/kotlin/src/android/src/main/java/alphaTab/EnvironmentPartials.kt +++ b/packages/kotlin/src/android/src/main/java/alphaTab/EnvironmentPartials.kt @@ -2,15 +2,12 @@ package alphaTab import alphaTab.collections.DoubleList import alphaTab.platform.Json -import alphaTab.platform.android.AndroidCanvas -import alphaTab.platform.android.AndroidEnvironment -import alphaTab.platform.android.JavaThreadAlphaSynthWorker -import alphaTab.platform.android.JavaThreadAlphaTabRendererWorker +import alphaTab.platform.jvm.JavaThreadAlphaSynthWorker +import alphaTab.platform.jvm.JavaThreadAlphaTabRendererWorker import alphaTab.platform.worker.IAlphaSynthWorkerMessage import alphaTab.platform.worker.IAlphaTabWorkerGlobalScope import alphaTab.platform.worker.IAlphaTabWorkerMessage import alphaTab.synth.AudioExportOptions -import android.os.Build import kotlin.contracts.ExperimentalContracts @@ -18,11 +15,12 @@ import kotlin.contracts.ExperimentalContracts @ExperimentalUnsignedTypes internal class EnvironmentPartials { companion object { + /** + * Prints additional information about the host platform (e.g. the Android device). + */ + internal var printHostInfo: ((print: (message: String) -> Unit) -> Unit)? = null + internal fun _createPlatformSpecificRenderEngines(engines: alphaTab.collections.Map) { - engines.set( - "android", - RenderEngineFactory(true) { AndroidCanvas() } - ) engines.set( "default", engines.get("skia")!! @@ -32,10 +30,7 @@ internal class EnvironmentPartials { internal fun _printPlatformInfo(print: (message: String) -> Unit) { print("OS Name: ${System.getProperty("os.name")}"); print("OS Version: ${System.getProperty("os.version")}"); - print("Device Brand: ${Build.MANUFACTURER}"); - print("Device Model: ${Build.MODEL}"); - print("SDK Version: ${Build.VERSION.SDK_INT}"); - print("Screen Size: ${AndroidEnvironment.screenWidth}x${AndroidEnvironment.screenHeight}"); + printHostInfo?.invoke(print) } @Suppress("NOTHING_TO_INLINE") diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/RegExp.kt b/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/RegExp.kt index e468b9648c..b0e9914f40 100644 --- a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/RegExp.kt +++ b/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/RegExp.kt @@ -1,6 +1,5 @@ package alphaTab.core.ecmaScript -import android.os.Build import java.util.regex.MatchResult import java.util.regex.Pattern @@ -69,42 +68,31 @@ internal class RegExp { } } + // Matcher.replaceAll(Function) would interpret '$' and '\' in the replacement and needs Android API 34. private fun replaceMatch(s: String, replacement: (result: MatchResult) -> String): String { val matcher = _regex.matcher(s); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - return if (_global) - matcher.replaceAll { - replacement(it) - } - else - matcher.replaceFirst { - replacement(it) - } - } else { - // custom implementation for older android versions - if (!matcher.find()) { - return s; - } - - val sb = StringBuilder() + if (!matcher.find()) { + return s; + } - var appendPos = 0 - if (_global) { + val sb = StringBuilder() - do { - sb.append(s, appendPos, matcher.start()) - sb.append(replacement(matcher)) - appendPos = matcher.end() - } while (matcher.find()) + var appendPos = 0 + if (_global) { - sb.append(s, appendPos, s.length) - } else { + do { sb.append(s, appendPos, matcher.start()) sb.append(replacement(matcher)) - sb.append(s, matcher.end(), s.length) - } + appendPos = matcher.end() + } while (matcher.find()) - return sb.toString() + sb.append(s, appendPos, s.length) + } else { + sb.append(s, appendPos, matcher.start()) + sb.append(replacement(matcher)) + sb.append(s, matcher.end(), s.length) } + + return sb.toString() } } diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidEnvironment.kt b/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidEnvironment.kt index 31c4229727..eaa17f55f7 100644 --- a/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidEnvironment.kt +++ b/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidEnvironment.kt @@ -1,9 +1,12 @@ package alphaTab.platform.android import alphaTab.Environment +import alphaTab.EnvironmentPartials +import alphaTab.RenderEngineFactory import alphaTab.alphaSkia.AlphaSkiaAndroid import alphaTab.core.ecmaScript.ArrayBuffer import android.graphics.Typeface +import android.os.Build import android.util.DisplayMetrics import kotlin.contracts.ExperimentalContracts @@ -28,6 +31,16 @@ internal class AndroidEnvironment { screenHeight = context.resources.displayMetrics.heightPixels AndroidCanvas.initialize(context) + Environment.renderEngines.set( + "android", + RenderEngineFactory(true) { AndroidCanvas() } + ) + EnvironmentPartials.printHostInfo = { print -> + print("Device Brand: ${Build.MANUFACTURER}"); + print("Device Model: ${Build.MODEL}"); + print("SDK Version: ${Build.VERSION.SDK_INT}"); + print("Screen Size: ${screenWidth}x${screenHeight}"); + } var bravuraBytes: ByteArray; context.assets.open("Bravura.otf").use { diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidUiFacade.kt b/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidUiFacade.kt index e8bca30ebd..d888d0679e 100644 --- a/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidUiFacade.kt +++ b/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/AndroidUiFacade.kt @@ -13,6 +13,8 @@ import alphaTab.platform.Cursors import alphaTab.platform.IContainer import alphaTab.platform.IMouseEventArgs import alphaTab.platform.IUiFacade +import alphaTab.platform.jvm.JavaThreadAlphaSynthWorker +import alphaTab.platform.jvm.JavaThreadAlphaTabRendererWorker import alphaTab.platform.skia.AlphaSkiaImage import alphaTab.platform.worker.AlphaSynthAudioExporterWorkerApi import alphaTab.platform.worker.AlphaSynthWebWorkerApi diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/JavaThreadWorkers.kt b/packages/kotlin/src/android/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt similarity index 99% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/android/JavaThreadWorkers.kt rename to packages/kotlin/src/android/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt index 8e99ac5ecd..e07f8d3ccd 100644 --- a/packages/kotlin/src/android/src/main/java/alphaTab/platform/android/JavaThreadWorkers.kt +++ b/packages/kotlin/src/android/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt @@ -1,4 +1,4 @@ -package alphaTab.platform.android +package alphaTab.platform.jvm import alphaTab.core.ecmaScript.MessageEvent import alphaTab.platform.worker.AlphaSynthWebWorker From cc5be0d6fe06aa655c2a479ee1bc987b276cf143 Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Sun, 8 Nov 2026 00:37:29 +0100 Subject: [PATCH 2/5] build(kotlin): publish a platform-independent alphaTab-core library The Kotlin target is split like the .NET one (AlphaTab + AlphaTab.Windows) so alphaTab can be used on any JVM, not only on Android (#2458). - New Gradle module :core (Kotlin/JVM) receives all transpiled code, the portable hand-written runtime and all tests. It is published as net.alphatab:alphaTab-core. Tests run as plain JUnit via :core:check. - :android keeps AlphaTabView and the Android platform code and is still published as net.alphatab:alphaTab. It depends on the core via api, so Android apps need no change. - The Android module reaches core internals through Kotlin friend paths, the counterpart of InternalsVisibleTo. Its Gradle module metadata pins alphaTab-core with a strict version, since internal members are not stable across versions. - The core compiles against the Java 17 class library (-Xjdk-release) and Animal Sniffer checks it against the Android API 26 signatures, so it cannot start using JDK APIs that Android lacks. - alphaSkia is an api dependency of the core: JVM applications call its native initialization themselves. - Explicit Kotlin module names avoid clashing META-INF/*.kotlin_module files in apps. - Shared publishing metadata and the version moved to the root build. --- packages/kotlin/package.json | 6 +- packages/kotlin/scripts/transpile.ts | 4 +- packages/kotlin/src/android/build.gradle.kts | 164 +++--------------- packages/kotlin/src/build.gradle.kts | 117 +++++++++++++ packages/kotlin/src/core/build.gradle.kts | 80 +++++++++ .../main/java/alphaTab/EnvironmentPartials.kt | 0 .../java/alphaTab/collections/BooleanList.kt | 0 .../alphaTab/collections/DoubleBooleanMap.kt | 0 .../alphaTab/collections/DoubleDoubleMap.kt | 0 .../java/alphaTab/collections/DoubleList.kt | 0 .../alphaTab/collections/DoubleObjectMap.kt | 0 .../java/alphaTab/collections/HashHelpers.kt | 0 .../collections/KeyNotFoundException.kt | 0 .../main/java/alphaTab/collections/List.kt | 0 .../src/main/java/alphaTab/collections/Map.kt | 0 .../main/java/alphaTab/collections/MapBase.kt | 0 .../alphaTab/collections/ObjectBooleanMap.kt | 0 .../alphaTab/collections/ObjectDoubleMap.kt | 0 .../alphaTab/collections/SimpleIterable.kt | 0 .../src/main/java/alphaTab/core/ArrayTuple.kt | 0 .../src/main/java/alphaTab/core/Console.kt | 0 .../src/main/java/alphaTab/core/Globals.kt | 0 .../main/java/alphaTab/core/IAlphaTabEnum.kt | 0 .../src/main/java/alphaTab/core/IRecord.kt | 0 .../src/main/java/alphaTab/core/TypeHelper.kt | 0 .../java/alphaTab/core/ecmaScript/Array.kt | 0 .../alphaTab/core/ecmaScript/ArrayBuffer.kt | 0 .../java/alphaTab/core/ecmaScript/BigInt.kt | 0 .../alphaTab/core/ecmaScript/CoreString.kt | 0 .../java/alphaTab/core/ecmaScript/DataView.kt | 0 .../java/alphaTab/core/ecmaScript/Date.kt | 0 .../java/alphaTab/core/ecmaScript/Error.kt | 0 .../alphaTab/core/ecmaScript/Float32Array.kt | 0 .../alphaTab/core/ecmaScript/Int16Array.kt | 0 .../alphaTab/core/ecmaScript/Int32Array.kt | 0 .../alphaTab/core/ecmaScript/Int8Array.kt | 0 .../java/alphaTab/core/ecmaScript/JSON.kt | 0 .../java/alphaTab/core/ecmaScript/Math.kt | 0 .../alphaTab/core/ecmaScript/MessageEvent.kt | 0 .../java/alphaTab/core/ecmaScript/Number.kt | 0 .../java/alphaTab/core/ecmaScript/Object.kt | 0 .../java/alphaTab/core/ecmaScript/Promise.kt | 0 .../core/ecmaScript/PromiseWithResolvers.kt | 0 .../java/alphaTab/core/ecmaScript/Record.kt | 0 .../java/alphaTab/core/ecmaScript/RegExp.kt | 0 .../main/java/alphaTab/core/ecmaScript/Set.kt | 0 .../alphaTab/core/ecmaScript/TextDecoder.kt | 0 .../alphaTab/core/ecmaScript/TextEncoder.kt | 0 .../alphaTab/core/ecmaScript/Uint16Array.kt | 0 .../alphaTab/core/ecmaScript/Uint32Array.kt | 0 .../alphaTab/core/ecmaScript/Uint8Array.kt | 0 .../alphaTex/AlphaTex1EnumMappingsPartials.kt | 0 .../SimpleAlphaTexParameterDefinition.kt | 0 .../java/alphaTab/io/JsonHelperPartials.kt | 0 .../main/java/alphaTab/io/TypeConversions.kt | 0 .../platform/jvm/JavaThreadWorkers.kt | 0 .../alphaTab/platform/skia/AlphaSkiaCanvas.kt | 0 .../alphaTab/platform/skia/AlphaSkiaImage.kt | 0 .../platform/skia/AlphaSkiaTextAlign.kt | 0 .../platform/skia/AlphaSkiaTextBaseline.kt | 0 .../platform/skia/AlphaSkiaTextMetrics.kt | 0 .../platform/skia/AlphaSkiaTextStyle.kt | 0 .../platform/skia/AlphaSkiaTypeface.kt | 0 .../platform/skia/SkiaCanvasPartials.kt | 0 .../platform/svg/FontSizesPartials.kt | 0 .../java/alphaTab/platform/svg/SvgBuffer.kt | 0 .../src/main/java/alphaTab/util/Lazy.kt | 0 .../java/alphaTab/PrettyFormatPartials.kt | 0 .../alphaTab/ScoreSerializerPluginPartials.kt | 0 .../java/alphaTab/TestPlatformPartialsImpl.kt | 0 .../test/java/alphaTab/core/TestGlobals.kt | 0 .../model/ComparisonHelpersPartialsImpl.kt | 0 .../visualTests/VisualTestHelperPartials.kt | 0 packages/kotlin/src/gradle/libs.versions.toml | 6 + packages/kotlin/src/settings.gradle.kts | 1 + scripts/update-version.mjs | 2 +- 76 files changed, 235 insertions(+), 145 deletions(-) create mode 100644 packages/kotlin/src/core/build.gradle.kts rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/EnvironmentPartials.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/BooleanList.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/DoubleBooleanMap.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/DoubleDoubleMap.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/DoubleList.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/DoubleObjectMap.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/HashHelpers.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/KeyNotFoundException.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/List.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/Map.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/MapBase.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/ObjectBooleanMap.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/ObjectDoubleMap.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/collections/SimpleIterable.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ArrayTuple.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/Console.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/Globals.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/IAlphaTabEnum.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/IRecord.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/TypeHelper.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/ArrayBuffer.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/BigInt.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/CoreString.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/DataView.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Date.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Error.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Float32Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Int16Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Int32Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Int8Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/JSON.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Math.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/MessageEvent.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Number.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Object.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Promise.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/PromiseWithResolvers.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Record.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/RegExp.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Set.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/TextDecoder.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/TextEncoder.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Uint16Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Uint32Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/core/ecmaScript/Uint8Array.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/importer/alphaTex/AlphaTex1EnumMappingsPartials.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/importer/alphaTex/SimpleAlphaTexParameterDefinition.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/io/JsonHelperPartials.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/io/TypeConversions.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/AlphaSkiaCanvas.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/AlphaSkiaImage.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/AlphaSkiaTextAlign.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/AlphaSkiaTextBaseline.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/AlphaSkiaTextMetrics.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/AlphaSkiaTextStyle.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/AlphaSkiaTypeface.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/skia/SkiaCanvasPartials.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/svg/FontSizesPartials.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/platform/svg/SvgBuffer.kt (100%) rename packages/kotlin/src/{android => core}/src/main/java/alphaTab/util/Lazy.kt (100%) rename packages/kotlin/src/{android => core}/src/test/java/alphaTab/PrettyFormatPartials.kt (100%) rename packages/kotlin/src/{android => core}/src/test/java/alphaTab/ScoreSerializerPluginPartials.kt (100%) rename packages/kotlin/src/{android => core}/src/test/java/alphaTab/TestPlatformPartialsImpl.kt (100%) rename packages/kotlin/src/{android => core}/src/test/java/alphaTab/core/TestGlobals.kt (100%) rename packages/kotlin/src/{android => core}/src/test/java/alphaTab/model/ComparisonHelpersPartialsImpl.kt (100%) rename packages/kotlin/src/{android => core}/src/test/java/alphaTab/visualTests/VisualTestHelperPartials.kt (100%) diff --git a/packages/kotlin/package.json b/packages/kotlin/package.json index 6ede79ff91..2c014a48d0 100644 --- a/packages/kotlin/package.json +++ b/packages/kotlin/package.json @@ -5,9 +5,9 @@ "private": true, "type": "module", "scripts": { - "clean": "rimraf src/android/src/main-generated && rimraf src/android/src/test-generated", + "clean": "rimraf src/core/src/main-generated && rimraf src/core/src/test-generated", "transpile": "tsx scripts/transpile.ts", - "build": "npm run transpile && node scripts/gradlew.mjs assembleRelease", - "test": "node scripts/gradlew.mjs testReleaseUnitTest --info" + "build": "npm run transpile && node scripts/gradlew.mjs assemble", + "test": "node scripts/gradlew.mjs :core:check --info" } } diff --git a/packages/kotlin/scripts/transpile.ts b/packages/kotlin/scripts/transpile.ts index 7b4963d8f1..92719bdc20 100644 --- a/packages/kotlin/scripts/transpile.ts +++ b/packages/kotlin/scripts/transpile.ts @@ -10,8 +10,8 @@ transpiler( { name: 'Kotlin', emit: createEmit( - path.resolve(__dirname, '../src/android/src/main-generated/java'), - path.resolve(__dirname, '../src/android/src/test-generated/java') + path.resolve(__dirname, '../src/core/src/main-generated/java'), + path.resolve(__dirname, '../src/core/src/test-generated/java') ) } ], diff --git a/packages/kotlin/src/android/build.gradle.kts b/packages/kotlin/src/android/build.gradle.kts index 57e70bb39a..9cec06b4ee 100644 --- a/packages/kotlin/src/android/build.gradle.kts +++ b/packages/kotlin/src/android/build.gradle.kts @@ -1,8 +1,6 @@ -import com.android.build.api.variant.HostTestBuilder import com.vanniktech.maven.publish.AndroidSingleVariantLibrary import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import java.io.FileInputStream -import java.util.Properties +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { // AGP 9+ has built-in Kotlin support; a separate kotlin-android plugin is no @@ -10,71 +8,15 @@ plugins { alias(libs.plugins.android.library) alias(libs.plugins.dokka) alias(libs.plugins.mavenPublish) - `maven-publish` - signing } - -val props = Properties() -val propsFile = project.rootProject.file("local.properties") -if (propsFile.exists()) { - FileInputStream(propsFile).use { - props.load(it) - } -} - -fun loadSetting(envKey: String, propKey: String, setter: (value: String) -> Unit) { - if (props.containsKey(propKey)) { - setter(props.getProperty(propKey)) - } else { - val env = providers - .environmentVariable(envKey) - if (env.isPresent) { - setter(env.get()) - } - } -} - -var libDescription = - "alphaTab is a cross platform music notation and guitar tablature rendering library. " + - "The \"alphaTab.net\" attribution in rendered scores must stay visible, " + - "see https://alphatab.net/docs/attribution" -var libAuthorId = "danielku15" -var libAuthorName = "Daniel Kuschny" -var libOrgUrl = "https://github.com/coderline" -var libCompany = "CoderLine" -var libVersion = "1.10.0-SNAPSHOT" -var libProjectUrl = "https://github.com/CoderLine/alphaTab" -var libGitUrlHttp = "https://github.com/CoderLine/alphaTab.git" -var libGitUrlGit = "scm:git:git://github.com/CoderLine/alphaTab.git" -var libLicenseSpdx = "MPL-2.0" -var libLicenseUrl = "https://opensource.org/licenses/MPL-2.0" -var libIssuesUrl = "https://github.com/CoderLine/alphaTab/issues" -val libGroup = "net.alphatab" -val libArtifactId = "alphaTab" - -loadSetting("ALPHATAB_DESCRIPTION", "alphatabDescription") { libDescription = it } -loadSetting("ALPHATAB_AUTHOR_ID", "alphatabAuthorId") { libAuthorId = it } -loadSetting("ALPHATAB_AUTHOR_NAME", "alphatabAuthorName") { libAuthorName = it } -loadSetting("ALPHATAB_ORG_URL", "alphatabOrgUrl") { libOrgUrl = it } -loadSetting("ALPHATAB_COMPANY", "alphatabCompany") { libCompany = it } -loadSetting("ALPHATAB_VERSION", "alphatabVersion") { libVersion = it } -loadSetting("ALPHATAB_PROJECT_URL", "alphatabProjectUrl") { libProjectUrl = it } -loadSetting("ALPHATAB_GIT_URL_HTTP", "alphatabGitUrlHttp") { libGitUrlHttp = it } -loadSetting("ALPHATAB_GIT_URL_GIT", "alphatabGitUrlGit") { libGitUrlGit = it } -loadSetting("ALPHATAB_LICENSE_SPDX", "alphatabLicenseSpdx") { libLicenseSpdx = it } -loadSetting("ALPHATAB_LICENSE_URL", "alphatabLicenseUrl") { libLicenseUrl = it } -loadSetting("ALPHATAB_ISSUES_URL", "alphatabIssuesUrl") { libIssuesUrl = it } - -group = libGroup -version = libVersion - val javaVersion = JavaVersion.VERSION_17; var jvmTargetVersion = JvmTarget.JVM_17 kotlin { compilerOptions { jvmTarget.set(jvmTargetVersion) + moduleName.set("alphaTab-android") freeCompilerArgs.addAll( listOf( "-Xno-call-assertions", @@ -85,15 +27,6 @@ kotlin { } } -// AGP 9 only generates unit-test tasks for the debug variant by default. Our -// pipeline runs tests against the release variant (matches published artifact), -// so enable the release host unit-test explicitly. -androidComponents { - beforeVariants(selector().withBuildType("release")) { variantBuilder -> - variantBuilder.hostTests[HostTestBuilder.UNIT_TEST_TYPE]?.enable = true - } -} - android { namespace = project.group.toString() compileSdk = 37 @@ -116,20 +49,13 @@ android { targetCompatibility = javaVersion } - sourceSets { getByName("main") { - java.srcDirs("src/main-generated/java") - kotlin.srcDirs("src/main-generated/java") assets.srcDirs( "../../../alphatab/font/bravura", "../../../alphatab/font/sonivox" ) } - getByName("test") { - java.srcDirs("src/test-generated/java") - kotlin.srcDirs("src/test-generated/java") - } } androidResources { @@ -147,41 +73,37 @@ android { } } +evaluationDependsOn(":core") +val core = project(":core") + +// The Android integration uses internal members of the core, like AlphaTab.Windows does in C# +// through InternalsVisibleTo. Both artifacts are therefore published and consumed in lockstep. +tasks.withType().configureEach { + friendPaths.from(core.tasks.named("jar")) +} + dependencies { + api(core) + constraints { + api("${core.group}:alphaTab-core") { + version { + strictly(core.version.toString()) + } + } + } + implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) - testImplementation(libs.junit) - androidTestImplementation(libs.androidx.junit) - androidTestImplementation(libs.androidx.espresso.core) - + implementation(libs.alphaskia) implementation(libs.alphaskia.android) implementation(libs.kotlinx.coroutines.core) - implementation(libs.alphaskia) - testImplementation(libs.alphaskia.macos) - testImplementation(libs.alphaskia.linux) - testImplementation(libs.alphaskia.windows) - testImplementation(libs.kotlinx.coroutines.test) - testImplementation(libs.klaxon) -} - -publishing { - repositories { - maven { - name = "DistPath" - url = rootProject.projectDir.resolve("dist").toURI() - } - } + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) } -internal fun Project.findOptionalProperty(propertyName: String) = - findProperty(propertyName)?.toString() - mavenPublishing { - publishToMavenCentral(automaticRelease = true) - coordinates(libGroup, libArtifactId, libVersion) - signAllPublications() - + coordinates(group.toString(), "alphaTab", version.toString()) configure( AndroidSingleVariantLibrary( variant = "release", @@ -189,43 +111,7 @@ mavenPublishing { publishJavadocJar = true ) ) - - val inMemoryKeyFile = project.findOptionalProperty("signingInMemoryKeyFile") - if (inMemoryKeyFile != null) { - val inMemoryKeyId = project.findOptionalProperty("signingInMemoryKeyId") - val inMemoryKeyPassword = - project.findOptionalProperty("signingInMemoryKeyPassword").orEmpty() - val signing = project.extensions.getByType(SigningExtension::class.java) - val inMemoryKey = File(inMemoryKeyFile).readText() - signing.useInMemoryPgpKeys(inMemoryKeyId, inMemoryKey, inMemoryKeyPassword) - } - pom { - name = libArtifactId - description = libDescription - url = libProjectUrl - licenses { - license { - name = libLicenseSpdx - url = libLicenseUrl - } - } - developers { - developer { - id = libAuthorId - name = libAuthorName - organization = libCompany - organizationUrl = libOrgUrl - } - } - scm { - url = libGitUrlHttp - connection = "scm:git:$libGitUrlGit" - developerConnection = "scm:git:$libGitUrlGit" - } - issueManagement { - system = "GitHub" - url = libIssuesUrl - } + name = "alphaTab" } } diff --git a/packages/kotlin/src/build.gradle.kts b/packages/kotlin/src/build.gradle.kts index d07a9a3e78..b7814637af 100644 --- a/packages/kotlin/src/build.gradle.kts +++ b/packages/kotlin/src/build.gradle.kts @@ -1,4 +1,121 @@ +import com.vanniktech.maven.publish.MavenPublishBaseExtension +import java.io.FileInputStream +import java.util.Properties + plugins { alias(libs.plugins.jetbrains.kotlin.android) apply false alias(libs.plugins.android.library) apply false + alias(libs.plugins.jetbrains.kotlin.jvm) apply false + alias(libs.plugins.dokka) apply false + alias(libs.plugins.mavenPublish) apply false + alias(libs.plugins.animalsniffer) apply false +} + +val props = Properties() +val propsFile = rootProject.file("local.properties") +if (propsFile.exists()) { + FileInputStream(propsFile).use { + props.load(it) + } +} + +fun loadSetting(envKey: String, propKey: String, setter: (value: String) -> Unit) { + if (props.containsKey(propKey)) { + setter(props.getProperty(propKey)) + } else { + val env = providers + .environmentVariable(envKey) + if (env.isPresent) { + setter(env.get()) + } + } +} + +var libDescription = + "alphaTab is a cross platform music notation and guitar tablature rendering library. " + + "The \"alphaTab.net\" attribution in rendered scores must stay visible, " + + "see https://alphatab.net/docs/attribution" +var libAuthorId = "danielku15" +var libAuthorName = "Daniel Kuschny" +var libOrgUrl = "https://github.com/coderline" +var libCompany = "CoderLine" +var libVersion = "1.10.0-SNAPSHOT" +var libProjectUrl = "https://github.com/CoderLine/alphaTab" +var libGitUrlHttp = "https://github.com/CoderLine/alphaTab.git" +var libGitUrlGit = "scm:git:git://github.com/CoderLine/alphaTab.git" +var libLicenseSpdx = "MPL-2.0" +var libLicenseUrl = "https://opensource.org/licenses/MPL-2.0" +var libIssuesUrl = "https://github.com/CoderLine/alphaTab/issues" +val libGroup = "net.alphatab" + +loadSetting("ALPHATAB_DESCRIPTION", "alphatabDescription") { libDescription = it } +loadSetting("ALPHATAB_AUTHOR_ID", "alphatabAuthorId") { libAuthorId = it } +loadSetting("ALPHATAB_AUTHOR_NAME", "alphatabAuthorName") { libAuthorName = it } +loadSetting("ALPHATAB_ORG_URL", "alphatabOrgUrl") { libOrgUrl = it } +loadSetting("ALPHATAB_COMPANY", "alphatabCompany") { libCompany = it } +loadSetting("ALPHATAB_VERSION", "alphatabVersion") { libVersion = it } +loadSetting("ALPHATAB_PROJECT_URL", "alphatabProjectUrl") { libProjectUrl = it } +loadSetting("ALPHATAB_GIT_URL_HTTP", "alphatabGitUrlHttp") { libGitUrlHttp = it } +loadSetting("ALPHATAB_GIT_URL_GIT", "alphatabGitUrlGit") { libGitUrlGit = it } +loadSetting("ALPHATAB_LICENSE_SPDX", "alphatabLicenseSpdx") { libLicenseSpdx = it } +loadSetting("ALPHATAB_LICENSE_URL", "alphatabLicenseUrl") { libLicenseUrl = it } +loadSetting("ALPHATAB_ISSUES_URL", "alphatabIssuesUrl") { libIssuesUrl = it } + +subprojects { + group = libGroup + version = libVersion + + plugins.withId("com.vanniktech.maven.publish") { + extensions.configure { + repositories { + maven { + name = "DistPath" + url = rootProject.projectDir.resolve("dist").toURI() + } + } + } + + extensions.configure { + publishToMavenCentral(automaticRelease = true) + signAllPublications() + + val inMemoryKeyFile = findProperty("signingInMemoryKeyFile")?.toString() + if (inMemoryKeyFile != null) { + val inMemoryKeyId = findProperty("signingInMemoryKeyId")?.toString() + val inMemoryKeyPassword = + findProperty("signingInMemoryKeyPassword")?.toString().orEmpty() + val signing = extensions.getByType(SigningExtension::class.java) + val inMemoryKey = File(inMemoryKeyFile).readText() + signing.useInMemoryPgpKeys(inMemoryKeyId, inMemoryKey, inMemoryKeyPassword) + } + + pom { + description = libDescription + url = libProjectUrl + licenses { + license { + name = libLicenseSpdx + url = libLicenseUrl + } + } + developers { + developer { + id = libAuthorId + name = libAuthorName + organization = libCompany + organizationUrl = libOrgUrl + } + } + scm { + url = libGitUrlHttp + connection = "scm:git:$libGitUrlGit" + developerConnection = "scm:git:$libGitUrlGit" + } + issueManagement { + system = "GitHub" + url = libIssuesUrl + } + } + } + } } diff --git a/packages/kotlin/src/core/build.gradle.kts b/packages/kotlin/src/core/build.gradle.kts new file mode 100644 index 0000000000..cad3a0f108 --- /dev/null +++ b/packages/kotlin/src/core/build.gradle.kts @@ -0,0 +1,80 @@ +import com.vanniktech.maven.publish.JavadocJar +import com.vanniktech.maven.publish.KotlinJvm +import com.vanniktech.maven.publish.SourcesJar +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.jetbrains.kotlin.jvm) + `java-library` + alias(libs.plugins.dokka) + alias(libs.plugins.mavenPublish) + alias(libs.plugins.animalsniffer) +} + +val javaVersion = JavaVersion.VERSION_17 + +java { + sourceCompatibility = javaVersion + targetCompatibility = javaVersion +} + +tasks.withType().configureEach { + options.release.set(17) +} + +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + moduleName.set("alphaTab-core") + freeCompilerArgs.addAll( + listOf( + // compile against the Java 17 class library, not the one of the JDK running Gradle + "-Xjdk-release=17", + "-Xno-call-assertions", + "-Xno-receiver-assertions", + "-Xno-param-assertions" + ) + ) + } +} + +sourceSets { + main { + kotlin.srcDirs("src/main-generated/java") + } + test { + kotlin.srcDirs("src/test-generated/java") + } +} + +dependencies { + implementation(libs.kotlinx.coroutines.core) + // JVM applications initialize the native alphaSkia library themselves (e.g. AlphaSkiaLinux) + api(libs.alphaskia) + + testImplementation(libs.junit) + testImplementation(libs.alphaskia.macos) + testImplementation(libs.alphaskia.linux) + testImplementation(libs.alphaskia.windows) + testImplementation(libs.kotlinx.coroutines.test) + testImplementation(libs.klaxon) + + // the core also runs on Android (minSdk of the alphaTab AAR) + signature(libs.gummybears.api26) { + artifact { + type = "signature" + } + } +} + +animalsniffer { + sourceSets = listOf(project.sourceSets.main.get()) +} + +mavenPublishing { + coordinates(group.toString(), "alphaTab-core", version.toString()) + configure(KotlinJvm(javadocJar = JavadocJar.Dokka("dokkaGeneratePublicationHtml"), sourcesJar = SourcesJar.Sources())) + pom { + name = "alphaTab-core" + } +} diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/EnvironmentPartials.kt b/packages/kotlin/src/core/src/main/java/alphaTab/EnvironmentPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/EnvironmentPartials.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/EnvironmentPartials.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/BooleanList.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/BooleanList.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/BooleanList.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/BooleanList.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleBooleanMap.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleBooleanMap.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleBooleanMap.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleBooleanMap.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleDoubleMap.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleDoubleMap.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleDoubleMap.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleDoubleMap.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleList.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleList.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleList.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleList.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleObjectMap.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleObjectMap.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/DoubleObjectMap.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/DoubleObjectMap.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/HashHelpers.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/HashHelpers.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/HashHelpers.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/HashHelpers.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/KeyNotFoundException.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/KeyNotFoundException.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/KeyNotFoundException.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/KeyNotFoundException.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/List.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/List.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/List.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/List.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/Map.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/Map.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/Map.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/Map.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/MapBase.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/MapBase.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/MapBase.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/MapBase.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/ObjectBooleanMap.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/ObjectBooleanMap.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/ObjectBooleanMap.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/ObjectBooleanMap.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/ObjectDoubleMap.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/ObjectDoubleMap.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/ObjectDoubleMap.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/ObjectDoubleMap.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/collections/SimpleIterable.kt b/packages/kotlin/src/core/src/main/java/alphaTab/collections/SimpleIterable.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/collections/SimpleIterable.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/collections/SimpleIterable.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ArrayTuple.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ArrayTuple.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ArrayTuple.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ArrayTuple.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/Console.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/Console.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/Console.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/Console.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/Globals.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/Globals.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/Globals.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/Globals.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/IAlphaTabEnum.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/IAlphaTabEnum.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/IAlphaTabEnum.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/IAlphaTabEnum.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/IRecord.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/IRecord.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/IRecord.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/IRecord.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/TypeHelper.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/TypeHelper.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/TypeHelper.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/TypeHelper.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/ArrayBuffer.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/ArrayBuffer.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/ArrayBuffer.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/ArrayBuffer.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/BigInt.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/BigInt.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/BigInt.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/BigInt.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/CoreString.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/CoreString.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/CoreString.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/CoreString.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/DataView.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/DataView.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/DataView.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/DataView.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Date.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Date.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Date.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Date.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Error.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Error.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Error.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Error.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Float32Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Float32Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Float32Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Float32Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Int16Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Int16Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Int16Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Int16Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Int32Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Int32Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Int32Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Int32Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Int8Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Int8Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Int8Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Int8Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/JSON.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/JSON.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/JSON.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/JSON.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Math.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Math.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Math.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Math.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/MessageEvent.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/MessageEvent.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/MessageEvent.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/MessageEvent.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Number.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Number.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Number.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Number.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Object.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Object.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Object.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Object.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Promise.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Promise.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Promise.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Promise.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/PromiseWithResolvers.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/PromiseWithResolvers.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/PromiseWithResolvers.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/PromiseWithResolvers.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Record.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Record.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Record.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Record.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/RegExp.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/RegExp.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/RegExp.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/RegExp.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Set.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Set.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Set.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Set.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/TextDecoder.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/TextDecoder.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/TextDecoder.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/TextDecoder.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/TextEncoder.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/TextEncoder.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/TextEncoder.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/TextEncoder.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Uint16Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Uint16Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Uint16Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Uint16Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Uint32Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Uint32Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Uint32Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Uint32Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Uint8Array.kt b/packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Uint8Array.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/core/ecmaScript/Uint8Array.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/core/ecmaScript/Uint8Array.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/importer/alphaTex/AlphaTex1EnumMappingsPartials.kt b/packages/kotlin/src/core/src/main/java/alphaTab/importer/alphaTex/AlphaTex1EnumMappingsPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/importer/alphaTex/AlphaTex1EnumMappingsPartials.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/importer/alphaTex/AlphaTex1EnumMappingsPartials.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/importer/alphaTex/SimpleAlphaTexParameterDefinition.kt b/packages/kotlin/src/core/src/main/java/alphaTab/importer/alphaTex/SimpleAlphaTexParameterDefinition.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/importer/alphaTex/SimpleAlphaTexParameterDefinition.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/importer/alphaTex/SimpleAlphaTexParameterDefinition.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/io/JsonHelperPartials.kt b/packages/kotlin/src/core/src/main/java/alphaTab/io/JsonHelperPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/io/JsonHelperPartials.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/io/JsonHelperPartials.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/io/TypeConversions.kt b/packages/kotlin/src/core/src/main/java/alphaTab/io/TypeConversions.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/io/TypeConversions.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/io/TypeConversions.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/jvm/JavaThreadWorkers.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaCanvas.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaCanvas.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaCanvas.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaCanvas.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaImage.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaImage.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaImage.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaImage.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextAlign.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextAlign.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextAlign.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextAlign.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextBaseline.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextBaseline.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextBaseline.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextBaseline.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextMetrics.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextMetrics.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextMetrics.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextMetrics.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextStyle.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextStyle.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTextStyle.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTextStyle.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTypeface.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTypeface.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/AlphaSkiaTypeface.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/AlphaSkiaTypeface.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/SkiaCanvasPartials.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/SkiaCanvasPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/skia/SkiaCanvasPartials.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/skia/SkiaCanvasPartials.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/svg/FontSizesPartials.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/svg/FontSizesPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/svg/FontSizesPartials.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/svg/FontSizesPartials.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/platform/svg/SvgBuffer.kt b/packages/kotlin/src/core/src/main/java/alphaTab/platform/svg/SvgBuffer.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/platform/svg/SvgBuffer.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/platform/svg/SvgBuffer.kt diff --git a/packages/kotlin/src/android/src/main/java/alphaTab/util/Lazy.kt b/packages/kotlin/src/core/src/main/java/alphaTab/util/Lazy.kt similarity index 100% rename from packages/kotlin/src/android/src/main/java/alphaTab/util/Lazy.kt rename to packages/kotlin/src/core/src/main/java/alphaTab/util/Lazy.kt diff --git a/packages/kotlin/src/android/src/test/java/alphaTab/PrettyFormatPartials.kt b/packages/kotlin/src/core/src/test/java/alphaTab/PrettyFormatPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/test/java/alphaTab/PrettyFormatPartials.kt rename to packages/kotlin/src/core/src/test/java/alphaTab/PrettyFormatPartials.kt diff --git a/packages/kotlin/src/android/src/test/java/alphaTab/ScoreSerializerPluginPartials.kt b/packages/kotlin/src/core/src/test/java/alphaTab/ScoreSerializerPluginPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/test/java/alphaTab/ScoreSerializerPluginPartials.kt rename to packages/kotlin/src/core/src/test/java/alphaTab/ScoreSerializerPluginPartials.kt diff --git a/packages/kotlin/src/android/src/test/java/alphaTab/TestPlatformPartialsImpl.kt b/packages/kotlin/src/core/src/test/java/alphaTab/TestPlatformPartialsImpl.kt similarity index 100% rename from packages/kotlin/src/android/src/test/java/alphaTab/TestPlatformPartialsImpl.kt rename to packages/kotlin/src/core/src/test/java/alphaTab/TestPlatformPartialsImpl.kt diff --git a/packages/kotlin/src/android/src/test/java/alphaTab/core/TestGlobals.kt b/packages/kotlin/src/core/src/test/java/alphaTab/core/TestGlobals.kt similarity index 100% rename from packages/kotlin/src/android/src/test/java/alphaTab/core/TestGlobals.kt rename to packages/kotlin/src/core/src/test/java/alphaTab/core/TestGlobals.kt diff --git a/packages/kotlin/src/android/src/test/java/alphaTab/model/ComparisonHelpersPartialsImpl.kt b/packages/kotlin/src/core/src/test/java/alphaTab/model/ComparisonHelpersPartialsImpl.kt similarity index 100% rename from packages/kotlin/src/android/src/test/java/alphaTab/model/ComparisonHelpersPartialsImpl.kt rename to packages/kotlin/src/core/src/test/java/alphaTab/model/ComparisonHelpersPartialsImpl.kt diff --git a/packages/kotlin/src/android/src/test/java/alphaTab/visualTests/VisualTestHelperPartials.kt b/packages/kotlin/src/core/src/test/java/alphaTab/visualTests/VisualTestHelperPartials.kt similarity index 100% rename from packages/kotlin/src/android/src/test/java/alphaTab/visualTests/VisualTestHelperPartials.kt rename to packages/kotlin/src/core/src/test/java/alphaTab/visualTests/VisualTestHelperPartials.kt diff --git a/packages/kotlin/src/gradle/libs.versions.toml b/packages/kotlin/src/gradle/libs.versions.toml index 1f10aaab61..95fd1ca016 100644 --- a/packages/kotlin/src/gradle/libs.versions.toml +++ b/packages/kotlin/src/gradle/libs.versions.toml @@ -14,6 +14,8 @@ junitVersion = "1.3.0" alphaskia = "3.5.147" mavenPublish = "0.37.0" klaxon = "5.6" +animalsniffer = "2.0.1" +gummybears = "0.16.0" [libraries] @@ -33,8 +35,12 @@ alphaskia-linux = { group = "net.alphatab", name="alphaSkia-linux", version.ref alphaskia-macos = { group = "net.alphatab", name="alphaSkia-macos", version.ref = "alphaskia" } alphaskia-android = { group = "net.alphatab", name="alphaSkia-android", version.ref = "alphaskia" } +gummybears-api26 = { group = "com.toasttab.android", name="gummy-bears-api-26", version.ref = "gummybears" } + [plugins] android-library = { id = "com.android.library", version.ref = "agp" } jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } mavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "mavenPublish" } +animalsniffer = { id = "ru.vyarus.animalsniffer", version.ref = "animalsniffer" } diff --git a/packages/kotlin/src/settings.gradle.kts b/packages/kotlin/src/settings.gradle.kts index 9290b274b1..0df7a091ab 100644 --- a/packages/kotlin/src/settings.gradle.kts +++ b/packages/kotlin/src/settings.gradle.kts @@ -20,4 +20,5 @@ dependencyResolutionManagement { } rootProject.name = "alphaTab" +include(":core") include(":android") diff --git a/scripts/update-version.mjs b/scripts/update-version.mjs index 35068566bc..17d77b32ac 100644 --- a/scripts/update-version.mjs +++ b/scripts/update-version.mjs @@ -95,6 +95,6 @@ for (const entry of fs.readdirSync(path.resolve(__dirname, '../packages/'), { wi } updateCSharpVersion(path.resolve(__dirname, '../packages/csharp/src/Directory.Build.props')); -updateKotlinVersion(path.resolve(__dirname, '../packages/kotlin/src/android/build.gradle.kts')); +updateKotlinVersion(path.resolve(__dirname, '../packages/kotlin/src/build.gradle.kts')); console.log('Done updating versions.'); From a301aa9e3e6596c281cde6c5fda7e20244b3bf72 Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Sun, 8 Nov 2026 00:52:09 +0100 Subject: [PATCH 3/5] docs: document the Kotlin packages for the JVM and Android The Kotlin target now ships alphaTab-core for any JVM next to the Android library (#2458). The website follows the new split: - New page "Platforms and packages" lists every package per ecosystem with runtime, UI control, render engines and audio output. - "Getting Started (Android)" becomes "Getting Started (Kotlin)": installation-android is now installation-kotlin with both packages, a verified JVM rendering sample and the Android setup; the old address redirects. The Android configuration page stays. - The low-level API guide gets Kotlin examples next to JavaScript and C#. - Where "Android" stood for the Kotlin API in general it now reads "Kotlin": reference example tabs and name badges (JSDoc @example titles), Skia/SVG/font pages, feature catalog intros, introduction, landing texts and llms.txt. Pages about AlphaTabView, AudioTrack and the UI-bound api object keep "Android". - Release notes for 1.10 and the contributing guide describe the new packages and Gradle modules. --- packages/alphatab/src/AlphaTabApiBase.ts | 138 +++++------ packages/alphatab/src/DisplaySettings.ts | 2 +- packages/alphatab/src/LogLevel.ts | 2 +- packages/alphatab/src/NotationSettings.ts | 2 +- .../src/generated/DisplaySettingsJson.ts | 2 +- .../src/generated/NotationSettingsJson.ts | 2 +- website/docs/attribution.mdx | 2 +- website/docs/contributing.mdx | 12 +- website/docs/features/export/export-midi.mdx | 2 +- .../export/export-to-guitar-pro-7.mdx | 2 +- website/docs/features/export/index.mdx | 2 +- .../features/extend/alphatabview-android.mdx | 2 +- .../docs/features/extend/custom-ui-facade.mdx | 2 +- website/docs/features/extend/index.mdx | 2 +- website/docs/features/import-load/index.mdx | 2 +- .../features/import-load/load-from-url.mdx | 2 +- website/docs/features/index.mdx | 4 +- .../docs/features/render/bravura-default.mdx | 2 +- .../features/render/choosing-a-backend.mdx | 8 +- .../features/render/custom-fonts-on-skia.mdx | 11 +- .../features/render/custom-smufl-fonts.mdx | 4 +- .../features/render/custom-text-fonts.mdx | 2 +- .../features/render/font-family-fallbacks.mdx | 4 +- website/docs/features/render/html5-canvas.mdx | 6 +- website/docs/features/render/index.mdx | 2 +- .../render/nodejs-headless-rendering.mdx | 2 +- website/docs/features/render/skia-backend.mdx | 10 +- website/docs/features/render/svg-output.mdx | 6 +- .../getting-started/configuration-android.mdx | 4 +- .../getting-started/installation-android.mdx | 153 ------------ .../getting-started/installation-kotlin.mdx | 222 ++++++++++++++++++ website/docs/guides/lowlevel-apis.mdx | 106 ++++++++- website/docs/introduction.mdx | 15 +- website/docs/platforms.mdx | 54 +++++ website/docs/releases/release1_10.mdx | 12 + website/docs/style-guide.md | 2 +- website/docusaurus.config.mts | 3 +- website/sidebars.ts | 5 +- website/src/components/CodeBadge/index.tsx | 6 +- .../components/CodeBadge/styles.module.scss | 4 +- website/src/components/FeatureCard/index.tsx | 3 +- .../components/FeatureChapterGrid/index.tsx | 4 +- .../src/components/HomepageFeatures/index.tsx | 2 +- .../src/components/PlatformBadges/index.tsx | 5 +- .../components/PropertyDescription/index.tsx | 2 +- .../landing/LandingFeatures/index.tsx | 2 +- .../components/landing/LandingHero/index.tsx | 2 +- website/static/llms.txt | 13 +- 48 files changed, 548 insertions(+), 310 deletions(-) delete mode 100644 website/docs/getting-started/installation-android.mdx create mode 100644 website/docs/getting-started/installation-kotlin.mdx create mode 100644 website/docs/platforms.mdx diff --git a/packages/alphatab/src/AlphaTabApiBase.ts b/packages/alphatab/src/AlphaTabApiBase.ts index 2a2515a155..03e5f2a469 100644 --- a/packages/alphatab/src/AlphaTabApiBase.ts +++ b/packages/alphatab/src/AlphaTabApiBase.ts @@ -225,7 +225,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * val container = api.container; @@ -265,7 +265,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * updateScoreInfo(api.score) @@ -297,7 +297,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * showSettingsDialog(api.settings) @@ -325,7 +325,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * highlightCurrentTracksInTrackSelector(api.tracks) @@ -498,7 +498,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.destroy() @@ -552,7 +552,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * @@ -626,7 +626,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * contentResolver.openInputStream(uri).use { @@ -675,7 +675,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.renderScore(generateScore(), alphaTab.collections.DoubleList(2, 3)); @@ -732,7 +732,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.renderTracks(alphaTab.collections.List( @@ -873,7 +873,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.tex("\\title 'Test' . 3.3.4"); @@ -921,7 +921,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * contentResolver.openInputStream(uri).use { @@ -965,7 +965,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.loadSoundFont(readResource("guitars.sf2"), true) @@ -1002,7 +1002,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.render() @@ -1066,7 +1066,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.customCursorHandler = CustomCursorHandler(); @@ -1131,7 +1131,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.customScrollHandler = CustomScrollHandler(); @@ -1167,7 +1167,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * val lookupResult = api.tickCache.findBeat(alphaTab.core.ecmaScript.Set(0, 1), 100); @@ -1234,7 +1234,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * setupPlayerEvents(api.player) @@ -1266,7 +1266,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * if (api.isReadyForPlayback) api.play() @@ -1297,7 +1297,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * if (api.playerState != PlayerState.Playing) api.play() @@ -1328,7 +1328,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.masterVolume = 0.5 @@ -1364,7 +1364,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.metronomeVolume = 0.5 @@ -1400,7 +1400,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.countInVolume = 0.5 @@ -1457,7 +1457,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...); * api.midiEventsPlayedFilter = alphaTab.collections.List( alphaTab.midi.MidiEventType.AlphaTabMetronome ) @@ -1497,7 +1497,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.tickPosition = 4000 @@ -1530,7 +1530,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.timePosition = 4000 @@ -1584,7 +1584,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playbackRange = PlaybackRange.apply { @@ -1627,7 +1627,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playbackSpeed = 0.5 @@ -1663,7 +1663,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.isLooping = true @@ -1820,7 +1820,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...); * api.changeTrackVolume(alphaTab.collections.List(api.score.tracks[0], api.score.tracks[1]), 1.5); @@ -1861,7 +1861,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.changeTrackSolo(alphaTab.collections.List(api.score.tracks[0], api.score.tracks[1]), true); @@ -1900,7 +1900,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.changeTrackMute(alphaTab.collections.List(api.score.tracks[0], api.score.tracks[1]), true); @@ -1940,7 +1940,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...); * api.changeTrackTranspositionPitch(alphaTab.collections.List(api.score.tracks[0], api.score.tracks[1]), 3); @@ -1975,7 +1975,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.play() @@ -2005,7 +2005,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.pause(); @@ -2037,7 +2037,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playPause() @@ -2069,7 +2069,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.stop() @@ -2106,7 +2106,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playBeat(api.score.tracks[0].staves[0].bars[0].voices[0].beats[0]) @@ -2152,7 +2152,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playNote(api.score.tracks[0].staves[0].bars[0].voices[0].beats[0].notes[0]); @@ -2565,7 +2565,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playedBeatChanged.on { beat -> @@ -2613,7 +2613,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.activeBeatsChanged.on { args -> @@ -2663,7 +2663,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.beatMouseDown.on { beat -> @@ -2699,7 +2699,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.beatMouseMove.on { beat -> @@ -2739,7 +2739,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.beatMouseUp.on { beat -> @@ -2780,7 +2780,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.noteMouseDown.on { note -> @@ -2822,7 +2822,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.noteMouseMove.on { note -> @@ -2866,7 +2866,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.noteMouseUp.on { note -> @@ -3126,7 +3126,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * val startBeat = api.score.tracks[0].staves[0].bars[0].voices[0].beats[0] @@ -3172,7 +3172,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * val startBeat = api.score.tracks[0].staves[0].bars[0].voices[0].beats[0] @@ -3271,7 +3271,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.clearPlaybackRangeHighlight() @@ -3312,7 +3312,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playbackRangeHighlightChanged.on { e -> @@ -3491,7 +3491,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.scoreLoaded.on { score -> @@ -3573,7 +3573,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.resize.on { args -> @@ -3622,7 +3622,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.renderStarted.on { resized -> @@ -3670,7 +3670,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.renderFinished.on { @@ -3722,7 +3722,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.postRenderFinished.on { @@ -3779,7 +3779,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.error.on { error -> @@ -3831,7 +3831,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playerReady.on { @@ -3887,7 +3887,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playerFinished.on { @@ -3937,7 +3937,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...); * api.soundFontLoaded.on { @@ -3993,7 +3993,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.midiLoad.on { file -> @@ -4040,7 +4040,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.midiLoaded.on { e -> @@ -4086,7 +4086,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playerStateChanged.on { args -> @@ -4143,7 +4143,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playerPositionChanged.on { args -> @@ -4217,7 +4217,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...); * api.midiEventsPlayedFilter = alphaTab.collections.List( alphaTab.midi.MidiEventType.AlphaTabMetronome ) @@ -4297,7 +4297,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.playbackRangeChanged.on { args -> @@ -4348,7 +4348,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * val api = AlphaTabApi(...) * api.SettingsUpdated.on { @@ -4403,7 +4403,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * fun init() = kotlinx.coroutines.runBlocking { * val api = AlphaTabApi(...) @@ -4455,7 +4455,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * fun init() = kotlinx.coroutines.runBlocking { * val api = AlphaTabApi(...) @@ -4501,7 +4501,7 @@ export class AlphaTabApiBase { * ``` * * @example - * Android + * Kotlin * ```kotlin * fun init() = kotlinx.coroutines.runBlocking { * val api = AlphaTabApi(...) diff --git a/packages/alphatab/src/DisplaySettings.ts b/packages/alphatab/src/DisplaySettings.ts index 82af6e339d..317bb240e2 100644 --- a/packages/alphatab/src/DisplaySettings.ts +++ b/packages/alphatab/src/DisplaySettings.ts @@ -236,7 +236,7 @@ export class DisplaySettings { * | JSON | `display.resources.` | `var settings = { display: { resources: { wordsFonts: '...'} } };` | * | JSON | `resources.` | `var settings = { resources: { wordsFonts: '...'} };` | * | .net | `Display.Resources.` | `settings.Display.Resources.WordsFonts = ...` | - * | Android | `display.resources.` | `settings.display.resources.wordsFonts = ...` | + * | Kotlin | `display.resources.` | `settings.display.resources.wordsFonts = ...` | * ## Types * * ### Fonts diff --git a/packages/alphatab/src/LogLevel.ts b/packages/alphatab/src/LogLevel.ts index d9e8edd150..d83f39581f 100644 --- a/packages/alphatab/src/LogLevel.ts +++ b/packages/alphatab/src/LogLevel.ts @@ -9,7 +9,7 @@ export enum LogLevel { * Trace level (high-volume internal flow details, implies all other levels). * @remarks * The published JavaScript files do not contain trace messages; they are only written when running alphaTab - * from its TypeScript sources and on .NET and Android. + * from its TypeScript sources and on .NET and Kotlin. * @since 1.9.0 */ Trace = -1, diff --git a/packages/alphatab/src/NotationSettings.ts b/packages/alphatab/src/NotationSettings.ts index 848d8a81ad..03124efde1 100644 --- a/packages/alphatab/src/NotationSettings.ts +++ b/packages/alphatab/src/NotationSettings.ts @@ -487,7 +487,7 @@ export class NotationSettings { * settings.Notation.Elements[AlphaTab.NotationElement.TrackNames] = false; * ``` * @example - * Android + * Kotlin * ```kotlin * val settings = AlphaTab.Settings(); * settings.notation.elements[alphaTab.NotationElement.ScoreTitle] = false; diff --git a/packages/alphatab/src/generated/DisplaySettingsJson.ts b/packages/alphatab/src/generated/DisplaySettingsJson.ts index 4d7682f2b8..a7c7a60232 100644 --- a/packages/alphatab/src/generated/DisplaySettingsJson.ts +++ b/packages/alphatab/src/generated/DisplaySettingsJson.ts @@ -209,7 +209,7 @@ export interface DisplaySettingsJson { * | JSON | `display.resources.` | `var settings = { display: { resources: { wordsFonts: '...'} } };` | * | JSON | `resources.` | `var settings = { resources: { wordsFonts: '...'} };` | * | .net | `Display.Resources.` | `settings.Display.Resources.WordsFonts = ...` | - * | Android | `display.resources.` | `settings.display.resources.wordsFonts = ...` | + * | Kotlin | `display.resources.` | `settings.display.resources.wordsFonts = ...` | * ## Types * * ### Fonts diff --git a/packages/alphatab/src/generated/NotationSettingsJson.ts b/packages/alphatab/src/generated/NotationSettingsJson.ts index 6bf98f230e..ea775a073c 100644 --- a/packages/alphatab/src/generated/NotationSettingsJson.ts +++ b/packages/alphatab/src/generated/NotationSettingsJson.ts @@ -108,7 +108,7 @@ export interface NotationSettingsJson { * settings.Notation.Elements[AlphaTab.NotationElement.TrackNames] = false; * ``` * @example - * Android + * Kotlin * ```kotlin * val settings = AlphaTab.Settings(); * settings.notation.elements[alphaTab.NotationElement.ScoreTitle] = false; diff --git a/website/docs/attribution.mdx b/website/docs/attribution.mdx index c90a438824..3111fd3364 100644 --- a/website/docs/attribution.mdx +++ b/website/docs/attribution.mdx @@ -52,7 +52,7 @@ A song with 12 bars shows the attribution at the end of the first system: - **Style:** drawn in the [staff line color](/docs/reference/types/renderingresources/#stafflinecolor), so it follows your theme and dark mode. It scales with [`display.scale`](/docs/reference/settings/display/scale). - **Space:** it uses room the score already has, and adds no extra line. - **Small scores:** songs with up to 10 bars render without it, unless more than 2 tracks are shown. Exercises, lesson snippets and previews stay clean. -- **Everywhere:** the same on web, .NET and Android, on screen, in print and in rendered images. +- **Everywhere:** the same on web, .NET, the JVM and Android, on screen, in print and in rendered images. A song with 4 bars renders without it: diff --git a/website/docs/contributing.mdx b/website/docs/contributing.mdx index 158feda87a..1d2dce9807 100644 --- a/website/docs/contributing.mdx +++ b/website/docs/contributing.mdx @@ -44,7 +44,7 @@ alphaTab lives in one monorepo — [github.com/CoderLine/alphaTab](https://githu - `alphatab` — the main library and the source of truth for all platforms - `alphatex` — the alphaTex text-format parser and tools - `csharp` — the .NET build, transpiled from the TypeScript source -- `kotlin` — the Kotlin/Android build, transpiled from the TypeScript source +- `kotlin` — the Kotlin build, transpiled from the TypeScript source: the Gradle module `core` (the platform-independent JVM library and all tests) and `android` (the Android integration) - `transpiler` — the TypeScript-to-C#-and-Kotlin transpiler both platforms consume - `vite`, `webpack` — the bundler plugins - `monaco`, `lsp` — the Monaco editor integration and alphaTex language server @@ -81,7 +81,7 @@ You will need: - [Node.js](https://nodejs.org/) 20 or newer — for TypeScript builds, tests, and workspace management - [.NET SDK](https://dotnet.microsoft.com/download) 8.0 or newer — only if you plan to build or test the C# port -- [Java 17+](https://adoptium.net/) and the [Android SDK](https://developer.android.com/studio) — only if you plan to build or test the Kotlin/Android port +- [Java 17+](https://adoptium.net/) and the [Android SDK](https://developer.android.com/studio) — only if you plan to build or test the Kotlin port Any modern web-focused IDE works. Visual Studio Code is a good default — the repository ships editor settings and recommended extensions it picks up automatically. @@ -126,11 +126,11 @@ npm run build-csharp # transpile TypeScript to C#, then run dotnet build npm run test-csharp # run the .NET unit tests via dotnet test ``` -**Kotlin for Android** +**Kotlin** ```bash -npm run build-kotlin # transpile TypeScript to Kotlin, then run gradle assembleRelease -npm run test-kotlin # run the Android instrumentation tests +npm run build-kotlin # transpile TypeScript to Kotlin, then build the core JAR and the Android AAR with gradle +npm run test-kotlin # run the unit tests and the Android API check of the core on the JVM ``` **Bundler plugins in isolation** @@ -148,7 +148,7 @@ TypeScript is the source of truth. All alphaTab development happens in the [`pac alphaTab toolchain: TypeScript source, cross-compiled to JavaScript, C#, and Kotlin -alphaTab targets zero runtime dependencies. The core modules are written to run on any platform with a garbage collector — JavaScript, .NET, or Kotlin for Android — without pulling in third-party libraries. Contributions to the core need to keep this constraint in mind: no new runtime dependencies without an architectural discussion first. +alphaTab targets zero runtime dependencies. The core modules are written to run on any platform with a garbage collector — JavaScript, .NET, or Kotlin — without pulling in third-party libraries. Contributions to the core need to keep this constraint in mind: no new runtime dependencies without an architectural discussion first. ### Code style diff --git a/website/docs/features/export/export-midi.mdx b/website/docs/features/export/export-midi.mdx index 18c485249f..033c62381f 100644 --- a/website/docs/features/export/export-midi.mdx +++ b/website/docs/features/export/export-midi.mdx @@ -40,7 +40,7 @@ The download uses `.mid` as the filename, falling back to `File.mid ## Programmatic pipeline -For server-side rendering, .NET, Android, or any flow where you want the bytes without a download, build the pipeline yourself: +For server-side rendering, .NET, Kotlin, or any flow where you want the bytes without a download, build the pipeline yourself: ```js import * as alphaTab from '@coderline/alphatab'; diff --git a/website/docs/features/export/export-to-guitar-pro-7.mdx b/website/docs/features/export/export-to-guitar-pro-7.mdx index c3c9977fb7..9bf07c732d 100644 --- a/website/docs/features/export/export-to-guitar-pro-7.mdx +++ b/website/docs/features/export/export-to-guitar-pro-7.mdx @@ -50,7 +50,7 @@ api.scoreLoaded.on(() => { }); ``` -`getAlphaTabContainer()` is the platform-specific step — a `
` on Web, an `AlphaTab` control on .NET, an `AlphaTabView` on Android. The exporter itself runs on every runtime; only the download link is browser-specific. On .NET or Android, write the byte array to disk with the native file API instead. +`getAlphaTabContainer()` is the platform-specific step — a `
` on Web, an `AlphaTab` control on .NET, an `AlphaTabView` on Android. The exporter itself runs on every runtime; only the download link is browser-specific. On .NET or Kotlin, write the byte array to disk with the native file API instead. ## What the exporter emits diff --git a/website/docs/features/export/index.mdx b/website/docs/features/export/index.mdx index 147e209d31..06db9d3885 100644 --- a/website/docs/features/export/index.mdx +++ b/website/docs/features/export/index.mdx @@ -15,7 +15,7 @@ import chapters from './_chapters'; alphaTab is a two-way street. A score that came in as MusicXML can leave as a `.gp` your users open in Guitar Pro. Edits made in your app can go back to a database as JSON. The same synth that drives live playback can bake a study track to WAV. Everything on this page is a stable outbound path — pick the format that fits what you want to hand a user, a DAW, or a server. -Every capability below is available on Web, .NET, and Android unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. +Every capability below is available on Web, .NET, and Kotlin unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. {chapters.map((chapter) => (
diff --git a/website/docs/features/extend/alphatabview-android.mdx b/website/docs/features/extend/alphatabview-android.mdx index d70567864a..90464c9e41 100644 --- a/website/docs/features/extend/alphatabview-android.mdx +++ b/website/docs/features/extend/alphatabview-android.mdx @@ -88,7 +88,7 @@ fun AlphaTabScore(onReady: (alphaTab.AlphaTabView) -> Unit) { ## Where to look next -- [Installation (Android)](/docs/getting-started/installation-android) — Gradle setup, Maven coordinates, and the first-render walkthrough. +- [Installation (Kotlin)](/docs/getting-started/installation-kotlin#render-on-android) — Gradle setup, Maven coordinates, and the first-render walkthrough. - [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia) — how to register titles, lyrics, and fingering fonts on the Android Skia backend. - [WPF and WinForms controls](/docs/features/extend/wpf-and-winforms-controls) — the sibling native hosts on .NET. - [Custom UI facade](/docs/features/extend/custom-ui-facade) — if you need alphaTab in a UI framework it has no shipped control for. diff --git a/website/docs/features/extend/custom-ui-facade.mdx b/website/docs/features/extend/custom-ui-facade.mdx index 4464968820..0b617977d1 100644 --- a/website/docs/features/extend/custom-ui-facade.mdx +++ b/website/docs/features/extend/custom-ui-facade.mdx @@ -16,7 +16,7 @@ import { AlphaTab } from '@site/src/components/AlphaTab'; import * as Riffs from '@site/src/tex-riffs'; -Hosting alphaTab in a UI framework it does not know about — WinUI, MAUI, Avalonia, a mobile framework, a game engine, a custom canvas layer — means implementing `IUiFacade`, the contract alphaTab uses to talk to its host. Every shipped platform already provides one: `BrowserUiFacade` on the web, WPF and WinForms facades on .NET, `AndroidUiFacade` on Android. Ship your own facade to reach anywhere else. +Hosting alphaTab in a UI framework it does not know about — WinUI, MAUI, Avalonia, Swing or JavaFX on the JVM, a mobile framework, a game engine, a custom canvas layer — means implementing `IUiFacade`, the contract alphaTab uses to talk to its host. Every shipped platform already provides one: `BrowserUiFacade` on the web, WPF and WinForms facades on .NET, `AndroidUiFacade` on Android. Ship your own facade to reach anywhere else. {Riffs.AM_VERSE_CHORUS} diff --git a/website/docs/features/extend/index.mdx b/website/docs/features/extend/index.mdx index 4927656290..43894100d2 100644 --- a/website/docs/features/extend/index.mdx +++ b/website/docs/features/extend/index.mdx @@ -15,7 +15,7 @@ import chapters from './_chapters'; alphaTab is designed to be embedded. When the shipped defaults are not enough, you can build scores in code, walk and mutate the loaded model, wire the worker and worklet into your own bundler, or host the engine in a native UI framework it does not already know about. -Every capability below is available on Web, .NET, and Android unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. +Every capability below is available on Web, .NET, and Kotlin unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. {chapters.map((chapter) => (
diff --git a/website/docs/features/import-load/index.mdx b/website/docs/features/import-load/index.mdx index 1d9271136c..dbcee3f518 100644 --- a/website/docs/features/import-load/index.mdx +++ b/website/docs/features/import-load/index.mdx @@ -16,7 +16,7 @@ import chapters from './_chapters'; Every alphaTab session starts by turning a source file into an in-memory `Score`. The importer pipeline reads Guitar Pro (GP3 through GP8), MusicXML, Capella, and alphaTab's own alphaTex text format, then hands the parsed model to the render engine. This group covers every way to feed alphaTab a score, every format it accepts, the importer settings that adjust how it decodes them, and the load-lifecycle events you hook once the score arrives. -Every capability below is available on Web, .NET, and Android unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. +Every capability below is available on Web, .NET, and Kotlin unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. {chapters.map((chapter) => (
diff --git a/website/docs/features/import-load/load-from-url.mdx b/website/docs/features/import-load/load-from-url.mdx index 4661b73f41..18cbb4714d 100644 --- a/website/docs/features/import-load/load-from-url.mdx +++ b/website/docs/features/import-load/load-from-url.mdx @@ -29,7 +29,7 @@ Both paths run the same fetch pipeline internally and fire `scoreLoaded` on comp ## Browser fetch, not universal -URL loading uses the browser `XMLHttpRequest`. It works in every Web target and follows the page's origin and CORS rules. On Node.js, .NET, and Android the URL path is not wired up — read the bytes yourself and pass them through `api.load(bytes)` instead. The `readScoreFile()` placeholder in the [bytes page](load-from-bytes) covers that pattern. +URL loading uses the browser `XMLHttpRequest`. It works in every Web target and follows the page's origin and CORS rules. On Node.js, .NET, and Kotlin the URL path is not wired up — read the bytes yourself and pass them through `api.load(bytes)` instead. The `readScoreFile()` placeholder in the [bytes page](load-from-bytes) covers that pattern. ## Show it in code diff --git a/website/docs/features/index.mdx b/website/docs/features/index.mdx index 22d385fed8..850de41188 100644 --- a/website/docs/features/index.mdx +++ b/website/docs/features/index.mdx @@ -14,9 +14,9 @@ import { IconNotation, IconPointer } from '@site/src/components/FeatureCard/icon alphaTab is a music-notation SDK that reads Guitar Pro, MusicXML, CapXML, and alphaTex files and produces engraved sheet music with playback. This section catalogs what alphaTab does, grouped by capability. Each entry links into the [API reference](/docs/reference/api/) or a deeper guide for the exact signatures. -## Portable across Web, .NET, and Android {#portable} +## Portable across Web, .NET, and Kotlin {#portable} -alphaTab compiles a single TypeScript core to JavaScript, C#, and Kotlin. API surface, class names, setting names, and event names are identical on every runtime. Code samples on these pages are written in JavaScript; every property and method has the same name on .NET and Android. Platform-specific setup — loading a file, obtaining a container, downloading a byte array — is shown as a placeholder helper like `getAlphaTabContainer()` or `readScoreFile()` that you replace with the natural equivalent for your platform. +alphaTab compiles a single TypeScript core to JavaScript, C#, and Kotlin. API surface, class names, setting names, and event names are identical on every runtime. Code samples on these pages are written in JavaScript; every property and method has the same name on .NET and Kotlin. Platform-specific setup — loading a file, obtaining a container, downloading a byte array — is shown as a placeholder helper like `getAlphaTabContainer()` or `readScoreFile()` that you replace with the natural equivalent for your platform. Where a capability genuinely differs across platforms, the card names the affected platforms with a small pill. diff --git a/website/docs/features/render/bravura-default.mdx b/website/docs/features/render/bravura-default.mdx index 11da14b880..ff87a0eed6 100644 --- a/website/docs/features/render/bravura-default.mdx +++ b/website/docs/features/render/bravura-default.mdx @@ -52,7 +52,7 @@ Override `core.fontDirectory` if your bundler places the font files somewhere el ## Where to look next - [Using a custom music font](/docs/features/render/custom-smufl-fonts) — swap Bravura for another SMuFL font. -- [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia) — the .NET / Android equivalent of the `@font-face` step. +- [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia) — the .NET / Kotlin equivalent of the `@font-face` step. - [`core.fontDirectory`](/docs/reference/settings/core/fontdirectory) and [`core.smuflFontSources`](/docs/reference/settings/core/smuflfontsources) reference entries. - [Bravura on GitHub](https://github.com/steinbergmedia/bravura) — the source font and license. - [SMuFL specification](https://www.smufl.org/) — the standard alphaTab implements. diff --git a/website/docs/features/render/choosing-a-backend.mdx b/website/docs/features/render/choosing-a-backend.mdx index 48b11e05cd..771a829cee 100644 --- a/website/docs/features/render/choosing-a-backend.mdx +++ b/website/docs/features/render/choosing-a-backend.mdx @@ -22,7 +22,7 @@ Three render backends ship with alphaTab, each optimizing for a different constr - **Web** — SVG (default) or HTML5 Canvas. Skia is not available in the browser. - **.NET** — Skia (default). SVG works too if you need scalable text output. -- **Android** — Skia (default). SVG works too. +- **Kotlin** — Skia (default) on the JVM and on Android. SVG works too. - **Node.js** — SVG for text output; Skia (via [alphaSkia](https://github.com/CoderLine/alphaSkia)) for PNG. Leaving `core.engine` at `'default'` picks the right backend for the runtime you are on. @@ -44,8 +44,8 @@ Leaving `core.engine` at `'default'` picks the right backend for the runtime you **Reach for [Skia](skia-backend) when:** -- You are on .NET or Android and want the platform default — consistent output across Windows, macOS, Linux, and Android. -- You need PNG or raster export from a headless environment (Node.js, CI, server pipelines). +- You are on .NET or Kotlin and want the platform default — consistent output across Windows, macOS, Linux, and Android. +- You need PNG or raster export from a headless environment (Node.js, the JVM, CI, server pipelines). - You register custom `.ttf` / `.otf` fonts and want them applied via [`registerAlphaSkiaCustomFont`](/docs/features/render/custom-fonts-on-skia). ## Show it in code @@ -68,6 +68,6 @@ const api = new alphaTab.AlphaTabApi(container, { - [SVG rendering](svg-output) — the vector default. - [HTML5 Canvas](html5-canvas) — Web-only raster. -- [Skia rendering (.NET / Android)](skia-backend) — native raster off the Web. +- [Skia rendering (.NET / Kotlin)](skia-backend) — native raster off the Web. - [Node.js headless rendering](nodejs-headless-rendering) — server-side image pipelines. - [`core.engine`](/docs/reference/settings/core/engine) in the settings reference. diff --git a/website/docs/features/render/custom-fonts-on-skia.mdx b/website/docs/features/render/custom-fonts-on-skia.mdx index e4968b58b8..a10a173ba6 100644 --- a/website/docs/features/render/custom-fonts-on-skia.mdx +++ b/website/docs/features/render/custom-fonts-on-skia.mdx @@ -1,15 +1,16 @@ --- title: "Custom fonts on Skia" -description: "Register any font with the Skia rendering backend used on .NET and Android via Environment.registerAlphaSkiaCustomFont." +description: "Register any font with the Skia rendering backend used on .NET and Kotlin via Environment.registerAlphaSkiaCustomFont." sidebar_custom_props: feature_chapter: fonts feature_order: 30 - feature_platforms: [net, android] + feature_platforms: [net, kotlin] keywords: - alphaTab - Skia - custom font - .NET + - Kotlin - Android --- @@ -17,9 +18,9 @@ import { AlphaTab } from '@site/src/components/AlphaTab'; import * as Riffs from '@site/src/tex-riffs'; -Building a .NET desktop app or Android app that uses non-system fonts — a corporate typography brief for titles and lyrics, a language-specific font for East-Asian lyric text, or a hand-lettered wordmark for the score header? The Skia rendering backend that powers alphaTab on those runtimes does not read fonts from the operating system's font store. Every font used around the notation — titles, lyrics, chord names, fingerings — must be registered with Skia explicitly first. +Building a .NET desktop app, a JVM service or an Android app that uses non-system fonts — a corporate typography brief for titles and lyrics, a language-specific font for East-Asian lyric text, or a hand-lettered wordmark for the score header? The Skia rendering backend that powers alphaTab on those runtimes does not read fonts from the operating system's font store. Every font used around the notation — titles, lyrics, chord names, fingerings — must be registered with Skia explicitly first. -This registration flow is Skia-only. The preview below is a browser render for illustration; the code snippet configures the exact pipeline that runs inside a .NET or Android app. +This registration flow is Skia-only. The preview below is a browser render for illustration; the code snippet configures the exact pipeline that runs inside a .NET, JVM or Android app. {Riffs.AMAZING_GRACE} @@ -45,7 +46,7 @@ const container = getAlphaTabContainer(); const api = new alphaTab.AlphaTabApi(container, settings); ``` -`loadFontBytes()` and `getAlphaTabContainer()` are placeholders for the platform-specific pieces. On .NET, read the font with `File.ReadAllBytes` or from an embedded resource stream. On Android, open it from `assets/` via `AssetManager` and copy into a `ByteArray`. Every line after registration runs unchanged on both runtimes. +`loadFontBytes()` and `getAlphaTabContainer()` are placeholders for the platform-specific pieces. On .NET, read the font with `File.ReadAllBytes` or from an embedded resource stream. On the JVM, read it with `File.readBytes()`. On Android, open it from `assets/` via `AssetManager` and copy into a `ByteArray`. Every line after registration runs unchanged on both runtimes. ## What to register diff --git a/website/docs/features/render/custom-smufl-fonts.mdx b/website/docs/features/render/custom-smufl-fonts.mdx index a959e6d19e..2542e9ba90 100644 --- a/website/docs/features/render/custom-smufl-fonts.mdx +++ b/website/docs/features/render/custom-smufl-fonts.mdx @@ -73,7 +73,7 @@ If you want to author a new SMuFL font instead of adopting an existing one: - Start from the [SMuFL specification](https://www.smufl.org/) — glyph codepoints are stable across every compliant font. - Publish a `metadata.json` following the [Bravura reference](https://github.com/steinbergmedia/bravura/blob/master/redist/bravura_metadata.json). alphaTab reads `engravingDefaults`, glyph anchor points (`stemUpSE`, `stemDownNW`, `cutOutNW`, etc.), and bounding boxes. -- Ship at least `.woff2` and `.otf`. On .NET and Android alphaTab uses the OpenType variant. +- Ship at least `.woff2` and `.otf`. On .NET and Kotlin alphaTab uses the OpenType variant. - Cover the full glyph range alphaTab draws (listed above). Missing glyphs do not fall back — they render as gaps. ## Licensing @@ -83,6 +83,6 @@ The default Bravura font is licensed under [SIL Open Font License 1.1](https://s ## Where to look next - [Bravura and SMuFL](/docs/features/render/bravura-default) — the default font and why SMuFL matters. -- [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia) — the equivalent workflow on .NET and Android. +- [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia) — the equivalent workflow on .NET and Kotlin. - [`CoreSettings.smuflFontSources`](/docs/reference/settings/core/smuflfontsources) and [`EngravingSettings.fillFromSmufl`](/docs/reference/types/engravingsettings) in the reference. - [Petaluma](https://github.com/steinbergmedia/petaluma) and [Leland](https://github.com/MuseScoreFonts/Leland) — two alternate SMuFL fonts that pair well with alphaTab. diff --git a/website/docs/features/render/custom-text-fonts.mdx b/website/docs/features/render/custom-text-fonts.mdx index 2319355b75..dd1cab96d1 100644 --- a/website/docs/features/render/custom-text-fonts.mdx +++ b/website/docs/features/render/custom-text-fonts.mdx @@ -85,7 +85,7 @@ const api = new alphaTab.AlphaTabApi(container, { `getAlphaTabContainer()` is a placeholder for the platform-specific step of obtaining the render target — a `
` on Web, an `AlphaTab` control on .NET, or an `AlphaTabView` on Android. Every other line runs unchanged on all three runtimes. -Ensure the fonts you reference are actually loaded on the page (as web fonts on the Web, registered with alphaSkia on .NET / Android). alphaTab does not fetch text fonts for you. +Ensure the fonts you reference are actually loaded on the page (as web fonts on the Web, registered with alphaSkia on .NET / Kotlin). alphaTab does not fetch text fonts for you. ## Where to look next diff --git a/website/docs/features/render/font-family-fallbacks.mdx b/website/docs/features/render/font-family-fallbacks.mdx index 90e4ed5ec1..278878b19b 100644 --- a/website/docs/features/render/font-family-fallbacks.mdx +++ b/website/docs/features/render/font-family-fallbacks.mdx @@ -39,7 +39,7 @@ You can express a `Font` in three shapes and each one supports fallback: - **JSON object** — `{ families: ['Playfair Display', 'Georgia', 'serif'], size: 20, style: 'Italic', weight: 'Bold' }`. - **`Font` instance** — `Font.withFamilyList(['Playfair Display', 'Georgia', 'serif'], 20, ...)` for programmatic construction. -The Web backend hands the family list to CSS as-is, so browser font matching does the work. The Skia backend (used on .NET and Android via alphaSkia) walks the list in order and uses the first family registered through `registerAlphaSkiaCustomFont`. +The Web backend hands the family list to CSS as-is, so browser font matching does the work. The Skia backend (used on .NET and Kotlin via alphaSkia) walks the list in order and uses the first family registered through `registerAlphaSkiaCustomFont`. ## Show it in code @@ -66,5 +66,5 @@ The same fallback rule applies to the deprecated `family` getter for backward co ## Where to look next - [Custom text fonts](/docs/features/render/custom-text-fonts) — every text field you can target. -- [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia) — register families for the .NET and Android backends. +- [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia) — register families for the .NET and Kotlin backends. - [`Font`](/docs/reference/types/model/font) in the reference. diff --git a/website/docs/features/render/html5-canvas.mdx b/website/docs/features/render/html5-canvas.mdx index 21056f0a0d..935edd16e3 100644 --- a/website/docs/features/render/html5-canvas.mdx +++ b/website/docs/features/render/html5-canvas.mdx @@ -21,7 +21,7 @@ Draw the score into `` elements instead of SVG. Reach for the Canvas bac ## When Canvas is the right pick -HTML5 Canvas is a Web-only backend — .NET uses [Skia](skia-backend), Android uses Skia. On the Web, reach for it when: +HTML5 Canvas is a Web-only backend — .NET and Kotlin use [Skia](skia-backend). On the Web, reach for it when: - **The score is long or dense.** Thousands of SVG nodes slow down scrolling and repaint; a canvas surface stays a single element regardless of note count. - **You do not need per-element CSS or hit-testing on the DOM.** alphaTab's own bounds lookup still works for mouse and touch — see [Bounds lookup](/docs/features/interact/bounds-lookup) — but you cannot restyle a single glyph via a CSS selector. @@ -43,11 +43,11 @@ const api = new alphaTab.AlphaTabApi(container, { }); ``` -`getAlphaTabContainer()` is the placeholder for the render target — on Web that is the `
` alphaTab attaches to. Canvas is only available on the Web runtime; passing `engine: 'html5'` from .NET or Android falls back to the platform default. +`getAlphaTabContainer()` is the placeholder for the render target — on Web that is the `
` alphaTab attaches to. Canvas is only available on the Web runtime; passing `engine: 'html5'` from .NET or Kotlin falls back to the platform default. ## Where to look next - [SVG rendering](svg-output) — the vector default, better for print and accessibility. -- [Skia rendering (.NET / Android)](skia-backend) — the native raster equivalent off the Web. +- [Skia rendering (.NET / Kotlin)](skia-backend) — the native raster equivalent off the Web. - [Choosing a backend](choosing-a-backend) — side-by-side comparison. - [`core.engine`](/docs/reference/settings/core/engine) in the settings reference. diff --git a/website/docs/features/render/index.mdx b/website/docs/features/render/index.mdx index 4280af2fb4..4c88415b77 100644 --- a/website/docs/features/render/index.mdx +++ b/website/docs/features/render/index.mdx @@ -21,7 +21,7 @@ import chapters from './_chapters'; The render engine walks the score model, applies traditional music-engraving rules, and draws the result through a pluggable canvas backend. alphaTab uses the [Bravura](https://github.com/steinbergmedia/bravura) SMuFL font for every glyph and re-flows the score when the container it lives in changes size. -Every capability below is available on Web, .NET, and Android unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. +Every capability below is available on Web, .NET, and Kotlin unless a card names specific platforms. Follow any card into the [reference](/docs/reference/api/) for the exact signature. {chapters.map((chapter) => (
diff --git a/website/docs/features/render/nodejs-headless-rendering.mdx b/website/docs/features/render/nodejs-headless-rendering.mdx index 72fa96daed..528870ce95 100644 --- a/website/docs/features/render/nodejs-headless-rendering.mdx +++ b/website/docs/features/render/nodejs-headless-rendering.mdx @@ -63,7 +63,7 @@ Swap `engine` to `'skia'` and wire `Environment.enableAlphaSkia` plus an `AlphaS ## Where to look next - [Node.js guide](/docs/guides/nodejs) — the full walkthrough including PNG export and custom fonts. -- [Skia rendering (.NET / Android)](skia-backend) — the same backend used for PNG output. +- [Skia rendering (.NET / Kotlin)](skia-backend) — the same backend used for PNG output. - [alphaSkia on GitHub](https://github.com/CoderLine/alphaSkia) — the raster rendering library. - [`ScoreRenderer`](/docs/reference/types/rendering/scorerenderer) in the API reference. - [`core.engine`](/docs/reference/settings/core/engine) in the settings reference. diff --git a/website/docs/features/render/skia-backend.mdx b/website/docs/features/render/skia-backend.mdx index 39eab4472b..cd123e2b9c 100644 --- a/website/docs/features/render/skia-backend.mdx +++ b/website/docs/features/render/skia-backend.mdx @@ -1,5 +1,5 @@ --- -title: "Skia rendering (.NET / Android)" +title: "Skia rendering (.NET / Kotlin)" description: "Native rendering via alphaSkia." sidebar_custom_props: feature_chapter: backends @@ -14,15 +14,15 @@ import { AlphaTab } from '@site/src/components/AlphaTab'; import * as Riffs from '@site/src/tex-riffs'; -Skia is the default rendering engine on .NET and Android — reach for it when building a WPF or MAUI desktop app, an Android app hosting `AlphaTabView`, or any pipeline where you need PNG bytes off a native runtime. alphaTab renders through [alphaSkia](https://github.com/CoderLine/alphaSkia), a thin wrapper around Google's [Skia](https://skia.org/) library, so the same score produces identical glyph metrics across Windows, macOS, Linux, and Android. +Skia is the default rendering engine on .NET and Kotlin — reach for it when building a WPF or MAUI desktop app, an Android app hosting `AlphaTabView`, a JVM service, or any pipeline where you need PNG bytes off a native runtime. alphaTab renders through [alphaSkia](https://github.com/CoderLine/alphaSkia), a thin wrapper around Google's [Skia](https://skia.org/) library, so the same score produces identical glyph metrics across Windows, macOS, Linux, and Android. -The preview below is a browser-side SVG rendering; the code snippet configures the exact same pipeline on .NET or Android, where Skia takes over and produces raster output. +The preview below is a browser-side SVG rendering; the code snippet configures the exact same pipeline on .NET or Kotlin, where Skia takes over and produces raster output. {Riffs.PACHELBEL_CANON} ## What Skia gets you -- **Native raster on every non-web target.** Skia is the default engine on .NET and Android, so leaving `engine` unset already picks it. Setting it explicitly makes intent clear. +- **Native raster on every non-web target.** Skia is the default engine on .NET and Kotlin, so leaving `engine` unset already picks it. Setting it explicitly makes intent clear. - **Consistent output across platforms.** The same score renders identically on WPF, MAUI, and Android — no more platform-specific font hinting differences. - **PNG export.** The alphaSkia canvas exposes `toPng()`, which is what powers the [Node.js headless rendering](nodejs-headless-rendering) workflow. - **Custom font support.** Register `.ttf` / `.otf` files with `Environment.registerAlphaSkiaCustomFont` and use them in `display.resources`. See [Custom fonts on Skia](/docs/features/render/custom-fonts-on-skia). @@ -45,7 +45,7 @@ const api = new alphaTab.AlphaTabApi(container, { `getAlphaTabContainer()` is a placeholder for the platform-specific step of obtaining the render target — an `AlphaTab` control on .NET or an `AlphaTabView` on Android. On desktop .NET you typically embed the WPF or WinForms control; on Android you place `AlphaTabView` in a layout. -For a Node.js pipeline that renders to PNG on the server, see [Node.js headless rendering](nodejs-headless-rendering). +For a Node.js pipeline that renders to PNG on the server, see [Node.js headless rendering](nodejs-headless-rendering). For the JVM, see [Render on the JVM](/docs/getting-started/installation-kotlin#render-on-the-jvm). ## Where to look next diff --git a/website/docs/features/render/svg-output.mdx b/website/docs/features/render/svg-output.mdx index d209a63969..329468ef8f 100644 --- a/website/docs/features/render/svg-output.mdx +++ b/website/docs/features/render/svg-output.mdx @@ -25,9 +25,9 @@ SVG is the default backend on Web and the recommended output whenever the render - **Scales without loss.** Zoom or export at any DPI; the glyph outlines stay crisp. - **Prints cleanly.** Browsers rasterize SVG at printer resolution, so bar lines and note heads land pixel-accurate on paper. - **Hit-testable.** Each rendered element sits in the DOM, so custom overlays and DOM queries work directly against the score geometry. -- **Available on every platform.** SVG runs the same on Web, .NET, and Android — pass `engine: 'svg'` anywhere and get identical output. +- **Available on every platform.** SVG runs the same on Web, .NET, and Kotlin — pass `engine: 'svg'` anywhere and get identical output. -The trade-off is throughput. On very dense scores (hundreds of bars in a single view) the DOM grows large and layout thrash can appear during scroll. For that case, reach for [HTML5 Canvas](html5-canvas) on Web or [Skia](skia-backend) on .NET / Android. +The trade-off is throughput. On very dense scores (hundreds of bars in a single view) the DOM grows large and layout thrash can appear during scroll. For that case, reach for [HTML5 Canvas](html5-canvas) on Web or [Skia](skia-backend) on .NET / Kotlin. ## Show it in code @@ -48,6 +48,6 @@ const api = new alphaTab.AlphaTabApi(container, { ## Where to look next - [HTML5 Canvas](html5-canvas) — Web-only raster alternative for dense scores. -- [Skia rendering (.NET / Android)](skia-backend) — native raster on non-web runtimes. +- [Skia rendering (.NET / Kotlin)](skia-backend) — native raster on non-web runtimes. - [Choosing a backend](choosing-a-backend) — side-by-side comparison. - [`core.engine`](/docs/reference/settings/core/engine) in the settings reference. diff --git a/website/docs/getting-started/configuration-android.mdx b/website/docs/getting-started/configuration-android.mdx index b39680549d..539c8f559a 100644 --- a/website/docs/getting-started/configuration-android.mdx +++ b/website/docs/getting-started/configuration-android.mdx @@ -16,9 +16,9 @@ The `AlphaTabView` is the entry point to alphaTab on Android. Every setting, eve ## Setup -Add the `AlphaTabView` to your layout and grab a reference to it in the activity. The [installation page](installation-android#render-your-first-score) shows the full XML and Kotlin. +Add the `AlphaTabView` to your layout and grab a reference to it in the activity. The [installation page](installation-kotlin#render-on-android) shows the full XML and Kotlin. -For non-UI backgrounds — services, background workers, or custom controls — use the low-level classes directly instead of the view. The [Kotlin sources on GitHub](https://github.com/CoderLine/alphaTab/tree/develop/src.kotlin) show how the `AlphaTabView` is built and can be used as a reference for a bespoke wrapper. +For non-UI backgrounds — services, background workers, or custom controls — use the low-level classes directly instead of the view, as shown in [Render on the JVM](installation-kotlin#render-on-the-jvm) and the [low-level API guide](/docs/guides/lowlevel-apis). The [Android sources on GitHub](https://github.com/CoderLine/alphaTab/tree/develop/packages/kotlin/src/android) show how the `AlphaTabView` is built and can be used as a reference for a bespoke wrapper. ## Settings diff --git a/website/docs/getting-started/installation-android.mdx b/website/docs/getting-started/installation-android.mdx deleted file mode 100644 index 38a84de5ec..0000000000 --- a/website/docs/getting-started/installation-android.mdx +++ /dev/null @@ -1,153 +0,0 @@ ---- -title: Installation (Android) -description: Install alphaTab in a Kotlin Android project via Maven Central, then render music notation in a native activity. -keywords: - - alphaTab - - Android - - Kotlin - - Maven - - Gradle - - AlphaTabView - - music notation ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -alphaTab on Android renders and plays music notation in native apps built with Kotlin. It ships an `AlphaTabView` for classic Android layouts. - -## Install - -alphaTab is published on Maven Central under the coordinates `net.alphatab:alphaTab`: - -- Release versions: [central.sonatype.com/artifact/net.alphatab/alphaTab](https://central.sonatype.com/artifact/net.alphatab/alphaTab) -- Pre-release snapshots: [central.sonatype.com/repository/maven-snapshots](https://central.sonatype.com/repository/maven-snapshots/) - -Add the dependency to your build system: - - - - -```kotlin -repositories { - google() - mavenCentral() - // Pre-release snapshots: - // maven("https://central.sonatype.com/repository/maven-snapshots/") -} - -dependencies { - implementation("net.alphatab:alphaTab:1.6.1") - // Pre-release snapshots: - // implementation("net.alphatab:alphaTab:1.7.0-SNAPSHOT") -} -``` - - - - -```groovy -repositories { - google() - mavenCentral() - // Pre-release snapshots: - // maven { - // url = "https://central.sonatype.com/repository/maven-snapshots/" - // } -} - -dependencies { - implementation "net.alphatab:alphaTab:1.6.1" - // Pre-release snapshots: - // implementation "net.alphatab:alphaTab:1.7.0-SNAPSHOT" -} -``` - - - - -```xml - - - - net.alphatab - alphaTab - 1.6.1 - - - runtime - - - -``` - - - - -## Render your first score - -Once alphaTab is on the classpath, add the `AlphaTabView` control to any layout. This example places it inside a `ConstraintLayout` that fills the activity: - -```xml - - - - - - -``` - -Get a reference to the view from your activity and use its `api` property to drive alphaTab: - -```kotlin -import alphaTab.AlphaTabView - -class MainActivity : ComponentActivity() { - private lateinit var alphaTabView: AlphaTabView - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - - alphaTabView = findViewById(R.id.alphatab_view) - val api = alphaTabView.api - // load a score, subscribe to events, drive playback here - } -} -``` - -More samples live at [github.com/CoderLine/alphaTabSamplesAndroid](https://github.com/CoderLine/alphaTabSamplesAndroid/). - -## Jetpack Compose - -alphaTab does not currently ship a Compose control. Two options: - -- Vote on the [roadmap issue](https://github.com/CoderLine/alphaTab/issues/1475) to signal demand. -- [Wrap the classic `AlphaTabView`](https://developer.android.com/develop/ui/compose/libraries) inside a Compose tree using `AndroidView`. - -## Dependencies - -alphaTab on Android carries a small number of third-party dependencies: - -- **Rendering.** Either the built-in Android `Canvas` or [alphaSkia](https://github.com/CoderLine/alphaSkia), which wraps the Skia engine used by Chrome. alphaSkia is the recommended engine and is significantly faster than the platform canvas. -- **Async.** `org.jetbrains.kotlinx:kotlinx-coroutines-core` powers alphaTab's asynchronous operations. - -Reach out on GitHub if you need alphaTab wired to a different UI framework or audio backend. diff --git a/website/docs/getting-started/installation-kotlin.mdx b/website/docs/getting-started/installation-kotlin.mdx new file mode 100644 index 0000000000..5cb7f43bf2 --- /dev/null +++ b/website/docs/getting-started/installation-kotlin.mdx @@ -0,0 +1,222 @@ +--- +title: Installation (Kotlin) +description: Install alphaTab from Maven Central, then render music notation on any JVM or in an Android app. +keywords: + - alphaTab + - Kotlin + - Java + - JVM + - Android + - Maven + - Gradle + - AlphaTabView + - music notation +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +alphaTab for Kotlin runs on any JVM, for servers, command-line tools and headless rendering, and in Android apps with a native `AlphaTabView`. + +## Install + +Two packages on Maven Central cover the Kotlin target: + +- [`net.alphatab:alphaTab-core`](https://central.sonatype.com/artifact/net.alphatab/alphaTab-core) runs on any JVM 17 or newer. It contains the importers and exporters, the renderer and the synthesizer, and is used through the [low-level APIs](/docs/guides/lowlevel-apis). It has no UI control and no audio output. +- [`net.alphatab:alphaTab`](https://central.sonatype.com/artifact/net.alphatab/alphaTab) is the Android library (minSdk 26). It adds the `AlphaTabView`, the Android canvas and the audio output, and brings in `alphaTab-core` as a dependency. + +Always use both packages in the same version: `net.alphatab:alphaTab` requires exactly its own version of `alphaTab-core`. Pre-release snapshots are published to [central.sonatype.com/repository/maven-snapshots](https://central.sonatype.com/repository/maven-snapshots/). + + + + +```kotlin +repositories { + google() + mavenCentral() + // Pre-release snapshots: + // maven("https://central.sonatype.com/repository/maven-snapshots/") +} + +dependencies { + // Android apps: + implementation("net.alphatab:alphaTab:1.10.0") + + // JVM applications, with the native Skia library of the target OS: + // implementation("net.alphatab:alphaTab-core:1.10.0") + // implementation("net.alphatab:alphaSkia-linux:3.5.147") +} +``` + + + + +```groovy +repositories { + google() + mavenCentral() + // Pre-release snapshots: + // maven { + // url = "https://central.sonatype.com/repository/maven-snapshots/" + // } +} + +dependencies { + // Android apps: + implementation "net.alphatab:alphaTab:1.10.0" + + // JVM applications, with the native Skia library of the target OS: + // implementation "net.alphatab:alphaTab-core:1.10.0" + // implementation "net.alphatab:alphaSkia-linux:3.5.147" +} +``` + + + + +```xml + + + + + net.alphatab + alphaTab-core + 1.10.0 + + + + net.alphatab + alphaSkia-linux + 3.5.147 + + + +``` + + + + +## Render on the JVM {#render-on-the-jvm} + +On a JVM, alphaTab renders through alphaSkia, which needs a native library per operating system: `net.alphatab:alphaSkia-windows`, `alphaSkia-linux` or `alphaSkia-macos`, with the entry points `AlphaSkiaWindows`, `AlphaSkiaLinux` and `AlphaSkiaMacOs`. Use the alphaSkia version that `alphaTab-core` depends on. + +alphaSkia also needs the Bravura music font. It ships as `dist/font/Bravura.otf` in the [`@coderline/alphatab`](https://www.npmjs.com/package/@coderline/alphatab) npm package. + +This command-line program loads a file, renders it 970 pixels wide and writes one PNG per rendered part: + +```kotlin +import alphaTab.Environment +import alphaTab.Settings +import alphaTab.alphaSkia.AlphaSkiaLinux +import alphaTab.collections.DoubleList +import alphaTab.core.ecmaScript.Uint8Array +import alphaTab.importer.ScoreLoader +import alphaTab.platform.skia.AlphaSkiaImage +import alphaTab.rendering.ScoreRenderer +import java.io.File +import kotlin.contracts.ExperimentalContracts + +@OptIn(ExperimentalUnsignedTypes::class, ExperimentalContracts::class) +fun main(args: Array) { + AlphaSkiaLinux.INSTANCE.initialize() + Environment.enableAlphaSkia(File("Bravura.otf").readBytes().asUByteArray(), null) + + val score = ScoreLoader.loadScoreFromBytes(Uint8Array(File(args[0]).readBytes().asUByteArray()), null) + + val settings = Settings() + settings.core.engine = "skia" + settings.core.enableLazyLoading = false + + val renderer = ScoreRenderer(settings) + renderer.width = 970.0 + + var index = 0 + renderer.partialRenderFinished.on { result -> + (result.renderResult as AlphaSkiaImage).use { image -> + File("score-${index++}.png").writeBytes(image.toPng()!!.asByteArray()) + } + } + renderer.renderFinished.on { result -> + println("Rendered $index images, ${result.totalWidth}x${result.totalHeight}") + } + + renderer.renderScore(score, DoubleList(0.0), null) +} +``` + +- `enableLazyLoading = false` renders every part right away. With lazy loading, a part is only rendered once a UI requests it. +- Text uses the fonts installed on the system. On a server without fonts, register them with `Environment.registerAlphaSkiaCustomFont`. +- Set `settings.core.engine = "svg"` to receive every part as an SVG string instead. Initialize alphaSkia anyway: alphaTab measures text through it. + +The [low-level API guide](/docs/guides/lowlevel-apis) shows MIDI generation, audio synthesis and JSON serialization with the same classes. + +{/* Anchor of this section on the former installation-android page, which redirects here. */} + + +## Render on Android {#render-on-android} + +Add the `AlphaTabView` control to any layout. This example places it inside a `ConstraintLayout` that fills the activity: + +```xml + + + + + + +``` + +Get a reference to the view from your activity and use its `api` property to drive alphaTab: + +```kotlin +import alphaTab.AlphaTabView + +class MainActivity : ComponentActivity() { + private lateinit var alphaTabView: AlphaTabView + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + alphaTabView = findViewById(R.id.alphatab_view) + val api = alphaTabView.api + // load a score, subscribe to events, drive playback here + } +} +``` + +The Android library bundles the Bravura font and the default SoundFont and initializes alphaSkia itself. More samples live at [github.com/CoderLine/alphaTabSamplesAndroid](https://github.com/CoderLine/alphaTabSamplesAndroid/). + +## Jetpack Compose + +alphaTab does not currently ship a Compose control. Two options: + +- Vote on the [roadmap issue](https://github.com/CoderLine/alphaTab/issues/1475) to signal demand. +- [Wrap the classic `AlphaTabView`](https://developer.android.com/develop/ui/compose/libraries) inside a Compose tree using `AndroidView`. + +## Dependencies + +alphaTab for Kotlin carries a small number of third-party dependencies: + +- **Rendering.** [alphaSkia](https://github.com/CoderLine/alphaSkia), which wraps the Skia engine used by Chrome, or the SVG output. On Android the built-in Android `Canvas` is available as well; alphaSkia is significantly faster. +- **Async.** `org.jetbrains.kotlinx:kotlinx-coroutines-core` powers alphaTab's asynchronous operations. + +There is no UI control for desktop JVM toolkits such as Swing or JavaFX. Reach out on GitHub if you need alphaTab wired to a different UI framework or audio backend. diff --git a/website/docs/guides/lowlevel-apis.mdx b/website/docs/guides/lowlevel-apis.mdx index b3f1829142..06a982d2ed 100644 --- a/website/docs/guides/lowlevel-apis.mdx +++ b/website/docs/guides/lowlevel-apis.mdx @@ -8,7 +8,8 @@ import TabItem from '@theme/TabItem'; This guide explains how to use the low level APIs of alphaTab in case the full API object cannot be used or is not needed. The full API object is usually linked directly to a UI via a `IUiFacade`. There exist various `IUiFacade` implementations -for the different platforms like for Web, .net WPF and .net WinForms. +for the different platforms like for Web, .NET WPF, .NET WinForms and Android. On the JVM, `net.alphatab:alphaTab-core` has no UI +integration, so these low level APIs are the way to use alphaTab there; see [Render on the JVM](/docs/getting-started/installation-kotlin#render-on-the-jvm). In scenarios where none of these UI platforms are used or if not even a UI exists, you will need to use the low level APIs of alphaTab to setup the individual steps manually. The following examples show the @@ -30,7 +31,8 @@ a `AlphaTab.Settings` object which might control some aspects of the import sequ defaultValue="js" values={[ { label: 'JavaScript', value: 'js', }, - { label: 'C#', value: 'cs', } + { label: 'C#', value: 'cs', }, + { label: 'Kotlin', value: 'kt', } ] }> @@ -56,6 +58,15 @@ var settings = new AlphaTab.Settings(); var score = AlphaTab.Importer.ScoreLoader.LoadScoreFromBytes(data, settings); ``` + + + +```kotlin +val data = java.io.File("MyFile.gp").readBytes() +val settings = alphaTab.Settings() +val score = alphaTab.importer.ScoreLoader.loadScoreFromBytes(alphaTab.core.ecmaScript.Uint8Array(data.asUByteArray()), settings) +``` + @@ -75,7 +86,8 @@ This logic is part of the `AlphaTabApi` which wraps a ScoreRenderer into a worke defaultValue="js" values={[ { label: 'JavaScript', value: 'js', }, - { label: 'C#', value: 'cs', } + { label: 'C#', value: 'cs', }, + { label: 'Kotlin', value: 'kt', } ] }> @@ -159,6 +171,42 @@ renderer.Width = 800; renderer.ResizeRender(); ``` + + + +```kotlin +// 1. Setup renderer +val score: alphaTab.model.Score = /* Load score here */ +val settings = alphaTab.Settings() +settings.core.engine = "svg" +val renderer = alphaTab.rendering.ScoreRenderer(settings) +renderer.width = 1200.0 + +// 2. Listen to Events +val svgChunks = mutableListOf>() // svg, width, height +renderer.preRender.on { isResize -> + svgChunks.clear() // clear on new rendering +} +// request rendering of each chunk layed out. +// you can defer rendering based on your needs. +renderer.partialLayoutFinished.on { r -> + renderer.renderResult(r.id) +} +renderer.partialRenderFinished.on { r -> + svgChunks.add(Triple(r.renderResult as String, r.width, r.height)) +} +renderer.renderFinished.on { r -> + displayResult(svgChunks, r.totalWidth, r.totalHeight) +} + +// 3. Fire off rendering +renderer.renderScore(score, alphaTab.collections.DoubleList(0.0), null) + +// 4. resize +renderer.width = 800.0 +renderer.resizeRender() +``` + @@ -176,7 +224,8 @@ Midi Synthesis engine. The main classes related to midi generation are: defaultValue="js" values={[ { label: 'JavaScript', value: 'js', }, - { label: 'C#', value: 'cs', } + { label: 'C#', value: 'cs', }, + { label: 'Kotlin', value: 'kt', } ] }> @@ -216,6 +265,25 @@ generator.Generate(); SaveToFile(midiFile); ``` + + + +```kotlin +val score: alphaTab.model.Score = /* Load score here */ +val settings = alphaTab.Settings() + +// Setup generator and midi file handler +val midiFile = alphaTab.midi.MidiFile() +val handler = alphaTab.midi.AlphaSynthMidiFileHandler(midiFile, true /* For SMF1.0 export */) +val generator = alphaTab.midi.MidiFileGenerator(score, settings, handler) + +// start generation +generator.generate() + +// use midi file +java.io.File("MyFile.mid").writeBytes(midiFile.toBinary().buffer.asByteArray()) +``` + @@ -233,7 +301,8 @@ to ensure smooth playback. defaultValue="js" values={[ { label: 'JavaScript', value: 'js', }, - { label: 'C#', value: 'cs', } + { label: 'C#', value: 'cs', }, + { label: 'Kotlin', value: 'kt', } ] }> @@ -289,6 +358,22 @@ player.LoadMidiFile(midiFile); player.Play(); ``` + + + +```kotlin +val midiFile: alphaTab.midi.MidiFile = /* Load score and convert it to midi here */ +val soundFont: alphaTab.core.ecmaScript.Uint8Array = /* Load SoundFont2 as Uint8Array here */ + +// alphaTab-core has no audio output of its own: MySynthOutput implements +// alphaTab.synth.ISynthOutput for the sound API of your platform. +// On Android, the AlphaTabView plays through AudioTrack. +val player = alphaTab.synth.AlphaSynth(MySynthOutput(), 500.0) +player.loadSoundFont(soundFont, false) +player.loadMidiFile(midiFile) +player.play() +``` + @@ -321,7 +406,8 @@ For the conversions back to `Score` objects a `Settings` object can/should be pa defaultValue="js" values={[ { label: 'JavaScript', value: 'js', }, - { label: 'C#', value: 'cs', } + { label: 'C#', value: 'cs', }, + { label: 'Kotlin', value: 'kt', } ] }> @@ -341,5 +427,13 @@ var map = AlphaTab.Model.JsonConverter.ScoreToJsObject(api.Score); var score = AlphaTab.Model.JsonConverter.JsObjectToScore(map, api.Settings); ``` + + + +```kotlin +val map = alphaTab.model.JsonConverter.scoreToJsObject(score) +val score2 = alphaTab.model.JsonConverter.jsObjectToScore(map, settings) +``` + \ No newline at end of file diff --git a/website/docs/introduction.mdx b/website/docs/introduction.mdx index 5b224a2dd0..2d33798434 100644 --- a/website/docs/introduction.mdx +++ b/website/docs/introduction.mdx @@ -12,7 +12,7 @@ keywords: - Guitar Pro --- -alphaTab is an SDK for rendering and playing interactive music notation. Use it in JavaScript for the browser and Node.js, in .NET for desktop or server, or in Kotlin for Android. Feed it a Guitar Pro, MusicXML, CapXML, or alphaTex file, wire it into your UI, and you get engraved sheet music that resizes, scrolls, and plays back. +alphaTab is an SDK for rendering and playing interactive music notation. Use it in JavaScript for the browser and Node.js, in .NET for desktop or server, or in Kotlin on the JVM and Android. Feed it a Guitar Pro, MusicXML, CapXML, or alphaTex file, wire it into your UI, and you get engraved sheet music that resizes, scrolls, and plays back. ## An SDK, not a widget @@ -41,7 +41,7 @@ Parsers that fill the data model from a file. Currently supported: ### Render engine -The render engine takes the data model and produces engraved music notation following the rules of traditional music engraving. It builds a visual tree of every symbol and relayouts dynamically when the container resizes. Symbols come from the [SMuFL](https://www.smufl.org/) music font [Bravura](https://github.com/steinbergmedia/bravura). Output goes to HTML Canvas or SVG in the browser, and to Skia or the platform-native canvas on .NET and Android. +The render engine takes the data model and produces engraved music notation following the rules of traditional music engraving. It builds a visual tree of every symbol and relayouts dynamically when the container resizes. Symbols come from the [SMuFL](https://www.smufl.org/) music font [Bravura](https://github.com/steinbergmedia/bravura). Output goes to HTML Canvas or SVG in the browser, and to Skia, SVG or the platform-native canvas on .NET, the JVM and Android. ### Audio engine @@ -49,7 +49,7 @@ The audio engine converts the data model to MIDI, then plays the MIDI through an ## Where it runs -The three implementations share one source. TypeScript is authoritative; a toolchain compiles it to C# and Kotlin so every platform gets the same features on the same release cycle. +The three implementations share one source. TypeScript is authoritative; a toolchain compiles it to C# and Kotlin so every platform gets the same features on the same release cycle. [Platforms and packages](platforms) lists every package and what it contains. ### JavaScript / TypeScript {#javascript} @@ -66,9 +66,12 @@ Two NuGet packages, depending on where you need it: The .NET build has a small number of third-party dependencies for drawing (through alphaSkia) and audio (NAudio). -### Kotlin for Android {#android} +### Kotlin (JVM and Android) {#android} -Distributed on Maven Central as [`net.alphatab:alphaTab`](https://central.sonatype.com/artifact/net.alphatab/alphaTab). It ships an `AlphaTabView` for classic Android layouts. A Jetpack Compose control is not included yet — [vote on the roadmap issue](https://github.com/CoderLine/alphaTab/issues/1475) or [wrap the classic view](https://developer.android.com/develop/ui/compose/libraries) inside a Compose tree. +Two packages on Maven Central, depending on where you need it: + +- [`net.alphatab:alphaTab-core`](https://central.sonatype.com/artifact/net.alphatab/alphaTab-core) runs on any JVM 17 or newer for servers, command-line tools, and headless use. +- [`net.alphatab:alphaTab`](https://central.sonatype.com/artifact/net.alphatab/alphaTab) is the Android library with an `AlphaTabView` for classic Android layouts. A Jetpack Compose control is not included yet — [vote on the roadmap issue](https://github.com/CoderLine/alphaTab/issues/1475) or [wrap the classic view](https://developer.android.com/develop/ui/compose/libraries) inside a Compose tree. ## Next steps @@ -76,6 +79,6 @@ Pick your platform: - [Getting Started (Web)](/docs/getting-started/installation-web) - [Getting Started (.NET)](/docs/getting-started/installation-net) -- [Getting Started (Android)](/docs/getting-started/installation-android) +- [Getting Started (Kotlin)](/docs/getting-started/installation-kotlin) Once installed, browse the [Features](/docs/features/) catalog to see what alphaTab does grouped by capability, or explore [alphaTex](/docs/alphatex/introduction), the text format for authoring music notation. diff --git a/website/docs/platforms.mdx b/website/docs/platforms.mdx new file mode 100644 index 0000000000..b787a1e3fe --- /dev/null +++ b/website/docs/platforms.mdx @@ -0,0 +1,54 @@ +--- +title: Platforms and packages +description: The alphaTab packages for Web, .NET and Kotlin, what each one contains, and where it runs. +keywords: + - alphaTab + - platforms + - packages + - npm + - NuGet + - Maven + - JVM + - Android +--- + +alphaTab ships for three ecosystems from one TypeScript source. This page lists every package, what it contains, and which package to install for your runtime. + +## At a glance + +| Package | Runs on | UI control | Render engines | Audio output | +|---|---|---|---|---| +| [`@coderline/alphatab`](https://www.npmjs.com/package/@coderline/alphatab) | Evergreen browsers, Node.js | `AlphaTabApi` on any DOM element | SVG, HTML5 Canvas; alphaSkia in Node.js | Web Audio (browser) | +| [`AlphaTab`](https://www.nuget.org/packages/AlphaTab/) | .NET Standard 2.0 | — | Skia, GDI+, SVG | — | +| [`AlphaTab.Windows`](https://www.nuget.org/packages/AlphaTab.Windows/) | .NET 8 on Windows | WPF and WinForms controls | Skia, GDI+, SVG | NAudio | +| [`net.alphatab:alphaTab-core`](https://central.sonatype.com/artifact/net.alphatab/alphaTab-core) | JVM 17+ | — | Skia, SVG | — | +| [`net.alphatab:alphaTab`](https://central.sonatype.com/artifact/net.alphatab/alphaTab) | Android 8.0+ (API 26) | `AlphaTabView` | Skia, Android Canvas, SVG | Android `AudioTrack` | + +Packages without a UI control are used through the [low-level APIs](/docs/guides/lowlevel-apis): load files, render to images or SVG, generate MIDI, synthesize and export audio. Packages without an audio output still run the synthesizer; to play its samples, implement `ISynthOutput` for the sound API of your platform. + +## Web + +- [`@coderline/alphatab`](https://www.npmjs.com/package/@coderline/alphatab) contains everything for the browser and for Node.js, with no runtime dependencies. +- [`@coderline/alphatab-webpack`](/docs/getting-started/installation-webpack) and [`@coderline/alphatab-vite`](/docs/getting-started/installation-vite) are build plugins that wire up alphaTab's workers, worklets, font and SoundFont in your bundler. +- [`@coderline/alphatab-monaco`](https://www.npmjs.com/package/@coderline/alphatab-monaco) and [`@coderline/alphatab-language-server`](https://www.npmjs.com/package/@coderline/alphatab-language-server) add alphaTex editing support. +- [`@coderline/alphaskia`](https://www.npmjs.com/package/@coderline/alphaskia) plus `@coderline/alphaskia-windows`, `-linux` or `-macos` enable PNG rendering in Node.js; see [Node.js headless rendering](/docs/features/render/nodejs-headless-rendering). + +Start with [Installation (Web)](/docs/getting-started/installation-web). + +## .NET + +- [`AlphaTab`](https://www.nuget.org/packages/AlphaTab/) targets .NET Standard 2.0 for console tools, servers and headless rendering. +- [`AlphaTab.Windows`](https://www.nuget.org/packages/AlphaTab.Windows/) targets .NET 8.0 on Windows and adds the WPF and WinForms controls and NAudio playback. It depends on `AlphaTab`. +- `AlphaSkia.Native.Windows`, `AlphaSkia.Native.Linux` and `AlphaSkia.Native.MacOs` provide the native Skia library per operating system. `AlphaTab.Windows` brings the Windows one. + +Start with [Installation (.NET)](/docs/getting-started/installation-net). + +## Kotlin + +- [`net.alphatab:alphaTab-core`](https://central.sonatype.com/artifact/net.alphatab/alphaTab-core) runs on any JVM 17 or newer, on servers, in command-line tools and in desktop applications. It is the platform-independent part of alphaTab for Kotlin and Java code. +- [`net.alphatab:alphaTab`](https://central.sonatype.com/artifact/net.alphatab/alphaTab) is the Android library. It adds the `AlphaTabView`, the Android canvas and audio output, bundles the Bravura font and the default SoundFont, and depends on `alphaTab-core` in exactly the same version. +- `net.alphatab:alphaSkia-windows`, `alphaSkia-linux` and `alphaSkia-macos` provide the native Skia library on the JVM. The Android library brings `alphaSkia-android`. + +There is no UI control for desktop JVM toolkits such as Swing or JavaFX, and none is planned. + +Start with [Installation (Kotlin)](/docs/getting-started/installation-kotlin). diff --git a/website/docs/releases/release1_10.mdx b/website/docs/releases/release1_10.mdx index abedf0e971..e20f508f99 100644 --- a/website/docs/releases/release1_10.mdx +++ b/website/docs/releases/release1_10.mdx @@ -39,9 +39,21 @@ Numbered staves write every note instead of a single digit per beat. A chord is The previous display with a single digit of the first voice, as in Guitar Pro, is available as the new [`NumberedNoteMode.SingleNote`](/docs/reference/types/model/numberednotemode); it now shows the highest note of a chord. Details: [Chords and multiple voices](/docs/features/render/numbered-notation#chords-and-multiple-voices). +### Kotlin + +#### kotlin: platform-independent alphaTab-core library +https://github.com/CoderLine/alphaTab/issues/2458 + +alphaTab for Kotlin is published as two packages, like the .NET version. The new [`net.alphatab:alphaTab-core`](https://central.sonatype.com/artifact/net.alphatab/alphaTab-core) runs on any JVM 17 or newer: load files, render to PNG or SVG through alphaSkia, generate MIDI and synthesize audio on servers, in command-line tools or in desktop applications. [`net.alphatab:alphaTab`](https://central.sonatype.com/artifact/net.alphatab/alphaTab) stays the Android library with the `AlphaTabView` and is built on top of the core. Details: [Platforms and packages](/docs/platforms) and [Render on the JVM](/docs/getting-started/installation-kotlin#render-on-the-jvm). + ### Upgrade Notes #### Visual changes * Low octave dots on numbered staves sit below the duration lines instead of between digit and lines, as in printed jiǎnpǔ. * Numbered staves show all notes of chords and all voices. Set `notes` of the numbered staff configuration to `NumberedNoteMode.SingleNote` (alphaTex: `\defaultStaffDisplay numbered { notes singleNote }`) for one digit per beat; see [Single note mode](/docs/features/render/numbered-notation#single-note-mode). + +#### Kotlin packages + +* Android apps need no change: `net.alphatab:alphaTab` brings in `net.alphatab:alphaTab-core` in the same version. Builds that do not resolve transitive dependencies must add `alphaTab-core` themselves. +* The Android installation page moved to [Installation (Kotlin)](/docs/getting-started/installation-kotlin); the old address redirects there. diff --git a/website/docs/style-guide.md b/website/docs/style-guide.md index 14bf68e6ba..a0a0dfecbf 100644 --- a/website/docs/style-guide.md +++ b/website/docs/style-guide.md @@ -44,7 +44,7 @@ Every operational page opens with: Elaboration and edge cases come after those three. Concept content ("what alphaTab is") stays on the introduction page, not mixed into installation. -Multi-platform documentation uses parallel pages, not tabs. Web, .NET, and Android each get their own installation and configuration pages. Tabs are reserved for package managers (npm / pnpm / yarn) and other truly interchangeable choices. +Multi-platform documentation uses parallel pages, not tabs. Web, .NET, and Kotlin each get their own installation and configuration pages. Tabs are reserved for package managers (npm / pnpm / yarn) and other truly interchangeable choices. ## Code samples diff --git a/website/docusaurus.config.mts b/website/docusaurus.config.mts index eb5436c6b2..cedf8eaa78 100644 --- a/website/docusaurus.config.mts +++ b/website/docusaurus.config.mts @@ -567,7 +567,7 @@ async function createConfig(): Promise { { label: "Getting started", to: "/docs/introduction" }, { label: "Web", to: "/docs/getting-started/installation-web" }, { label: ".NET", to: "/docs/getting-started/installation-net" }, - { label: "Android", to: "/docs/getting-started/installation-android" }, + { label: "Kotlin", to: "/docs/getting-started/installation-kotlin" }, { label: "API reference", to: "/docs/reference/api" }, ], }, @@ -649,6 +649,7 @@ async function createConfig(): Promise { { from: "/docs/migration/data-attributes", to: "/docs/getting-started/configuration-web" }, { from: "/docs/migration/dom-events", to: "/docs/getting-started/configuration-web" }, { from: "/docs/migration/jquery", to: "/docs/getting-started/installation-web" }, + { from: "/docs/getting-started/installation-android", to: "/docs/getting-started/installation-kotlin" }, { from: "/docs/showcase/general", to: "/docs/features/render/coverage-repeats", diff --git a/website/sidebars.ts b/website/sidebars.ts index 463158a616..b6932452bb 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -4,6 +4,7 @@ const sidebars: SidebarsConfig = { docs: { alphaTab: [ "introduction", + "platforms", "contributing", "attribution" ], @@ -49,8 +50,8 @@ const sidebars: SidebarsConfig = { "getting-started/installation-net", "getting-started/configuration-net", ], - "Getting Started (Android)": [ - "getting-started/installation-android", + "Getting Started (Kotlin)": [ + "getting-started/installation-kotlin", "getting-started/configuration-android", ], Guides: [ diff --git a/website/src/components/CodeBadge/index.tsx b/website/src/components/CodeBadge/index.tsx index c7e194bdd8..a0a52b115a 100644 --- a/website/src/components/CodeBadge/index.tsx +++ b/website/src/components/CodeBadge/index.tsx @@ -13,7 +13,7 @@ export type Platform = | "json" | "json-html" | "html" - | "android"; + | "kotlin"; export type CodeBadgeProps = { type?: Platform; @@ -37,8 +37,8 @@ export const CodeBadge: React.FC = ({ type, name, link }) => { case "net": title = ".net"; break; - case "android": - title = "Android"; + case "kotlin": + title = "Kotlin"; break; case "net-wf": title = ".net WinForms"; diff --git a/website/src/components/CodeBadge/styles.module.scss b/website/src/components/CodeBadge/styles.module.scss index a1e3adacb7..28ac72b07b 100644 --- a/website/src/components/CodeBadge/styles.module.scss +++ b/website/src/components/CodeBadge/styles.module.scss @@ -25,11 +25,11 @@ color: #5d99c6; } -.android { +.kotlin { border-color: #75a478; } -.android span { +.kotlin span { color: #75a478; } diff --git a/website/src/components/FeatureCard/index.tsx b/website/src/components/FeatureCard/index.tsx index 9b13ba6970..de3ab92b73 100644 --- a/website/src/components/FeatureCard/index.tsx +++ b/website/src/components/FeatureCard/index.tsx @@ -3,11 +3,12 @@ import Link from '@docusaurus/Link'; import { IconArrow } from '@coderline/alphatab-ui'; import styles from './styles.module.scss'; -export type Platform = 'web' | 'net' | 'android'; +export type Platform = 'web' | 'net' | 'kotlin' | 'android'; const PLATFORM_LABEL: Record = { web: 'Web', net: '.NET', + kotlin: 'Kotlin', android: 'Android', }; diff --git a/website/src/components/FeatureChapterGrid/index.tsx b/website/src/components/FeatureChapterGrid/index.tsx index 1139887158..cbfc67c3c1 100644 --- a/website/src/components/FeatureChapterGrid/index.tsx +++ b/website/src/components/FeatureChapterGrid/index.tsx @@ -15,7 +15,7 @@ * sidebar_custom_props: * feature_chapter: layout # required — chapter id from _chapters.ts * since: "1.3" # optional — small "since" pill on the card - * feature_platforms: [web, net, android] # optional — platform pills; omit for "all" + * feature_platforms: [web, net, kotlin] # optional — platform pills; omit for "all" * feature_accent: violet # optional — accent colour override * feature_hook: ... # optional — overrides description as hook * feature_order: 20 # optional — sort within chapter (asc) @@ -79,7 +79,7 @@ const KNOWN_ACCENTS: readonly CardAccent[] = [ 'slate', ]; -const KNOWN_PLATFORMS: readonly Platform[] = ['web', 'net', 'android']; +const KNOWN_PLATFORMS: readonly Platform[] = ['web', 'net', 'kotlin', 'android']; function normalizeAccent(v: unknown): CardAccent | undefined { return typeof v === 'string' && (KNOWN_ACCENTS as readonly string[]).includes(v) diff --git a/website/src/components/HomepageFeatures/index.tsx b/website/src/components/HomepageFeatures/index.tsx index 3d5694f00c..51f608b523 100644 --- a/website/src/components/HomepageFeatures/index.tsx +++ b/website/src/components/HomepageFeatures/index.tsx @@ -51,7 +51,7 @@ const FeatureList: FeatureItem[] = [ <> The core of alphaTab is designed to run with minimal external dependencies and on multiple platforms and runtime environments. From one central code base we provide - alphaTab for web based apps (JavaScript), apps using .net and Kotlin for Android. + alphaTab for web based apps (JavaScript), apps using .NET and Kotlin for the JVM and Android. Use alphaTab in your backend and frontend using your preferred technologies to build the app you want. ), diff --git a/website/src/components/PlatformBadges/index.tsx b/website/src/components/PlatformBadges/index.tsx index 7e7daaf887..77abd824fd 100644 --- a/website/src/components/PlatformBadges/index.tsx +++ b/website/src/components/PlatformBadges/index.tsx @@ -1,11 +1,12 @@ import React from 'react'; import styles from './styles.module.scss'; -export type Platform = 'web' | 'net' | 'android'; +export type Platform = 'web' | 'net' | 'kotlin' | 'android'; const LABELS: Record = { web: 'Web', net: '.NET', + kotlin: 'Kotlin', android: 'Android', }; @@ -15,7 +16,7 @@ export interface PlatformBadgesProps { } export const PlatformBadges: React.FC = ({ - platforms = ['web', 'net', 'android'], + platforms = ['web', 'net', 'kotlin'], children, }) => { return ( diff --git a/website/src/components/PropertyDescription/index.tsx b/website/src/components/PropertyDescription/index.tsx index c1fcf73bb7..7dd0166c5a 100644 --- a/website/src/components/PropertyDescription/index.tsx +++ b/website/src/components/PropertyDescription/index.tsx @@ -28,7 +28,7 @@ export const PropertyDescription: React.FC = ({ ))} {androidNames.map((n) => ( - + ))}
); diff --git a/website/src/components/landing/LandingFeatures/index.tsx b/website/src/components/landing/LandingFeatures/index.tsx index 6977a149f5..b80a499d7c 100644 --- a/website/src/components/landing/LandingFeatures/index.tsx +++ b/website/src/components/landing/LandingFeatures/index.tsx @@ -49,7 +49,7 @@ const CARDS: FeatureCard[] = [ { n: '06', t: 'Open core, three runtimes', - d: 'MPL-2.0 license. JavaScript for web, .NET for desktop and server, Kotlin for native Android.', + d: 'MPL-2.0 license. JavaScript for web, .NET for desktop and server, Kotlin for the JVM and native Android.', v: , }, ]; diff --git a/website/src/components/landing/LandingHero/index.tsx b/website/src/components/landing/LandingHero/index.tsx index 4b6183f78a..6cf4ca2288 100644 --- a/website/src/components/landing/LandingHero/index.tsx +++ b/website/src/components/landing/LandingHero/index.tsx @@ -16,7 +16,7 @@ export const LandingHero: React.FC = () => {

alphaTab renders interactive guitar tabs and sheet music from Guitar Pro, MusicXML, Capella, and the - built-in alphaTex syntax. One core, three runtimes — JavaScript, .NET, and Kotlin for Android. + built-in alphaTex syntax. One core, three runtimes — JavaScript, .NET, and Kotlin for the JVM and Android.

diff --git a/website/static/llms.txt b/website/static/llms.txt index d23737ffc9..b12dca0d08 100644 --- a/website/static/llms.txt +++ b/website/static/llms.txt @@ -1,12 +1,13 @@ # alphaTab -> alphaTab is an SDK for JavaScript, .NET, and Kotlin that renders and plays interactive music notation. It parses Guitar Pro, MusicXML, CapXML, and alphaTex files and produces engraved sheet music with playback in the browser, on the desktop, and on Android. +> alphaTab is an SDK for JavaScript, .NET, and Kotlin that renders and plays interactive music notation. It parses Guitar Pro, MusicXML, CapXML, and alphaTex files and produces engraved sheet music with playback in the browser, on the desktop, on the JVM, and on Android. -alphaTab is not a drop-in widget — it exposes an API you build your own score UI on top of. The four internal modules are the data model, importers, render engine, and audio engine. The documentation is organised as a concept page (introduction), platform-specific getting-started tracks for Web, .NET, and Android, a feature catalog grouped by capability, the alphaTex language reference, format and API references, and step-by-step tutorials. +alphaTab is not a drop-in widget — it exposes an API you build your own score UI on top of. The four internal modules are the data model, importers, render engine, and audio engine. The documentation is organised as a concept page (introduction), platform-specific getting-started tracks for Web, .NET, and Kotlin, a feature catalog grouped by capability, the alphaTex language reference, format and API references, and step-by-step tutorials. ## Introduction - [Introduction](https://alphatab.net/docs/introduction): overview of alphaTab, its four internal modules, and the three supported platforms. +- [Platforms and packages](https://alphatab.net/docs/platforms): the alphaTab packages for Web, .NET and Kotlin, what each one contains, and where it runs. - [Documentation style guide](https://alphatab.net/docs/style-guide): voice, structure, and code-sample rules every doc page follows. - [Contributing](https://alphatab.net/docs/contributing): how to contribute code, docs, and bug reports. @@ -29,9 +30,9 @@ alphaTab is not a drop-in widget — it exposes an API you build your own score - [Installation (.NET)](https://alphatab.net/docs/getting-started/installation-net): install AlphaTab or AlphaTab.Windows from NuGet, render from console, WPF, or WinForms. - [Configuration (.NET)](https://alphatab.net/docs/getting-started/configuration-net): set up the API on your host, pass settings, subscribe to events, drive playback from C#. -## Getting Started (Android) +## Getting Started (Kotlin) -- [Installation (Android)](https://alphatab.net/docs/getting-started/installation-android): install from Maven Central and render music notation with AlphaTabView. +- [Installation (Kotlin)](https://alphatab.net/docs/getting-started/installation-kotlin): install alphaTab from Maven Central, then render music notation on any JVM or in an Android app. - [Configuration (Android)](https://alphatab.net/docs/getting-started/configuration-android): access the API, pass settings, subscribe to events, drive playback from Kotlin. ## Features @@ -67,12 +68,12 @@ alphaTab is not a drop-in widget — it exposes an API you build your own score - [Multi-track and grand staff](https://alphatab.net/docs/features/render/multi-track-rendering): Piano grand staff, multi-track rendering, multiple tunings displayed. - [SVG rendering](https://alphatab.net/docs/features/render/svg-output): Vector output, scaling, print, when to reach for it. - [HTML5 Canvas](https://alphatab.net/docs/features/render/html5-canvas): Raster output, HighDPI awareness, when it's the right choice. -- [Skia rendering (.NET / Android)](https://alphatab.net/docs/features/render/skia-backend): Native rendering via alphaSkia. +- [Skia rendering (.NET / Kotlin)](https://alphatab.net/docs/features/render/skia-backend): Native rendering via alphaSkia. - [Node.js headless rendering](https://alphatab.net/docs/features/render/nodejs-headless-rendering): Server-side image rendering. - [Choosing a backend](https://alphatab.net/docs/features/render/choosing-a-backend): Decision guide comparing SVG / Canvas / Skia. - [Bravura and SMuFL](https://alphatab.net/docs/features/render/bravura-default): The default music font, why SMuFL matters. - [Using a custom music font](https://alphatab.net/docs/features/render/custom-smufl-fonts): Swap Bravura for Petaluma or Leland, live demo. -- [Custom fonts on Skia](https://alphatab.net/docs/features/render/custom-fonts-on-skia): Register any font with the Skia rendering backend used on .NET and Android via Environment.registerAlphaSkiaCustomFont. +- [Custom fonts on Skia](https://alphatab.net/docs/features/render/custom-fonts-on-skia): Register any font with the Skia rendering backend used on .NET and Kotlin via Environment.registerAlphaSkiaCustomFont. - [Custom text fonts](https://alphatab.net/docs/features/render/custom-text-fonts): Configure title / subtitle / lyrics / chord / effect / marker fonts. - [Font family fallbacks](https://alphatab.net/docs/features/render/font-family-fallbacks): Multiple families with graceful fallback. - [Hiding dynamics](https://alphatab.net/docs/features/render/hide-dynamics): Score-wide dynamics visibility, live toggle. From 1c9f43a33a44dbe28bca5cfd49442e66293e52b5 Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Sun, 8 Nov 2026 00:57:50 +0100 Subject: [PATCH 4/5] fix(website): show the case-correct Maven artifact in the landing install snippet Maven coordinates are case-sensitive; net.alphatab:alphatab does not resolve, the artifact is net.alphatab:alphaTab. --- website/src/components/landing/LandingCta/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/src/components/landing/LandingCta/index.tsx b/website/src/components/landing/LandingCta/index.tsx index b6a6435d3b..131a0d0db8 100644 --- a/website/src/components/landing/LandingCta/index.tsx +++ b/website/src/components/landing/LandingCta/index.tsx @@ -17,7 +17,7 @@ export const LandingCta: React.FC = () => { const installs: Install[] = [ { platform: 'JavaScript', cmd: 'npm i @coderline/alphatab' }, { platform: '.NET', cmd: 'dotnet add package AlphaTab' }, - { platform: 'Kotlin', cmd: `implementation("net.alphatab:alphatab:${version}")` }, + { platform: 'Kotlin', cmd: `implementation("net.alphatab:alphaTab:${version}")` }, ]; return ( From 928cc18f1a702e3d39ba9cdd3d1cd15935dee87b Mon Sep 17 00:00:00 2001 From: Danielku15 Date: Sun, 8 Nov 2026 01:01:44 +0100 Subject: [PATCH 5/5] docs(website): fill install snippets with the versions the site is built for The .NET and Kotlin install pages hard-coded package versions, which went stale (the .NET page still showed 1.6.1). A remark plugin now replaces {{alphaTabVersion}} and {{alphaSkiaVersion}} in code blocks and inline code: the alphaTab version is the one the navbar and landing page show, the alphaSkia version is read from the Kotlin version catalog that alphaTab-core depends on. A leading backslash keeps a placeholder literal. The MIDI events guide loads alphaTab from the @latest CDN tag like the other pages instead of the @alpha pre-release tag. The style guide documents the placeholders. --- .../getting-started/installation-kotlin.mdx | 18 +++++------ .../docs/getting-started/installation-net.mdx | 2 +- website/docs/guides/handling-midi-events.mdx | 8 ++--- website/docs/style-guide.md | 2 ++ website/docusaurus.config.mts | 10 ++++++ website/src/remark/version-placeholders.ts | 31 +++++++++++++++++++ 6 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 website/src/remark/version-placeholders.ts diff --git a/website/docs/getting-started/installation-kotlin.mdx b/website/docs/getting-started/installation-kotlin.mdx index 5cb7f43bf2..c7faf94c59 100644 --- a/website/docs/getting-started/installation-kotlin.mdx +++ b/website/docs/getting-started/installation-kotlin.mdx @@ -46,11 +46,11 @@ repositories { dependencies { // Android apps: - implementation("net.alphatab:alphaTab:1.10.0") + implementation("net.alphatab:alphaTab:{{alphaTabVersion}}") // JVM applications, with the native Skia library of the target OS: - // implementation("net.alphatab:alphaTab-core:1.10.0") - // implementation("net.alphatab:alphaSkia-linux:3.5.147") + // implementation("net.alphatab:alphaTab-core:{{alphaTabVersion}}") + // implementation("net.alphatab:alphaSkia-linux:{{alphaSkiaVersion}}") } ``` @@ -69,11 +69,11 @@ repositories { dependencies { // Android apps: - implementation "net.alphatab:alphaTab:1.10.0" + implementation "net.alphatab:alphaTab:{{alphaTabVersion}}" // JVM applications, with the native Skia library of the target OS: - // implementation "net.alphatab:alphaTab-core:1.10.0" - // implementation "net.alphatab:alphaSkia-linux:3.5.147" + // implementation "net.alphatab:alphaTab-core:{{alphaTabVersion}}" + // implementation "net.alphatab:alphaSkia-linux:{{alphaSkiaVersion}}" } ``` @@ -87,13 +87,13 @@ dependencies { net.alphatab alphaTab-core - 1.10.0 + {{alphaTabVersion}} net.alphatab alphaSkia-linux - 3.5.147 + {{alphaSkiaVersion}} @@ -104,7 +104,7 @@ dependencies { ## Render on the JVM {#render-on-the-jvm} -On a JVM, alphaTab renders through alphaSkia, which needs a native library per operating system: `net.alphatab:alphaSkia-windows`, `alphaSkia-linux` or `alphaSkia-macos`, with the entry points `AlphaSkiaWindows`, `AlphaSkiaLinux` and `AlphaSkiaMacOs`. Use the alphaSkia version that `alphaTab-core` depends on. +On a JVM, alphaTab renders through alphaSkia, which needs a native library per operating system: `net.alphatab:alphaSkia-windows`, `alphaSkia-linux` or `alphaSkia-macos`, with the entry points `AlphaSkiaWindows`, `AlphaSkiaLinux` and `AlphaSkiaMacOs`. Use alphaSkia `{{alphaSkiaVersion}}`, the version `alphaTab-core` depends on. alphaSkia also needs the Bravura music font. It ships as `dist/font/Bravura.otf` in the [`@coderline/alphatab`](https://www.npmjs.com/package/@coderline/alphatab) npm package. diff --git a/website/docs/getting-started/installation-net.mdx b/website/docs/getting-started/installation-net.mdx index 3ef0ecee90..98cb38aee5 100644 --- a/website/docs/getting-started/installation-net.mdx +++ b/website/docs/getting-started/installation-net.mdx @@ -32,7 +32,7 @@ Or add the reference directly to your `.csproj`: ```xml - + ``` diff --git a/website/docs/guides/handling-midi-events.mdx b/website/docs/guides/handling-midi-events.mdx index dea401e719..55f00fa8d9 100644 --- a/website/docs/guides/handling-midi-events.mdx +++ b/website/docs/guides/handling-midi-events.mdx @@ -71,7 +71,7 @@ From this starting point we will be adding the logic. - +