automidically/internal/midi/midi.go

98 lines
1.9 KiB
Go

// git.auengun.net/GregoryDosh/automidically
// Copyright (C) 2020 GregoryDosh
package midi
import (
"sync"
"github.com/sirupsen/logrus"
"gitlab.com/gomidi/midi/v2"
"gitlab.com/gomidi/midi/v2/drivers"
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
)
var log = logrus.WithField("module", "midi")
type Device struct {
DeviceName string
messageCallback func(int, int)
messageChan chan [2]int
device drivers.In
stopFunc func()
sync.Mutex
}
func (d *Device) Cleanup() error {
d.Lock()
defer d.Unlock()
if d.messageChan != nil {
close(d.messageChan)
d.messageChan = nil
}
if d.stopFunc != nil {
d.stopFunc()
d.stopFunc = nil
}
if d.messageCallback != nil {
d.messageCallback = nil
}
midi.CloseDriver()
return nil
}
func (d *Device) SetMessageCallback(cb func(int, int)) {
d.Lock()
defer d.Unlock()
d.messageCallback = cb
}
func (d *Device) handleMIDIMessageLoop() {
log.Trace("Enter handleMIDIMessageLoop")
defer log.Trace("Exit handleMIDIMessageLoop")
stop, err := midi.ListenTo(d.device, func(msg midi.Message, timestampms int32) {
mb := msg.Bytes()
channelMessage := [2]int{int(mb[1]), int(mb[2])}
log.Debug(channelMessage)
d.messageChan <- channelMessage
}, midi.UseSysEx())
if err != nil {
log.Error(err)
return
}
d.stopFunc = stop
for msg := range d.messageChan {
d.Lock()
if d.messageCallback != nil {
d.messageCallback(msg[0], msg[1])
}
d.Unlock()
}
}
func New(searchName string) *Device {
if searchName == "" {
log.Error("missing MIDI device name")
return nil
}
in, err := midi.FindInPort(searchName)
if err != nil {
log.Errorf("unable to find MIDI device containing '%s'", searchName)
return nil
}
log.Infof("using MIDI device %s", in.String())
d := &Device{
DeviceName: in.String(),
device: in,
messageChan: make(chan [2]int, 250),
}
go d.handleMIDIMessageLoop()
return d
}