port to linux, stage 1
This commit is contained in:
parent
72f8c72458
commit
7d244b12f8
64
backend/alsa_wrapper/alsa_wrapper.c
Normal file
64
backend/alsa_wrapper/alsa_wrapper.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
#include "alsa_wrapper.h"
|
||||||
|
|
||||||
|
int new_client(char* client_name) {
|
||||||
|
int status;
|
||||||
|
status = snd_seq_open(&seq_handle, "hw", SND_SEQ_OPEN_OUTPUT, 0);
|
||||||
|
if (status < 0) {
|
||||||
|
return 1<<16|status;
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_client = snd_seq_client_id(seq_handle);
|
||||||
|
if (seq_client < 0) {
|
||||||
|
return 2<<16|status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = snd_seq_client_name(seq_handle, client_name);
|
||||||
|
if (status < 0) {
|
||||||
|
return 3<<16|status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_port(char* port_name) {
|
||||||
|
seq_port = snd_seq_create_simple_port(seq_handle, portname,
|
||||||
|
SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
|
||||||
|
SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION);
|
||||||
|
if (seq_port < 0) {
|
||||||
|
return seq_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_data(char* data, int length) {
|
||||||
|
int status;
|
||||||
|
snd_midi_event_t* midiParser;
|
||||||
|
|
||||||
|
status = snd_midi_event_new(length, &midiParser);
|
||||||
|
if (status < 0) {
|
||||||
|
return 1<<16|status;
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_seq_event_t* ev;
|
||||||
|
snd_seq_ev_clear(ev);
|
||||||
|
|
||||||
|
status = snd_midi_event_encode(midiParser, data, length, ev);
|
||||||
|
if (status < 0) {
|
||||||
|
return 2<<16|status;
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_seq_ev_set_direct(ev);
|
||||||
|
snd_seq_ev_set_source(ev, seq_port);
|
||||||
|
snd_seq_ev_set_dest(ev, SND_SEQ_ADDRESS_SUBSCRIBERS, 0);
|
||||||
|
|
||||||
|
status = snd_seq_event_output_direct(seq_handle, ev);
|
||||||
|
if (status < 0) {
|
||||||
|
return 3<<16|status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
12
backend/alsa_wrapper/alsa_wrapper.h
Normal file
12
backend/alsa_wrapper/alsa_wrapper.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef ARREMI_ALSA_WRAPPER_H
|
||||||
|
#define ARREMI_ALSA_WRAPPER_H
|
||||||
|
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
|
static snd_seq_t *seq_handle;
|
||||||
|
int seq_client, seq_port;
|
||||||
|
|
||||||
|
int new_client(char*);
|
||||||
|
int new_port(char*);
|
||||||
|
int send_data(char*, int);
|
||||||
|
#endif
|
@ -9,7 +9,7 @@ import (
|
|||||||
type MIDIDevice struct {
|
type MIDIDevice struct {
|
||||||
client midi.Client
|
client midi.Client
|
||||||
source midi.Source
|
source midi.Source
|
||||||
Signal chan midi.Packet
|
Signal chan int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMIDIDevice construction func
|
// NewMIDIDevice construction func
|
||||||
@ -23,7 +23,7 @@ func NewMIDIDevice() (*MIDIDevice, error) {
|
|||||||
func (midiDev *MIDIDevice) Init() error {
|
func (midiDev *MIDIDevice) Init() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
midiDev.Signal = make(chan midi.Packet, 4096)
|
midiDev.Signal = make(chan int, 4096)
|
||||||
midiDev.client, err = midi.NewClient(consts.ClientName)
|
midiDev.client, err = midi.NewClient(consts.ClientName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -35,7 +35,7 @@ func (midiDev *MIDIDevice) Init() error {
|
|||||||
|
|
||||||
func (midiDev *MIDIDevice) Write(p []byte) (int, error) {
|
func (midiDev *MIDIDevice) Write(p []byte) (int, error) {
|
||||||
var pack = midi.NewPacket(p, 0)
|
var pack = midi.NewPacket(p, 0)
|
||||||
midiDev.Signal <- pack
|
midiDev.Signal <- 1
|
||||||
err := pack.Received(&(midiDev.source))
|
err := pack.Received(&(midiDev.source))
|
||||||
return len(p), err
|
return len(p), err
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
package backend
|
package backend
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifndef ARREMI
|
||||||
|
#define ARREMI
|
||||||
|
#cgo LDFLAGS: -lasound
|
||||||
|
#include "alsa_wrapper/alsa_wrapper.h"
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
import (
|
import (
|
||||||
|
"C"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/tonychee7000/Arremi/consts"
|
"github.com/tonychee7000/Arremi/consts"
|
||||||
midi "github.com/youpy/go-coremidi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MIDIDevice implies a Writer interface.
|
// MIDIDevice implies a Writer interface.
|
||||||
type MIDIDevice struct {
|
type MIDIDevice struct {
|
||||||
client midi.Client
|
Signal chan int
|
||||||
source midi.Source
|
|
||||||
Signal chan midi.Packet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMIDIDevice construction func
|
// NewMIDIDevice construction func
|
||||||
@ -21,23 +31,52 @@ func NewMIDIDevice() (*MIDIDevice, error) {
|
|||||||
|
|
||||||
// Init the client and source
|
// Init the client and source
|
||||||
func (midiDev *MIDIDevice) Init() error {
|
func (midiDev *MIDIDevice) Init() error {
|
||||||
var err error
|
var status int
|
||||||
|
|
||||||
midiDev.Signal = make(chan midi.Packet, 4096)
|
midiDev.Signal = make(chan int, 4096)
|
||||||
midiDev.client, err = midi.NewClient(consts.ClientName)
|
|
||||||
if err != nil {
|
cDevName := C.CString(consts.ClientName)
|
||||||
return err
|
defer C.free(unsafe.Pointer(cDevName))
|
||||||
|
status = C.new_client(cDevName)
|
||||||
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
midiDev.source, err = midi.NewSource(midiDev.client, consts.SourceName)
|
cPortName := C.CString(consts.SourceName)
|
||||||
return err
|
defer C.free(unsafe.Pointer(cPortName))
|
||||||
|
status = C.new_port(cPortName)
|
||||||
|
if status != 0 {
|
||||||
|
return fmt.Errorf("Error while createing sequencer port. %d", status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (midiDev *MIDIDevice) Write(p []byte) (int, error) {
|
func (midiDev *MIDIDevice) Write(p []byte) (int, error) {
|
||||||
var pack = midi.NewPacket(p, 0)
|
midiDev.Signal <- 1
|
||||||
midiDev.Signal <- pack
|
cData := (*C.CChar)(unsafe.Pointer(&p[0]))
|
||||||
err := pack.Received(&(midiDev.source))
|
defer C.free(unsafe.Pointer(cData))
|
||||||
return len(p), err
|
var status = C.send_data(cData, C.int(len(p)))
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllNoteOff I don't want panic!
|
// AllNoteOff I don't want panic!
|
||||||
@ -48,3 +87,7 @@ func (midiDev *MIDIDevice) AllNoteOff() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveErrCode(int code) (int, int) {
|
||||||
|
return code >> 16, code & 0xffff
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user