98 lines
1.9 KiB
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
|
|
}
|