Skip to content

Commit

Permalink
switch to rtmidi-javacpp from rtmidi-jna.
Browse files Browse the repository at this point in the history
JavaCPP is a maintained native-interop technology that we can resort to in 2023.

Due to weird build breakage on Maven package solution, rtmidi-javacpp is
submoduled and referenced as a local project module.

(I guess it is equivalent to atsushieno/aap-core#174)
  • Loading branch information
atsushieno committed Dec 7, 2023
1 parent 618ed57 commit 238e131
Show file tree
Hide file tree
Showing 10 changed files with 52 additions and 61 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "external/rtmidi"]
path = external/rtmidi
url = https://github.com/thestk/rtmidi.git
[submodule "external/rtmidi-javacpp"]
path = external/rtmidi-javacpp
url = https://github.com/atsushieno/rtmidi-javacpp.git
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ plugins {
id "org.jetbrains.kotlin.jvm" version "1.8.22" apply false
id "com.android.library" version "7.4.2" apply false
id "org.jetbrains.dokka" version "1.8.20" apply false
id 'org.bytedeco.gradle-javacpp-build' version "1.5.9" apply false
id 'org.bytedeco.gradle-javacpp-platform' version '1.5.9' apply false
}

allprojects {
Expand Down
1 change: 1 addition & 0 deletions external/rtmidi-javacpp
Submodule rtmidi-javacpp added at 247721
12 changes: 6 additions & 6 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
[versions]
alsakt = "0.3.4"
core-ktx = "1.10.1"
jna = "5.12.1"
jnaerator-runtime = "0.12"
junit = "4.13.2"
junit-jupiter-api = "5.9.0"
kotlin-test-junit = "1.9.0"
kotlinx-coroutines-core = "1.7.0"
kotlinx-datetime = "0.4.0"
ktor-io = "2.3.2"
metalava-gradle = "0.2.3"
rtmidi-jna = "0.1.3"
rtmidi-javacpp = "0.1.2"

[libraries]
alsakt = { module = "dev.atsushieno:alsakt", version.ref = "alsakt" }
core-ktx = { module = "androidx.core:core-ktx", version.ref = "core-ktx" }
jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
jnaerator-runtime = { module = "com.nativelibs4java:jnaerator-runtime", version.ref = "jnaerator-runtime" }
junit = { module = "junit:junit", version.ref = "junit" }
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter-api" }
junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter-api" }
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin-test-junit" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines-core" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
ktor-io = { module = "io.ktor:ktor-io", version.ref = "ktor-io" }
metalava-gradle = { module = "me.tylerbwong.gradle:metalava-gradle", version.ref = "metalava-gradle" }
rtmidi-jna = { module = "dev.atsushieno:rtmidi-jna", version.ref = "rtmidi-jna" }
rtmidi-javacpp = { module = "dev.atsushieno:rtmidi-javacpp", version.ref = "rtmidi-javacpp" }
rtmidi-javacpp-platform = { module = "dev.atsushieno:rtmidi-javacpp-platform", version.ref = "rtmidi-javacpp" }

[plugins]

Expand Down
6 changes: 3 additions & 3 deletions input-sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ plugins {
}

dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
implementation libs.kotlinx.coroutines.core
implementation project(":ktmidi")
implementation project(":ktmidi-jvm-desktop")
testImplementation "org.junit.jupiter:junit-jupiter-api:5.9.0"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.9.0"
testImplementation libs.junit.jupiter.api
testRuntimeOnly libs.junit.jupiter.engine
}

mainClassName = "dev.atsushieno.ktmidi.samples.inputsample.InputSampleKt"
Expand Down
17 changes: 4 additions & 13 deletions ktmidi-jvm-desktop/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ plugins {
id 'org.jetbrains.kotlin.jvm'
id 'maven-publish'
id 'signing'
id "org.bytedeco.gradle-javacpp-platform" version "1.5.9"
}

dependencies {
implementation project(":ktmidi")
implementation libs.alsakt
implementation libs.rtmidi.jna
implementation libs.jna
implementation libs.jnaerator.runtime
//implementation libs.rtmidi.javacpp
//implementation libs.rtmidi.javacpp.platform
implementation project(":rtmidi-javacpp")

implementation libs.kotlinx.coroutines.core
implementation libs.kotlinx.datetime
Expand Down Expand Up @@ -80,16 +81,6 @@ afterEvaluate {
}

repositories {
/*
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/atsushieno/ktmidi")
credentials {
username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
}
}
*/
maven {
name = "OSSRH"
url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package dev.atsushieno.ktmidi

import dev.atsushieno.rtmidi_javacpp.RtMidiCCallback
import org.bytedeco.javacpp.BytePointer
import java.nio.ByteBuffer
import java.nio.IntBuffer
import com.ochafik.lang.jnaerator.runtime.NativeSize
import com.sun.jna.Pointer
import dev.atsushieno.rtmidijna.RtMidiWrapper
import dev.atsushieno.rtmidijna.RtmidiLibrary
import dev.atsushieno.rtmidijna.RtmidiLibrary.RtMidiCCallback
import kotlinx.coroutines.yield
import org.bytedeco.javacpp.IntPointer
import org.bytedeco.javacpp.Pointer

import dev.atsushieno.rtmidi_javacpp.global.RtMidi as library

class RtMidiAccess() : MidiAccess() {
companion object {
private val library = RtmidiLibrary.INSTANCE

internal fun getPortName(rtmidi: RtMidiWrapper, index: Int) : String {
internal fun getPortName(rtmidi: Pointer, index: Int) : String {
val lenArr = intArrayOf(0)
val len = IntBuffer.wrap(lenArr)
if (library.rtmidi_get_port_name(rtmidi, index, null, len) < 0)
Expand Down Expand Up @@ -58,8 +57,8 @@ class RtMidiAccess() : MidiAccess() {

override val canCreateVirtualPort: Boolean
get() = when(library.rtmidi_out_get_current_api(library.rtmidi_out_create_default())) {
RtmidiLibrary.RtMidiApi.RTMIDI_API_LINUX_ALSA,
RtmidiLibrary.RtMidiApi.RTMIDI_API_MACOSX_CORE -> true
library.RTMIDI_API_LINUX_ALSA,
library.RTMIDI_API_MACOSX_CORE -> true
else -> false
}

Expand All @@ -81,21 +80,23 @@ class RtMidiAccess() : MidiAccess() {
abstract override fun close()
}

internal class RtMidiInputHandler(private val rtmidi: RtMidiWrapper) {
internal class RtMidiInputHandler(rtmidi: Pointer/*RtMidiInPtr*/) {
private var listener: OnMidiReceivedEventListener? = null

fun setMessageReceivedListener(listener: OnMidiReceivedEventListener) {
this.listener = listener
}

private fun onRtMidiMessage(timestamp: Double, message: Pointer, messageSize: NativeSize) {
listener?.onEventReceived(message.getByteArray(0, messageSize.toInt()), 0, messageSize.toInt(), (timestamp * 1_000_000_000).toLong())
private fun onRtMidiMessage(timestamp: Double, message: Pointer, messageSize: Long) {
val array = ByteArray(messageSize.toInt())
message.asByteBuffer().get(array)
listener?.onEventReceived(array, 0, messageSize.toInt(), (timestamp * 1_000_000_000).toLong())
}

class RtMidiAccessInputCallback(val owner: RtMidiInputHandler) : RtMidiCCallback {
class RtMidiAccessInputCallback(val owner: RtMidiInputHandler) : RtMidiCCallback() {

override fun apply(timeStamp: Double, message: Pointer?, messageSize: NativeSize?, userData: Pointer?) {
owner.onRtMidiMessage(timeStamp, message!!, messageSize!!)
override fun call(timeStamp: Double, message: BytePointer?, messageSize: Long, userData: Pointer?) {
owner.onRtMidiMessage(timeStamp, message!!, messageSize)
}
}

Expand All @@ -104,12 +105,12 @@ class RtMidiAccess() : MidiAccess() {
init {
library.rtmidi_in_set_callback(rtmidi,
callback,
Pointer.NULL)
IntPointer())
library.rtmidi_in_ignore_types(
rtmidi,
0,
1,
1,
false,
true,
true,
)
}
}
Expand Down Expand Up @@ -160,30 +161,19 @@ class RtMidiAccess() : MidiAccess() {
// Virtual ports

internal class RtMidiVirtualPortDetails(context: PortCreatorContext) : MidiPortDetails {
override val id: String
override val manufacturer: String
override val name: String
override val version: String

init {
id = context.portName
name = context.portName
manufacturer = context.manufacturer
version = context.version
}
override val id: String = context.portName
override val manufacturer: String = context.manufacturer
override val name: String = context.portName
override val version: String = context.version
}

internal abstract class RtMidiVirtualPort(context: PortCreatorContext) : MidiPort {
private val detailsImpl: MidiPortDetails
private val detailsImpl: MidiPortDetails = RtMidiVirtualPortDetails(context)

override val details: MidiPortDetails
get() = detailsImpl

override var midiProtocol: Int = 0

init {
detailsImpl = RtMidiVirtualPortDetails(context)
}
}

internal class RtMidiVirtualInput(context: PortCreatorContext) : MidiInput, RtMidiVirtualPort(context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class RtMidiAccessTest {
println("Test rtMidiAccessInfo() is skipped on GitHub Actions as ALSA is unavailable.")
return
}
// it does not work on M1 mac and arm64 Linux either
// it does not work on M1 mac and arm64 Linux either (lack of deps)
if (System.getProperty("os.arch") == "aarch64") {
println("Test rtMidiAccessInfo() is skipped as rtmidi-jna aarch64 builds are not available.")
return
Expand Down
4 changes: 2 additions & 2 deletions publish-root.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Create variables with empty default values
ext["ossrhUsername"] = ''
ext["ossrhPassword"] = ''
ext["sonatypeStagingProfileId"] = ''
ext["ossrhStagingRepositoryId"] = ''
ext["signing.keyId"] = ''
ext["signing.password"] = ''
ext["signing.secretKeyRingFile"] = ''
Expand All @@ -17,7 +17,7 @@ if (secretPropsFile.exists()) {
// Use system environment variables
ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') ?: ext["ossrhUsername"]
ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') ?: ext["ossrhPassword"]
ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID') ?: ext["sonatypeStagingProfileId"]
ext["ossrhStagingRepositoryId"] = System.getenv('OSSRH_STAGING_REPOSITORY_ID') ?: ext["ossrhStagingRepositoryId"]
ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') ?: ext["signing.keyId"]
ext["signing.password"] = System.getenv('SIGNING_PASSWORD') ?: ext["signing.password"]
ext["signing.secretKeyRingFile"] = System.getenv('SIGNING_SECRET_KEY_RING_FILE') ?: ext["signing.secretKeyRingFile"]
Expand Down
4 changes: 4 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ include(":input-sample")
include(":player-sample-lib")
include(":player-sample")
include(":player-sample-native")

include(":rtmidi-javacpp")
project(":rtmidi-javacpp").projectDir = new File("external/rtmidi-javacpp/rtmidi-javacpp")
gradle.rootProject { ext.javacppVersion = '1.5.8' }

0 comments on commit 238e131

Please sign in to comment.