mirror of
https://github.com/vsariola/sointu.git
synced 2025-07-19 05:24:48 -04:00
59 lines
1.4 KiB
Go
59 lines
1.4 KiB
Go
package gioui
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/vsariola/sointu/tracker"
|
|
)
|
|
|
|
type (
|
|
// Keyboard is used to associate the keys of a keyboard (e.g. computer or a
|
|
// MIDI keyboard) to currently playing notes. You can use any type T to
|
|
// identify each key; T should be a comparable type.
|
|
Keyboard[T comparable] struct {
|
|
broker *tracker.Broker
|
|
pressed map[T]tracker.NoteEvent
|
|
}
|
|
)
|
|
|
|
func MakeKeyboard[T comparable](broker *tracker.Broker) Keyboard[T] {
|
|
return Keyboard[T]{
|
|
broker: broker,
|
|
pressed: make(map[T]tracker.NoteEvent),
|
|
}
|
|
}
|
|
|
|
func (t *Keyboard[T]) Press(key T, ev tracker.NoteEvent) {
|
|
if _, ok := t.pressed[key]; ok {
|
|
return // already playing a note with this key, do not send a new event
|
|
}
|
|
t.Release(key) // unset any previous note
|
|
if ev.Note > 1 {
|
|
ev.Source = t // set the source to this keyboard
|
|
ev.On = true
|
|
ev.Timestamp = t.now()
|
|
if tracker.TrySend(t.broker.ToPlayer, any(ev)) {
|
|
t.pressed[key] = ev
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *Keyboard[T]) Release(key T) {
|
|
if ev, ok := t.pressed[key]; ok {
|
|
ev.Timestamp = t.now()
|
|
ev.On = false // the pressed contains the event we need to send to release the note
|
|
tracker.TrySend(t.broker.ToPlayer, any(ev))
|
|
delete(t.pressed, key)
|
|
}
|
|
}
|
|
|
|
func (t *Keyboard[T]) ReleaseAll() {
|
|
for key := range t.pressed {
|
|
t.Release(key)
|
|
}
|
|
}
|
|
|
|
func (t *Keyboard[T]) now() int64 {
|
|
return time.Now().UnixMilli() * 441 / 10 // convert to 44100Hz frames
|
|
}
|