Arremi/backend/midiDevice_linux.go

94 lines
2.0 KiB
Go
Raw Normal View History

2018-03-19 04:44:18 +00:00
package backend
2018-03-19 14:34:42 +00:00
/*
#ifndef ARREMI
#define ARREMI
#cgo LDFLAGS: -lasound
#include "alsa_wrapper/alsa_wrapper.h"
#endif
*/
2018-03-19 04:44:18 +00:00
import (
2018-03-19 14:34:42 +00:00
"C"
"unsafe"
)
import (
"fmt"
2018-03-19 04:44:18 +00:00
"github.com/tonychee7000/Arremi/consts"
)
// MIDIDevice implies a Writer interface.
type MIDIDevice struct {
2018-03-19 14:34:42 +00:00
Signal chan int
2018-03-19 04:44:18 +00:00
}
// NewMIDIDevice construction func
func NewMIDIDevice() (*MIDIDevice, error) {
var mididev = new(MIDIDevice)
err := mididev.Init()
return mididev, err
}
// Init the client and source
func (midiDev *MIDIDevice) Init() error {
2018-03-19 14:34:42 +00:00
var status int
2018-03-19 04:44:18 +00:00
2018-03-19 14:34:42 +00:00
midiDev.Signal = make(chan int, 4096)
cDevName := C.CString(consts.ClientName)
defer C.free(unsafe.Pointer(cDevName))
2018-03-19 14:41:35 +00:00
status = int(C.new_client(cDevName))
2018-03-19 14:34:42 +00:00
if status != 0 {
stage, errCode := resolveErrCode(status)
switch stage {
case 1:
return fmt.Errorf("Error while opening sequencer. %d", errCode)
case 2:
return fmt.Errorf("Error while getting sequencer id. %d", errCode)
case 3:
return fmt.Errorf("Error while setting sequencer name. %d", errCode)
}
2018-03-19 04:44:18 +00:00
}
2018-03-19 14:34:42 +00:00
cPortName := C.CString(consts.SourceName)
defer C.free(unsafe.Pointer(cPortName))
2018-03-19 14:41:35 +00:00
status = int(C.new_port(cPortName))
2018-03-19 14:34:42 +00:00
if status != 0 {
return fmt.Errorf("Error while createing sequencer port. %d", status)
}
return nil
2018-03-19 04:44:18 +00:00
}
func (midiDev *MIDIDevice) Write(p []byte) (int, error) {
2018-03-19 14:34:42 +00:00
midiDev.Signal <- 1
cData := (*C.CChar)(unsafe.Pointer(&p[0]))
defer C.free(unsafe.Pointer(cData))
2018-03-19 14:41:35 +00:00
var status = int(C.send_data(cData, C.int(len(p))))
2018-03-19 14:34:42 +00:00
if status != 0 {
stage, errCode := resolveErrCode(status)
switch stage {
case 1:
return 0, fmt.Errorf("Error while creating MIDI event. %d", errCode)
case 2:
return 0, fmt.Errorf("Error while encoding MIDI event. %d", errCode)
case 3:
return 0, fmt.Errorf("Error while sending data. %d", errCode)
}
}
return len(p), nil
2018-03-19 04:44:18 +00:00
}
// AllNoteOff I don't want panic!
func (midiDev *MIDIDevice) AllNoteOff() {
for i := 0; i < 16; i++ {
for j := 0; j < 128; j++ {
midiDev.Write([]byte{byte(0x90 + i), byte(j), 0})
}
}
}
2018-03-19 14:34:42 +00:00
func resolveErrCode(int code) (int, int) {
return code >> 16, code & 0xffff
}