mirror of https://github.com/nealey/vail.git
fixes: iambic, https, mobile, probably more
This commit is contained in:
parent
ac08b063fc
commit
863df2b0ed
9
main.go
9
main.go
|
@ -14,12 +14,10 @@ type Client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) Handle(ws *websocket.Conn) {
|
func (c Client) Handle(ws *websocket.Conn) {
|
||||||
log.Println("c.Handle hooray")
|
|
||||||
ws.MaxPayloadBytes = 500
|
ws.MaxPayloadBytes = 500
|
||||||
book.Join(c.repeaterName, ws)
|
book.Join(c.repeaterName, ws)
|
||||||
defer book.Part(c.repeaterName, ws)
|
defer book.Part(c.repeaterName, ws)
|
||||||
|
|
||||||
log.Println("for loop")
|
|
||||||
for {
|
for {
|
||||||
buf := make([]byte, ws.MaxPayloadBytes)
|
buf := make([]byte, ws.MaxPayloadBytes)
|
||||||
|
|
||||||
|
@ -34,25 +32,18 @@ func (c Client) Handle(ws *websocket.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChatHandler(w http.ResponseWriter, r *http.Request) {
|
func ChatHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Print("Handling chat")
|
|
||||||
c := Client {
|
c := Client {
|
||||||
repeaterName: r.FormValue("repeater"),
|
repeaterName: r.FormValue("repeater"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// This API is confusing as hell.
|
// This API is confusing as hell.
|
||||||
// I suspect there's a better way to do this.
|
// I suspect there's a better way to do this.
|
||||||
log.Print("Web Socketing")
|
|
||||||
websocket.Handler(c.Handle).ServeHTTP(w, r)
|
websocket.Handler(c.Handle).ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func hello(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Write([]byte("Hello world"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
book = NewBook()
|
book = NewBook()
|
||||||
http.Handle("/chat", http.HandlerFunc(ChatHandler))
|
http.Handle("/chat", http.HandlerFunc(ChatHandler))
|
||||||
http.Handle("/hello", http.HandlerFunc(hello))
|
|
||||||
http.Handle("/", http.FileServer(http.Dir("static")))
|
http.Handle("/", http.FileServer(http.Dir("static")))
|
||||||
go book.Run()
|
go book.Run()
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
<main class="mdl-layout__content">
|
<main class="mdl-layout__content">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="mdl-card mdl-shadow--4dp">
|
<div class="input mdl-card mdl-shadow--4dp">
|
||||||
<div class="mdl-card__title">
|
<div class="mdl-card__title">
|
||||||
<h2 class="mdl-card__title-text">Input</h2>
|
<h2 class="mdl-card__title-text">Input</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,8 @@ class Iambic {
|
||||||
this.endTxFunc = endTxFunc
|
this.endTxFunc = endTxFunc
|
||||||
this.intervalDuration = null
|
this.intervalDuration = null
|
||||||
this.state = this.stateBegin
|
this.state = this.stateBegin
|
||||||
this.keyState = null
|
this.ditDown = false
|
||||||
|
this.dahDown = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,23 +35,35 @@ class Iambic {
|
||||||
this.state()
|
this.state()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stateBegin() {
|
stateBegin() {
|
||||||
if (this.keyState) {
|
if (this.ditDown) {
|
||||||
// Don't transmit for one interval.
|
this.stateDit()
|
||||||
this.state = this.keyState
|
} else if (this.dahDown) {
|
||||||
this.state()
|
this.stateDah()
|
||||||
} else {
|
} else {
|
||||||
// No key pressed, go back to sleep.
|
|
||||||
clearInterval(this.interval)
|
clearInterval(this.interval)
|
||||||
this.interval = null
|
this.interval = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stateDit() {
|
stateDit() {
|
||||||
// Send a dit
|
// Send a dit
|
||||||
this.beginTxFunc()
|
this.beginTxFunc()
|
||||||
this.state = this.stateEnd
|
this.state = this.stateDitEnd
|
||||||
}
|
}
|
||||||
|
stateDitEnd() {
|
||||||
|
this.endTxFunc()
|
||||||
|
this.state = this.stateDitNext
|
||||||
|
}
|
||||||
|
stateDitNext() {
|
||||||
|
if (this.dahDown) {
|
||||||
|
this.state = this.stateDah
|
||||||
|
} else {
|
||||||
|
this.state = this.stateBegin
|
||||||
|
}
|
||||||
|
this.state()
|
||||||
|
}
|
||||||
|
|
||||||
stateDah() {
|
stateDah() {
|
||||||
// Send a dah
|
// Send a dah
|
||||||
this.beginTxFunc()
|
this.beginTxFunc()
|
||||||
|
@ -60,13 +73,21 @@ class Iambic {
|
||||||
this.state = this.stateDah3
|
this.state = this.stateDah3
|
||||||
}
|
}
|
||||||
stateDah3() {
|
stateDah3() {
|
||||||
this.state = this.stateEnd
|
this.state = this.stateDahEnd
|
||||||
}
|
}
|
||||||
stateEnd() {
|
stateDahEnd() {
|
||||||
// Stop sending
|
|
||||||
this.endTxFunc()
|
this.endTxFunc()
|
||||||
|
this.state = this.stateDahNext
|
||||||
|
}
|
||||||
|
stateDahNext() {
|
||||||
|
if (this.ditDown) {
|
||||||
|
this.state = this.stateDit
|
||||||
|
} else {
|
||||||
this.state = this.stateBegin
|
this.state = this.stateBegin
|
||||||
}
|
}
|
||||||
|
this.state()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edge trigger on key press or release
|
* Edge trigger on key press or release
|
||||||
|
@ -75,20 +96,10 @@ class Iambic {
|
||||||
* @param {number} key DIT or DAH
|
* @param {number} key DIT or DAH
|
||||||
*/
|
*/
|
||||||
Key(down, key) {
|
Key(down, key) {
|
||||||
// By setting keyState we request this state transition,
|
|
||||||
// the next time the transition is possible.
|
|
||||||
let keyState = null
|
|
||||||
if (key == DIT) {
|
if (key == DIT) {
|
||||||
keyState = this.stateDit
|
this.ditDown = down
|
||||||
} else if (key == DAH) {
|
} else if (key == DAH) {
|
||||||
keyState = this.stateDah
|
this.dahDown = down
|
||||||
}
|
|
||||||
|
|
||||||
if (down) {
|
|
||||||
this.keyState = keyState
|
|
||||||
} else if (keyState == this.keyState) {
|
|
||||||
// Only stop when we've released the right key
|
|
||||||
this.keyState = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not pulsing yet? Start right away!
|
// Not pulsing yet? Start right away!
|
||||||
|
@ -219,16 +230,13 @@ class Vail {
|
||||||
this.rxDelay = 0 // Milliseconds to add to incoming timestamps
|
this.rxDelay = 0 // Milliseconds to add to incoming timestamps
|
||||||
this.beginTxTime = null // Time when we began transmitting
|
this.beginTxTime = null // Time when we began transmitting
|
||||||
|
|
||||||
// Set up WebSocket
|
this.openSocket()
|
||||||
let wsUrl = new URL(window.location)
|
|
||||||
wsUrl.protocol = wsUrl.protocol.replace("http", "ws")
|
|
||||||
wsUrl.pathname += "chat"
|
|
||||||
this.socket = new WebSocket(wsUrl)
|
|
||||||
this.socket.addEventListener("message", e => this.wsMessage(e))
|
|
||||||
|
|
||||||
// Listen to HTML buttons
|
// Listen to HTML buttons
|
||||||
for (let e of document.querySelectorAll("button.key")) {
|
for (let e of document.querySelectorAll("button.key")) {
|
||||||
e.addEventListener("contextmenu", e => {e.preventDefault(); return false})
|
e.addEventListener("contextmenu", e => {e.preventDefault(); return false})
|
||||||
|
e.addEventListener("touchstart", e => this.keyButton(e))
|
||||||
|
e.addEventListener("touchend", e => this.keyButton(e))
|
||||||
e.addEventListener("mousedown", e => this.keyButton(e))
|
e.addEventListener("mousedown", e => this.keyButton(e))
|
||||||
e.addEventListener("mouseup", e => this.keyButton(e))
|
e.addEventListener("mouseup", e => this.keyButton(e))
|
||||||
}
|
}
|
||||||
|
@ -250,9 +258,21 @@ class Vail {
|
||||||
document.querySelector("#repeater").textContent = repeater
|
document.querySelector("#repeater").textContent = repeater
|
||||||
|
|
||||||
// Request MIDI access
|
// Request MIDI access
|
||||||
|
if (navigator.requestMIDIAccess) {
|
||||||
navigator.requestMIDIAccess()
|
navigator.requestMIDIAccess()
|
||||||
.then(a => this.midiInit(a))
|
.then(a => this.midiInit(a))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openSocket() {
|
||||||
|
// Set up WebSocket
|
||||||
|
let wsUrl = new URL(window.location)
|
||||||
|
wsUrl.protocol = wsUrl.protocol.replace("http", "ws")
|
||||||
|
wsUrl.pathname += "chat"
|
||||||
|
this.socket = new WebSocket(wsUrl)
|
||||||
|
this.socket.addEventListener("message", e => this.wsMessage(e))
|
||||||
|
this.socket.addEventListener("close", e => this.openSocket())
|
||||||
|
}
|
||||||
|
|
||||||
inputInit(selector, func) {
|
inputInit(selector, func) {
|
||||||
let element = document.querySelector(selector)
|
let element = document.querySelector(selector)
|
||||||
|
@ -280,10 +300,8 @@ class Vail {
|
||||||
}
|
}
|
||||||
|
|
||||||
midiStateChange(event) {
|
midiStateChange(event) {
|
||||||
if (event.port.connection == "open") {
|
// XXX: it's not entirely clear how to handle new devices showing up.
|
||||||
console.log(event)
|
// XXX: possibly we go through this.midiAccess.inputs and somehow only listen on new things
|
||||||
event.port.addEventListiner("midimessage", e => this.midiMessage(e))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
midiMessage(event) {
|
midiMessage(event) {
|
||||||
|
@ -461,7 +479,9 @@ class Vail {
|
||||||
}
|
}
|
||||||
|
|
||||||
keyButton(event) {
|
keyButton(event) {
|
||||||
let begin = event.type.endsWith("down")
|
let begin = event.type.endsWith("down") || event.type.endsWith("start")
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
if (event.target.id == "dah") {
|
if (event.target.id == "dah") {
|
||||||
this.iambic.Key(begin, DAH)
|
this.iambic.Key(begin, DAH)
|
||||||
|
@ -471,7 +491,7 @@ class Vail {
|
||||||
this.iambic.Key(begin, DIT)
|
this.iambic.Key(begin, DIT)
|
||||||
} else if (event.target.id == "key") {
|
} else if (event.target.id == "key") {
|
||||||
this.straightKey(begin)
|
this.straightKey(begin)
|
||||||
} else if (event.target.id == "ck") {
|
} else if ((event.target.id == "ck") && begin) {
|
||||||
this.Test()
|
this.Test()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue