forked from len0rd/rockbox
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21070 a1c6a512-1295-4272-9138-f99709370657
360 lines
8.5 KiB
C
360 lines
8.5 KiB
C
/* Copyright (c) 1997-1999 Guenter Geiger, Miller Puckette, Larry Troxler,
|
|
* Winfried Ritsch, Karl MacMillan, and others.
|
|
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
|
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
|
|
|
|
/* MIDI I/O for Linux using OSS */
|
|
|
|
#include <stdio.h>
|
|
#ifdef UNIX
|
|
#include <unistd.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include "m_pd.h"
|
|
#include "s_stuff.h"
|
|
|
|
static int oss_nmidiin;
|
|
static int oss_midiinfd[MAXMIDIINDEV];
|
|
static int oss_nmidiout;
|
|
static int oss_midioutfd[MAXMIDIOUTDEV];
|
|
|
|
static void oss_midiout(int fd, int n)
|
|
{
|
|
char b = n;
|
|
if ((write(fd, (char *) &b, 1)) != 1)
|
|
perror("midi write");
|
|
}
|
|
|
|
#define O_MIDIFLAG O_NDELAY
|
|
|
|
void sys_do_open_midi(int nmidiin, int *midiinvec,
|
|
int nmidiout, int *midioutvec)
|
|
{
|
|
int i;
|
|
for (i = 0; i < nmidiout; i++)
|
|
oss_midioutfd[i] = -1;
|
|
for (i = 0, oss_nmidiin = 0; i < nmidiin; i++)
|
|
{
|
|
int fd = -1, j, outdevindex = -1;
|
|
char namebuf[80];
|
|
int devno = midiinvec[i];
|
|
|
|
for (j = 0; j < nmidiout; j++)
|
|
if (midioutvec[j] == midiinvec[i])
|
|
outdevindex = j;
|
|
|
|
/* try to open the device for read/write. */
|
|
if (devno == 0 && fd < 0 && outdevindex >= 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
fd = open("/dev/midi", O_RDWR | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr,
|
|
"device 1: tried /dev/midi READ/WRITE; returned %d\n", fd);
|
|
if (outdevindex >= 0 && fd >= 0)
|
|
oss_midioutfd[outdevindex] = fd;
|
|
}
|
|
if (fd < 0 && outdevindex >= 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
sprintf(namebuf, "/dev/midi%2.2d", devno);
|
|
fd = open(namebuf, O_RDWR | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr,
|
|
"device %d: tried %s READ/WRITE; returned %d\n",
|
|
devno, namebuf, fd);
|
|
if (outdevindex >= 0 && fd >= 0)
|
|
oss_midioutfd[outdevindex] = fd;
|
|
}
|
|
if (fd < 0 && outdevindex >= 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
sprintf(namebuf, "/dev/midi%d", devno);
|
|
fd = open(namebuf, O_RDWR | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr, "device %d: tried %s READ/WRITE; returned %d\n",
|
|
devno, namebuf, fd);
|
|
if (outdevindex >= 0 && fd >= 0)
|
|
oss_midioutfd[outdevindex] = fd;
|
|
}
|
|
if (devno == 1 && fd < 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
fd = open("/dev/midi", O_RDONLY | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr,
|
|
"device 1: tried /dev/midi READONLY; returned %d\n", fd);
|
|
}
|
|
if (fd < 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
sprintf(namebuf, "/dev/midi%2.2d", devno);
|
|
fd = open(namebuf, O_RDONLY | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr, "device %d: tried %s READONLY; returned %d\n",
|
|
devno, namebuf, fd);
|
|
}
|
|
if (fd < 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
sprintf(namebuf, "/dev/midi%d", devno);
|
|
fd = open(namebuf, O_RDONLY | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr, "device %d: tried %s READONLY; returned %d\n",
|
|
devno, namebuf, fd);
|
|
}
|
|
if (fd >= 0)
|
|
oss_midiinfd[oss_nmidiin++] = fd;
|
|
else post("couldn't open MIDI input device %d", devno);
|
|
}
|
|
for (i = 0, oss_nmidiout = 0; i < nmidiout; i++)
|
|
{
|
|
int fd = oss_midioutfd[i];
|
|
char namebuf[80];
|
|
int devno = midioutvec[i];
|
|
if (devno == 1 && fd < 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
fd = open("/dev/midi", O_WRONLY | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr,
|
|
"device 1: tried /dev/midi WRITEONLY; returned %d\n", fd);
|
|
}
|
|
if (fd < 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
sprintf(namebuf, "/dev/midi%2.2d", devno);
|
|
fd = open(namebuf, O_WRONLY | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr, "device %d: tried %s WRITEONLY; returned %d\n",
|
|
devno, namebuf, fd);
|
|
}
|
|
if (fd < 0)
|
|
{
|
|
sys_setalarm(1000000);
|
|
sprintf(namebuf, "/dev/midi%d", devno);
|
|
fd = open(namebuf, O_WRONLY | O_MIDIFLAG);
|
|
if (sys_verbose)
|
|
fprintf(stderr, "device %d: tried %s WRITEONLY; returned %d\n",
|
|
devno, namebuf, fd);
|
|
}
|
|
if (fd >= 0)
|
|
oss_midioutfd[oss_nmidiout++] = fd;
|
|
else post("couldn't open MIDI output device %d", devno);
|
|
}
|
|
|
|
if (oss_nmidiin < nmidiin || oss_nmidiout < nmidiout || sys_verbose)
|
|
post("opened %d MIDI input device(s) and %d MIDI output device(s).",
|
|
oss_nmidiin, oss_nmidiout);
|
|
|
|
sys_setalarm(0);
|
|
}
|
|
|
|
#define md_msglen(x) (((x)<0xC0)?2:((x)<0xE0)?1:((x)<0xF0)?2:\
|
|
((x)==0xF2)?2:((x)<0xF4)?1:0)
|
|
|
|
void sys_putmidimess(int portno, int a, int b, int c)
|
|
{
|
|
if (portno >= 0 && portno < oss_nmidiout)
|
|
{
|
|
switch (md_msglen(a))
|
|
{
|
|
case 2:
|
|
oss_midiout(oss_midioutfd[portno],a);
|
|
oss_midiout(oss_midioutfd[portno],b);
|
|
oss_midiout(oss_midioutfd[portno],c);
|
|
return;
|
|
case 1:
|
|
oss_midiout(oss_midioutfd[portno],a);
|
|
oss_midiout(oss_midioutfd[portno],b);
|
|
return;
|
|
case 0:
|
|
oss_midiout(oss_midioutfd[portno],a);
|
|
return;
|
|
};
|
|
}
|
|
}
|
|
|
|
void sys_putmidibyte(int portno, int byte)
|
|
{
|
|
if (portno >= 0 && portno < oss_nmidiout)
|
|
oss_midiout(oss_midioutfd[portno], byte);
|
|
}
|
|
|
|
#if 0 /* this is the "select" version which doesn't work with OSS
|
|
driver for emu10k1 (it doesn't implement select.) */
|
|
void sys_poll_midi(void)
|
|
{
|
|
int i, throttle = 100;
|
|
struct timeval timout;
|
|
int did = 1, maxfd = 0;
|
|
while (did)
|
|
{
|
|
fd_set readset, writeset, exceptset;
|
|
did = 0;
|
|
if (throttle-- < 0)
|
|
break;
|
|
timout.tv_sec = 0;
|
|
timout.tv_usec = 0;
|
|
|
|
FD_ZERO(&writeset);
|
|
FD_ZERO(&readset);
|
|
FD_ZERO(&exceptset);
|
|
for (i = 0; i < oss_nmidiin; i++)
|
|
{
|
|
if (oss_midiinfd[i] > maxfd)
|
|
maxfd = oss_midiinfd[i];
|
|
FD_SET(oss_midiinfd[i], &readset);
|
|
}
|
|
select(maxfd+1, &readset, &writeset, &exceptset, &timout);
|
|
for (i = 0; i < oss_nmidiin; i++)
|
|
if (FD_ISSET(oss_midiinfd[i], &readset))
|
|
{
|
|
char c;
|
|
int ret = read(oss_midiinfd[i], &c, 1);
|
|
if (ret <= 0)
|
|
fprintf(stderr, "Midi read error\n");
|
|
else sys_midibytein(i, (c & 0xff));
|
|
did = 1;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
|
|
/* this version uses the asynchronous "read()" ... */
|
|
void sys_poll_midi(void)
|
|
{
|
|
int i, throttle = 100;
|
|
struct timeval timout;
|
|
int did = 1, maxfd = 0;
|
|
while (did)
|
|
{
|
|
fd_set readset, writeset, exceptset;
|
|
did = 0;
|
|
if (throttle-- < 0)
|
|
break;
|
|
for (i = 0; i < oss_nmidiin; i++)
|
|
{
|
|
char c;
|
|
int ret = read(oss_midiinfd[i], &c, 1);
|
|
if (ret < 0)
|
|
{
|
|
if (errno != EAGAIN)
|
|
perror("MIDI");
|
|
}
|
|
else if (ret != 0)
|
|
{
|
|
sys_midibytein(i, (c & 0xff));
|
|
did = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void sys_close_midi()
|
|
{
|
|
int i;
|
|
for (i = 0; i < oss_nmidiin; i++)
|
|
close(oss_midiinfd[i]);
|
|
for (i = 0; i < oss_nmidiout; i++)
|
|
close(oss_midioutfd[i]);
|
|
oss_nmidiin = oss_nmidiout = 0;
|
|
}
|
|
|
|
#define NSEARCH 10
|
|
static int oss_nmidiindevs, oss_nmidioutdevs, oss_initted;
|
|
|
|
void midi_oss_init(void)
|
|
{
|
|
int i;
|
|
if (oss_initted)
|
|
return;
|
|
oss_initted = 1;
|
|
for (i = 0; i < NSEARCH; i++)
|
|
{
|
|
int fd;
|
|
char namebuf[80];
|
|
|
|
oss_nmidiindevs = i;
|
|
/* try to open the device for reading */
|
|
if (i == 0)
|
|
{
|
|
fd = open("/dev/midi", O_RDONLY | O_NDELAY);
|
|
if (fd >= 0)
|
|
{
|
|
close(fd);
|
|
continue;
|
|
}
|
|
}
|
|
sprintf(namebuf, "/dev/midi%2.2d", i);
|
|
fd = open(namebuf, O_RDONLY | O_NDELAY);
|
|
if (fd >= 0)
|
|
{
|
|
close(fd);
|
|
continue;
|
|
}
|
|
sprintf(namebuf, "/dev/midi%d", i);
|
|
fd = open(namebuf, O_RDONLY | O_NDELAY);
|
|
if (fd >= 0)
|
|
{
|
|
close(fd);
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
for (i = 0; i < NSEARCH; i++)
|
|
{
|
|
int fd;
|
|
char namebuf[80];
|
|
|
|
oss_nmidioutdevs = i;
|
|
/* try to open the device for writing */
|
|
if (i == 0)
|
|
{
|
|
fd = open("/dev/midi", O_WRONLY | O_NDELAY);
|
|
if (fd >= 0)
|
|
{
|
|
close(fd);
|
|
continue;
|
|
}
|
|
}
|
|
sprintf(namebuf, "/dev/midi%2.2d", i);
|
|
fd = open(namebuf, O_WRONLY | O_NDELAY);
|
|
if (fd >= 0)
|
|
{
|
|
close(fd);
|
|
continue;
|
|
}
|
|
sprintf(namebuf, "/dev/midi%d", i);
|
|
fd = open(namebuf, O_WRONLY | O_NDELAY);
|
|
if (fd >= 0)
|
|
{
|
|
close(fd);
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void midi_getdevs(char *indevlist, int *nindevs,
|
|
char *outdevlist, int *noutdevs, int maxndev, int devdescsize)
|
|
{
|
|
int i, ndev;
|
|
if ((ndev = oss_nmidiindevs) > maxndev)
|
|
ndev = maxndev;
|
|
for (i = 0; i < ndev; i++)
|
|
sprintf(indevlist + i * devdescsize, "OSS MIDI device #%d", i+1);
|
|
*nindevs = ndev;
|
|
|
|
if ((ndev = oss_nmidioutdevs) > maxndev)
|
|
ndev = maxndev;
|
|
for (i = 0; i < ndev; i++)
|
|
sprintf(outdevlist + i * devdescsize, "OSS MIDI device #%d", i+1);
|
|
*noutdevs = ndev;
|
|
}
|
|
|