KORG microX utility.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
5.1 KiB

/*
* asysex - A SysEx Utility
* Copyright (C) 2012 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <midi.h>
#include <stdlib.h>
#include <assert.h>
#include <xmem.h>
#if USE_ALSA_MIDI_API
/* Linux ALSA API */
#include <alsa/asoundlib.h>
#define MIDI_IO_BUFFER_SIZE 256
struct midi_io
{
snd_rawmidi_t *in;
snd_rawmidi_t *out;
int error;
unsigned char buffer[MIDI_IO_BUFFER_SIZE];
size_t pos;
size_t len;
unsigned char status;
};
midi_io_t *
midi_open(const char *name)
{
midi_io_t *midi;
assert(name != NULL);
midi = xmalloc(sizeof(*midi));
midi->in = midi->out = NULL;
midi->error = midi->pos = midi->len = midi->status = 0;
if ( snd_rawmidi_open(&(midi->in), &(midi->out), name,
SND_RAWMIDI_NONBLOCK) < 0 ) {
free(midi);
midi = NULL;
}
else if ( snd_rawmidi_nonblock(midi->out, 0) < 0 ) {
midi_close(midi);
midi = NULL;
}
return midi;
}
int
midi_close(midi_io_t *midi)
{
assert(midi != NULL);
snd_rawmidi_close(midi->in);
snd_rawmidi_close(midi->out);
free(midi);
return 0;
}
ssize_t
midi_write(midi_io_t *midi, unsigned char *buffer, size_t len)
{
assert(midi != NULL);
assert(buffer != NULL);
/* Flush reading buffer. */
midi->pos = midi->len = 0;
midi->error = snd_rawmidi_write(midi->out, buffer, len);
return midi->error;
}
ssize_t
midi_read(midi_io_t *midi, unsigned char *buffer, size_t len)
{
assert(midi != NULL);
assert(buffer != NULL);
midi->error = snd_rawmidi_read(midi->in, buffer, len);
return midi->error;
}
int
midi_next(midi_io_t *midi)
{
unsigned char b;
assert(midi != NULL);
if ( midi->pos >= midi->len ) {
ssize_t n;
n = midi_read(midi, midi->buffer, MIDI_IO_BUFFER_SIZE);
if ( n < 0 )
return n;
midi->len = n;
midi->pos = 0;
}
b = (unsigned char) midi->buffer[midi->pos++];
if ( b >= 0x80 && b < 0xF8 ) /* Status byte? */
midi->status = b;
return b;
}
inline unsigned char
midi_status(midi_io_t *midi)
{
return midi->status;
}
const char *
midi_error(midi_io_t *midi)
{
assert(midi != NULL);
if ( midi->error > 0 )
return NULL;
else
return snd_strerror(midi->error);
}
#elif USE_OSS_MIDI_API
/* Open Sound System MIDI API */
#include <fcntl.h>
#define MIDI_IO_BUFFER_SIZE 256
struct midi_io
{
int fd;
int error;
unsigned char buffer[MIDI_IO_BUFFER_SIZE];
size_t pos;
size_t len;
unsigned char status;
};
midi_io_t *
midi_open(const char *name)
{
midi_io_t *midi;
assert(name != NULL);
midi = xmalloc(sizeof(*midi));
midi->fd = -1;
midi->error = midi->pos = midi->len = midi->status = 0;
if ( (midi->fd = open(name, O_RDWR, 0)) == -1 ) {
free(midi);
midi = NULL;
}
return midi;
}
int
midi_close(midi_io_t *midi)
{
assert(midi != NULL);
close(midi->fd);
free(midi);
return 0;
}
ssize_t
midi_write(midi_io_t *midi, unsigned char *buffer, size_t len)
{
ssize_t n;
assert(midi != NULL);
assert(buffer != NULL);
/* Flush reading buffer. */
midi->pos = midi->len = 0;
if ( (n = write(midi->fd, buffer, len)) == -1 )
midi->error = errno;
else
midi->error = 0;
return n;
}
ssize_t
midi_read(midi_io_t *midi, unsigned char *buffer, size_t len)
{
ssize_t n;
assert(midi != NULL);
assert(buffer != NULL);
if ( (n = read(midi->fd, buffer, len)) == -1 )
midi->error = errno;
else
midi->error = 0;
return n;
}
int
midi_next(midi_io_t *midi)
{
unsigned char b;
assert(midi != NULL);
if ( midi->pos >= midi->len ) {
ssize_t n;
n = midi_read(midi, midi->buffer, MIDI_IO_BUFFER_SIZE);
if ( n < 0 )
return n;
midi->len = n;
midi->pos = 0;
}
b = (unsigned char) midi->buffer[midi->pos++];
if ( b >= 0x80 && b < 0xF8 ) /* Status byte? */
midi->status = b;
return b;
}
inline unsigned char
midi_status(midi_io_t *midi)
{
return midi->status;
}
const char *
midi_error(midi_io_t *midi)
{
assert(midi != NULL);
if ( midi->error == 0 )
return NULL;
else
return strerror(midi->error);
}
#else
#error "No MIDI API available"
/* TODO: Support for others MIDI APIs (JackMIDI?, WinAPI?, ...) */
#endif