Skip to content

Commit 39a36fb

Browse files
committed
WIP
1 parent 75b1340 commit 39a36fb

File tree

30 files changed

+417
-321
lines changed

30 files changed

+417
-321
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package baaahs.rpc
2+
3+
import kotlin.coroutines.CoroutineContext
4+
5+
public class RpcClientId(public val id: String) : CoroutineContext.Element {
6+
override val key: CoroutineContext.Key<*>
7+
get() = Key
8+
9+
public companion object Key : CoroutineContext.Key<RpcClientId>
10+
}

rpc/src/commonMain/kotlin/baaahs/rpc/RpcImpl.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package baaahs.rpc
33
import kotlinx.serialization.KSerializer
44
import kotlinx.serialization.json.Json
55
import kotlinx.serialization.modules.SerializersModule
6+
import kotlin.coroutines.coroutineContext
67

78
public class CommandPort<C, R>(
89
public val name: String,
@@ -34,7 +35,12 @@ public interface RpcCommandChannel<C, R> {
3435
public suspend fun send(command: C): R
3536
}
3637

37-
public interface RpcClient : RpcEndpoint, RpcCommandRecipient
38+
public interface RpcClient : RpcEndpoint, RpcCommandRecipient {
39+
public companion object {
40+
public suspend fun id(): String =
41+
coroutineContext[RpcClientId]?.id ?: error("not in RPC call")
42+
}
43+
}
3844

3945
public interface RpcServer : RpcEndpoint
4046

src/commonMain/kotlin/baaahs/PubSub.kt

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import kotlinx.serialization.builtins.ListSerializer
1212
import kotlinx.serialization.json.Json
1313
import kotlinx.serialization.json.JsonElement
1414
import kotlinx.serialization.modules.SerializersModule
15+
import kotlin.coroutines.EmptyCoroutineContext
1516
import kotlin.js.JsName
1617
import kotlin.jvm.Synchronized
1718
import kotlin.properties.ReadWriteProperty
@@ -33,7 +34,8 @@ abstract class PubSub {
3334
val logger = Logger<PubSub>()
3435
}
3536

36-
open class Origin(val id: String) {
37+
open class Origin(val id: String, clientId: String?) {
38+
val clientId = clientId?.let { RpcClientId(it) }
3739
override fun toString(): String = "Origin($id)"
3840
}
3941

@@ -212,7 +214,9 @@ abstract class PubSub {
212214
val name = commandPort.name
213215
if (hasServerChannel(name)) error("Command channel $name already exists.")
214216
putServerChannel(name,
215-
ServerCommandChannel(commandPort) { command -> callback(command) })
217+
ServerCommandChannel(commandPort) { command ->
218+
callback(command)
219+
})
216220
}
217221

218222
class ServerCommandChannel<C, R>(
@@ -225,7 +229,7 @@ abstract class PubSub {
225229
fromConnection: Connection,
226230
handlerScope: CoroutineScope
227231
) {
228-
handlerScope.launch {
232+
handlerScope.launch(fromConnection.clientId ?: EmptyCoroutineContext) {
229233
try {
230234
val command = commandPort.fromJson(commandJson)
231235
val reply = callback.invoke(command)
@@ -271,7 +275,7 @@ abstract class PubSub {
271275
private val topics: Topics,
272276
private val commandChannels: CommandChannels,
273277
private val handlerScope: CoroutineScope
274-
) : Origin("connection $name"), Network.WebSocketListener {
278+
) : Origin("connection $name", name), Network.WebSocketListener {
275279
var isConnected: Boolean = false
276280
var everConnected: Boolean = false
277281

@@ -523,14 +527,19 @@ abstract class PubSub {
523527
httpServer: Network.HttpServer,
524528
private val handlerScope: CoroutineScope
525529
) : Endpoint(), IServer, RpcEndpoint {
526-
private val publisher = Origin("Server-side publisher")
530+
private val publisher = Origin("Server-side publisher", null)
527531
private val topics: Topics = Topics()
528532
override val commandChannels: CommandChannels = CommandChannels()
529533
private val connectionListeners: MutableList<(ConnectionFromClient) -> Unit> = mutableListOf()
534+
private val connectionCountByHost = hashMapOf<String, Int>()
530535

531536
init {
532537
httpServer.listenWebSocket("/sm/ws") { incomingConnection ->
533-
val name = "server ${incomingConnection.toAddress} to ${incomingConnection.fromAddress}"
538+
val fromAddress = incomingConnection.fromAddress.toString()
539+
val number = connectionCountByHost[fromAddress] ?: 0
540+
connectionCountByHost[fromAddress] = number + 1
541+
542+
val name = "${incomingConnection.fromAddress}${if (number > 0) "-$number" else ""}"
534543
ConnectionFromClient(name, topics, commandChannels, handlerScope)
535544
.also { connection -> connectionListeners.forEach { it.invoke(connection) } }
536545
}
@@ -664,7 +673,7 @@ abstract class PubSub {
664673

665674
@JsName("subscribe")
666675
fun <T> subscribe(topic: Topic<T>, onUpdateFn: (T) -> Unit): Channel<T> {
667-
val subscriber = Origin("Client-side subscriber at ${link.myAddress}")
676+
val subscriber = Origin("Client-side subscriber at ${link.myAddress}", link.myAddress.toString())
668677

669678
val topicName = topic.name
670679

src/commonMain/kotlin/baaahs/client/ClientStageManager.kt

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package baaahs.client
22

33
import baaahs.*
44
import baaahs.gl.Toolchain
5-
import baaahs.midi.MidiDevices
65
import baaahs.scene.OpenScene
76
import baaahs.scene.SceneProvider
87
import baaahs.show.Feed
@@ -22,7 +21,6 @@ class ClientStageManager(
2221
toolchain: Toolchain,
2322
private val pubSub: PubSub.Client,
2423
sceneProvider: SceneProvider,
25-
private val midiDevices: MidiDevices,
2624
private val coroutineScope: CoroutineScope = GlobalScope
2725
) : BaseShowPlayer(toolchain, SceneProviderWithFallback(sceneProvider)) {
2826
private val gadgets: MutableMap<String, ClientGadget> = mutableMapOf()
@@ -34,16 +32,6 @@ class ClientStageManager(
3432
private val showControlCommands = ShowControlCommands.IMPL
3533
.createSender(pubSub)
3634

37-
init {
38-
globalLaunch {
39-
midiDevices.listTransmitters().forEach { midiTransmitter ->
40-
midiTransmitter.listen { midiMessage ->
41-
println("MIDI from ${midiTransmitter.id}: $midiMessage")
42-
}
43-
}
44-
}
45-
}
46-
4735
private fun checkForChanges() {
4836
listeners.forEach { it.onPatchSetChanged() }
4937
}

src/commonMain/kotlin/baaahs/di/Modules.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ interface PinkyModule : KModule {
136136
scoped { GadgetManager(get(), get(), get(Named.pinkyContext)) }
137137
scoped<Toolchain> { RootToolchain(get()) }
138138
scoped { PinkyConfigStore(get(), fs.resolve(".")) }
139-
scoped { EventManager(get(), get(), get()) }
140-
scoped { StageManager(get(), get(), get(), get(Named.dataDir), get(), get(), get(), get(), get(), get(), get()) }
139+
scoped { EventManager(get(), get<PubSub.Server>(), get()) }
140+
scoped { StageManager(get(), get(), get(), get(Named.dataDir), get(), get(), get(), get(), get(), get(), get(), get()) }
141141
scoped { Pinky.NetworkStats() }
142142
scoped { BrainManager(get(), get(), get(), get(), get(Named.pinkyContext)) }
143143
scoped { SacnManager(get(), get(Named.pinkyContext), get(), get()) }
Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
package baaahs.midi
2-
3-
import baaahs.PubSub
4-
import baaahs.plugin.Plugins
5-
import kotlinx.serialization.builtins.ListSerializer
6-
import kotlinx.serialization.builtins.serializer
7-
8-
class MidiCommandPorts(plugins: Plugins) {
9-
val listTransmittersCommandPort = PubSub.CommandPort(
10-
"/midi/listTransmitters",
11-
RemoteMidiDevices.ListTransmittersCommand.serializer(),
12-
ListSerializer(RemoteMidiDevices.RemoteMidiDeviceInfo.serializer()),
13-
plugins.serialModule
14-
)
15-
val listenToTransmitterCommandPort = PubSub.CommandPort(
16-
"/midi/listenToTransmitter", RemoteMidiDevices.ListenToTransmitterCommand.serializer(), Unit.serializer(),
17-
plugins.serialModule
18-
)
19-
val midiEventCommandPort = PubSub.CommandPort(
20-
"/midi/event", RemoteMidiDevices.MidiEventCommand.serializer(), Unit.serializer(),
21-
plugins.serialModule
22-
)
23-
val closeTransmitterCommandPort = PubSub.CommandPort(
24-
"/midi/closeTransmitter", RemoteMidiDevices.CloseTransmitterCommand.serializer(), Unit.serializer(),
25-
plugins.serialModule
26-
)
27-
}
1+
//package baaahs.midi
2+
//
3+
//import baaahs.PubSub
4+
//import baaahs.plugin.Plugins
5+
//import kotlinx.serialization.builtins.ListSerializer
6+
//import kotlinx.serialization.builtins.serializer
7+
//
8+
//class MidiCommandPorts(plugins: Plugins) {
9+
// val listTransmittersCommandPort = PubSub.CommandPort(
10+
// "/midi/listTransmitters",
11+
// RemoteMidiDevices.ListTransmittersCommand.serializer(),
12+
// ListSerializer(RemoteMidiDevices.RemoteMidiDeviceInfo.serializer()),
13+
// plugins.serialModule
14+
// )
15+
// val listenToTransmitterCommandPort = PubSub.CommandPort(
16+
// "/midi/listenToTransmitter", RemoteMidiDevices.ListenToTransmitterCommand.serializer(), Unit.serializer(),
17+
// plugins.serialModule
18+
// )
19+
// val midiEventCommandPort = PubSub.CommandPort(
20+
// "/midi/event", RemoteMidiDevices.MidiEventCommand.serializer(), Unit.serializer(),
21+
// plugins.serialModule
22+
// )
23+
// val closeTransmitterCommandPort = PubSub.CommandPort(
24+
// "/midi/closeTransmitter", RemoteMidiDevices.CloseTransmitterCommand.serializer(), Unit.serializer(),
25+
// plugins.serialModule
26+
// )
27+
//}
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
package baaahs.midi
22

3+
import baaahs.rpc.Service
4+
5+
@Service
36
interface MidiDevices {
4-
suspend fun listTransmitters(): List<MidiTransmitter>
7+
suspend fun listTransmitters(): List<MidiPort>
8+
9+
companion object {
10+
val IMPL by lazy { MidiDevices.getImpl("pinky/midiDevices") }
11+
}
512
}
613

14+
//class MidiManager(
15+
// rpcEndpoint: RpcEndpoint
16+
//) : MidiDevices {
17+
// val midiDevicesService = MidiDevices.IMPL.createReceiver(rpcEndpoint, object : MidiDevices {
18+
// override suspend fun listTransmitters(): List<MidiPort> {
19+
// TODO("not implemented")
20+
// }
21+
// })
22+
//}
723
class NullMidiDevices : MidiDevices {
8-
override suspend fun listTransmitters(): List<MidiTransmitter> = emptyList()
24+
override suspend fun listTransmitters(): List<MidiPort> = emptyList()
925
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package baaahs.midi
2+
3+
import baaahs.rpc.Service
4+
import kotlinx.coroutines.CoroutineScope
5+
import kotlinx.coroutines.launch
6+
import kotlinx.datetime.Instant
7+
import kotlinx.serialization.Serializable
8+
9+
@Service
10+
interface MidiGatewayApi {
11+
suspend fun deviceOnline(midiDeviceId: Int, midiDevice: MidiDevice)
12+
suspend fun receivedEvent(midiDeviceId: Int, midiEvent: MidiEvent)
13+
suspend fun deviceOffline(midiDeviceId: Int)
14+
15+
companion object {
16+
val IMPL by lazy { MidiGateway.getImpl("pinky/midiGateway") }
17+
}
18+
}
19+
20+
@Service
21+
interface MidiGateway {
22+
suspend fun receivedEvent(midiDevice: MidiDevice, midiEvent: MidiEvent)
23+
suspend fun deviceOffline(midiDevice: MidiDevice)
24+
25+
companion object {
26+
val IMPL by lazy { MidiGateway.getImpl("pinky/midiGateway") }
27+
}
28+
}
29+
30+
class MidiGatewayServer : MidiGateway {
31+
override suspend fun receivedEvent(midiDevice: MidiDevice, midiEvent: MidiEvent) {
32+
TODO("not implemented")
33+
}
34+
35+
override suspend fun deviceOffline(midiDevice: MidiDevice) {
36+
TODO("not implemented")
37+
}
38+
}
39+
40+
class MidiGatewayClient(
41+
private val midiGateway: MidiGateway,
42+
private val scope: CoroutineScope
43+
) {
44+
fun receivedEvent(midiDevice: MidiDevice, midiEvent: MidiEvent) {
45+
scope.launch {
46+
midiGateway.receivedEvent(midiDevice, midiEvent)
47+
}
48+
}
49+
}
50+
51+
@Serializable
52+
data class MidiDevice(
53+
val id: String,
54+
val name: String,
55+
val vendor: String,
56+
val description: String,
57+
val version: String
58+
)
59+
60+
@Serializable
61+
data class MidiEvent(
62+
val instant: Instant,
63+
val channel: Int,
64+
val command: Int,
65+
val data1: Int,
66+
val data2: Int
67+
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package baaahs.midi
2+
3+
interface MidiPort

src/commonMain/kotlin/baaahs/midi/MidiTransmitter.kt

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)