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
|
2018-03-20 00:24:25 +00:00
|
|
|
#include <stdlib.h>
|
2018-03-19 14:34:42 +00:00
|
|
|
#include "alsa_wrapper/alsa_wrapper.h"
|
|
|
|
#endif
|
|
|
|
*/
|
2018-03-20 00:40:45 +00:00
|
|
|
import "C"
|
2018-03-19 14:34:42 +00:00
|
|
|
import (
|
|
|
|
"fmt"
|
2018-03-20 00:40:45 +00:00
|
|
|
"unsafe"
|
2018-03-19 14:34:42 +00:00
|
|
|
|
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
|
|
|
|
}
|