Skip to content

termtate/kotlinosc

Repository files navigation

kotlinosc

Maven Central CI License

kotlinosc is a Kotlin/JVM OSC (Open Sound Control) library focused on:

  • OSC packet codec (OscMessage, OscBundle)
  • OSC address pattern matching and routing
  • UDP and TCP server/client runtime
  • Kotlin-friendly DSL for server/client and bundle construction

This library currently implements OSC 1.0-compatible packet/data behavior.

Features

  • Lightweight: runtime dependency is only kotlin-logging.
  • Broad unit-test coverage.

Current Status

  • Latest release is available on Maven Central.
  • Public API is guarded by binary-compatibility checks (apiCheck / apiDump).
  • Maven Central + GitHub Release automation is configured via GitHub Actions (tag-triggered release).

Installation

Available on Maven Central.

Gradle (Kotlin DSL)

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.termtate.kotlinosc:kotlinosc:0.3.0")
}

Gradle (Groovy DSL)

repositories {
    mavenCentral()
}

dependencies {
    implementation 'io.github.termtate.kotlinosc:kotlinosc:0.3.0'
}

Maven

<dependency>
  <groupId>io.github.termtate.kotlinosc</groupId>
  <artifactId>kotlinosc</artifactId>
  <version>0.3.0</version>
</dependency>

Build And Test

./gradlew test
./gradlew apiCheck

On Windows:

.\gradlew.bat test
.\gradlew.bat apiCheck

Quick Start

Build an OSC message

import io.github.termtate.kotlinosc.type.OscMessage
import io.github.termtate.kotlinosc.type.invoke

val msg = OscMessage("/synth/freq", 440, 0.8f, "lead")

Build an OSC bundle (DSL)

import io.github.termtate.kotlinosc.arg.OscTimetag
import io.github.termtate.kotlinosc.type.oscBundle

val bundle = oscBundle(OscTimetag.IMMEDIATELY) {
    message("/a", 1, 2.0f, "x")
    bundle {
        message("/b", true)
    }
}

Encode and decode an OSC packet

import io.github.termtate.kotlinosc.codec.decodeFromByteArray
import io.github.termtate.kotlinosc.codec.encodeToByteArray
import io.github.termtate.kotlinosc.type.OscMessage
import io.github.termtate.kotlinosc.type.OscPacket
import io.github.termtate.kotlinosc.type.invoke

val message = OscMessage("/ping", "hello", 123)
val bytes = message.encodeToByteArray()
val decoded = OscPacket.decodeFromByteArray(bytes)

Start a server with DSL

import io.github.termtate.kotlinosc.transport.dsl.oscServer

val server = oscServer("127.0.0.1", 9000) {
    route {
        on("/ping") { message ->
            println("received: ${message.address}")
        }
    }
}

server.startAsync()
// ...
server.stop()

Send with client DSL

import io.github.termtate.kotlinosc.transport.dsl.oscClient
import io.github.termtate.kotlinosc.type.OscMessage

val client = oscClient("127.0.0.1", 9000)
client.send(OscMessage("/ping"))
client.closeAndJoin()

UDP is the default transport for both oscServer and oscClient.

Use TCP transport

TCP transport sends OSC packets over a persistent connection. Because TCP is a byte stream, client and server must use the same framing strategy. The default TCP framing strategy is LENGTH_PREFIXED.

import io.github.termtate.kotlinosc.transport.dsl.oscClient
import io.github.termtate.kotlinosc.transport.dsl.oscServer
import io.github.termtate.kotlinosc.type.OscMessage
import kotlinx.coroutines.runBlocking

runBlocking {
    val server = oscServer("127.0.0.1", 9000) {
        protocol { tcp() }
        route {
            on("/ping") { message ->
                println("received over TCP: ${message.address}")
            }
        }
    }

    val client = oscClient("127.0.0.1", 9000) {
        protocol { tcp() }
    }

    try {
        server.start()
        client.send(OscMessage("/ping"))
    } finally {
        client.closeAndJoin()
        server.stop()
    }
}

Use TCP SLIP framing

import io.github.termtate.kotlinosc.transport.dsl.oscClient
import io.github.termtate.kotlinosc.transport.dsl.oscServer
import io.github.termtate.kotlinosc.transport.tcp.codec.OscTcpFramingStrategy

val server = oscServer("127.0.0.1", 9000) {
    protocol {
        tcp {
            framingStrategy = OscTcpFramingStrategy.SLIP
        }
    }
}

val client = oscClient("127.0.0.1", 9000) {
    protocol {
        tcp {
            framingStrategy = OscTcpFramingStrategy.SLIP
        }
    }
}

Documentation

Publishing Setup

Publishing infrastructure is configured for Maven Central (Portal) with signing.

Before publishing, provide credentials in ~/.gradle/gradle.properties or CI secrets:

mavenCentralUsername=...
mavenCentralPassword=...
signingInMemoryKey=...
signingInMemoryKeyPassword=...

Validation commands:

./gradlew apiCheck
./gradlew publishToMavenLocal

Release publishing command (enables signing):

./gradlew publishToMavenCentral -Prelease

GitHub Actions release flow:

  • Push a tag like v<version>
  • Workflow publishes artifacts to Maven Central
  • Workflow creates GitHub Release notes from CHANGELOG.md

License

MIT. See LICENSE.

About

Kotlin/JVM OSC (Open Sound Control) library with codec, routing, transport, and DSL support.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors