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/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/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/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 73% rename from packages/kotlin/src/android/src/main/java/alphaTab/EnvironmentPartials.kt rename to packages/kotlin/src/core/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/core/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/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 70% 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 index e468b9648c..b0e9914f40 100644 --- 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 @@ -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/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/android/JavaThreadWorkers.kt b/packages/kotlin/src/core/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/core/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/core/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 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.'); 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..c7faf94c59 --- /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:{{alphaTabVersion}}") + + // JVM applications, with the native Skia library of the target OS: + // implementation("net.alphatab:alphaTab-core:{{alphaTabVersion}}") + // implementation("net.alphatab:alphaSkia-linux:{{alphaSkiaVersion}}") +} +``` + + + + +```groovy +repositories { + google() + mavenCentral() + // Pre-release snapshots: + // maven { + // url = "https://central.sonatype.com/repository/maven-snapshots/" + // } +} + +dependencies { + // Android apps: + implementation "net.alphatab:alphaTab:{{alphaTabVersion}}" + + // JVM applications, with the native Skia library of the target OS: + // implementation "net.alphatab:alphaTab-core:{{alphaTabVersion}}" + // implementation "net.alphatab:alphaSkia-linux:{{alphaSkiaVersion}}" +} +``` + + + + +```xml + + + + + net.alphatab + alphaTab-core + {{alphaTabVersion}} + + + + net.alphatab + alphaSkia-linux + {{alphaSkiaVersion}} + + + +``` + + + + +## 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 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. + +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/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. - +