package nl.astraeus.vst.chip.view import daw.style.Css import daw.style.Css.defineCss import daw.style.Css.noTextSelect import daw.style.CssId import daw.style.CssName import daw.style.hover import kotlinx.browser.window import kotlinx.html.InputType import kotlinx.html.div import kotlinx.html.h1 import kotlinx.html.input import kotlinx.html.js.onChangeFunction import kotlinx.html.js.onClickFunction import kotlinx.html.option import kotlinx.html.select import kotlinx.html.span import nl.astraeus.css.properties.BoxSizing import nl.astraeus.css.properties.FontWeight import nl.astraeus.css.properties.Position import nl.astraeus.css.properties.Transform import nl.astraeus.css.properties.em import nl.astraeus.css.properties.hsla import nl.astraeus.css.properties.prc import nl.astraeus.css.properties.px import nl.astraeus.css.properties.rem import nl.astraeus.css.properties.vh import nl.astraeus.css.properties.vw import nl.astraeus.css.style.cls import nl.astraeus.komp.HtmlBuilder import nl.astraeus.komp.Komponent import nl.astraeus.vst.chip.audio.VstChipWorklet import nl.astraeus.vst.chip.midi.Midi import org.khronos.webgl.Uint8Array import org.w3c.dom.HTMLInputElement import org.w3c.dom.HTMLSelectElement object MainView : Komponent() { private var messages: MutableList = ArrayList() private var started = false init { MainViewCss } fun addMessage(message: String) { messages.add(message) while (messages.size > 10) { messages.removeAt(0) } requestUpdate() } override fun HtmlBuilder.render() { div(MainViewCss.MainDivCss.name) { if (!started) { div(MainViewCss.StartSplashCss.name) { div(MainViewCss.StartBoxCss.name) { div(MainViewCss.StartButtonCss.name) { +"START" onClickFunction = { started = true VstChipWorklet.create { requestUpdate() } } } } } } h1 { +"VST Chip" } div { span { +"Midi input: " select { option { +"None" value = "" } option { +"Midi over Broadcast" value = "midi-broadcast" } for (mi in Midi.inputs) { option { +mi.name value = mi.id } } onChangeFunction = { event -> val target = event.target as HTMLSelectElement if (target.value == "") { Midi.setInput(null) } else { val selected = Midi.inputs.find { it.id == target.value } if (selected != null) { Midi.setInput(selected) } else if (target.value == "midi-broadcast") { // } } } } } span { +"channel:" input { type = InputType.number value = Midi.inputChannel.toString() onChangeFunction = { event -> val target = event.target as HTMLInputElement Midi.inputChannel = target.value.toInt() } } } } div { span { +"Midi output: " select { option { +"None" value = "" } option { +"Midi over Broadcast" value = "midi-broadcast" } for (mi in Midi.outputs) { option { +mi.name value = mi.id } } onChangeFunction = { event -> val target = event.target as HTMLSelectElement if (target.value == "") { Midi.setOutput(null) } else { val selected = Midi.outputs.find { it.id == target.value } if (selected != null) { Midi.setOutput(selected) } } } } } span { +"channel:" input { type = InputType.number value = Midi.outputChannel.toString() onChangeFunction = { event -> val target = event.target as HTMLInputElement Midi.outputChannel = target.value.toInt() } } } } div { +"Send note on to output" onClickFunction = { val data = Uint8Array( arrayOf( 0x90.toByte(), 0x3c.toByte(), 0x70.toByte() ) ) Midi.send(data, window.performance.now() + 1000) Midi.send(data, window.performance.now() + 2000) } } div { +"Send note off to output" onClickFunction = { val data = Uint8Array( arrayOf( 0x90.toByte(), 0x3c.toByte(), 0x0.toByte(), ) ) Midi.send(data) } } } } object MainViewCss : CssId("main") { object MainDivCss : CssName() object ActiveCss : CssName() object ButtonCss : CssName() object NoteBarCss : CssName() object StartSplashCss : CssName() object StartBoxCss : CssName() object StartButtonCss : CssName() init { defineCss { select("*") { select("*:before") { select("*:after") { boxSizing(BoxSizing.borderBox) } } } select("html", "body") { margin(0.px) padding(0.px) height(100.prc) fontFamily("JetbrainsMono, monospace") fontSize(14.px) fontWeight(FontWeight.bold) //transition() noTextSelect() } select(cls(ButtonCss)) { margin(1.rem) padding(1.rem) backgroundColor(Css.currentStyle.buttonBackgroundColor) hover { backgroundColor(Css.currentStyle.buttonBackgroundColor.hover()) } } select(cls(ActiveCss)) { backgroundColor(Css.currentStyle.selectedBackgroundColor) } select(cls(NoteBarCss)) { minHeight(4.rem) } select(cls(MainDivCss)) { margin(1.rem) } select("select") { plain("appearance", "none") border("0") outline("0") width(20.rem) padding(0.5.rem, 2.rem, 0.5.rem, 0.5.rem) backgroundImage("url('https://upload.wikimedia.org/wikipedia/commons/9/9d/Caret_down_font_awesome_whitevariation.svg')") background("right 0.8em center/1.4em") backgroundColor(Css.currentStyle.inputBackgroundColor) color(Css.currentStyle.entryFontColor) borderRadius(0.25.em) } select(cls(StartSplashCss)) { position(Position.fixed) left(0.px) top(0.px) width(100.vw) height(100.vh) zIndex(100) backgroundColor(hsla(32, 0, 50, 0.6)) select(cls(StartBoxCss)) { position(Position.relative) left(25.vw) top(25.vh) width(50.vw) height(50.vh) backgroundColor(hsla(0, 0, 50, 0.25)) select(cls(StartButtonCss)) { position(Position.absolute) left(50.prc) top(50.prc) transform(Transform("translate(-50%, -50%)")) padding(1.rem) backgroundColor(Css.currentStyle.buttonBackgroundColor) cursor("pointer") } } } } } } }