diff --git a/InOut/rtalsa.c b/InOut/rtalsa.c
index 94bd9fe..381ad97 100644
--- a/InOut/rtalsa.c
+++ b/InOut/rtalsa.c
@@ -2,6 +2,7 @@
rtalsa.c:
Copyright (C) 2005 Istvan Varga
+ (C) 2009 Andrés Cabrera, Clemens Ladisch
This file is part of Csound.
@@ -82,8 +83,10 @@ typedef struct alsaMidiInputDevice_ {
snd_rawmidi_t *dev;
int bufpos, nbytes, datreq;
unsigned char prvStatus, dat1, dat2;
+ struct alsaMidiInputDevice_ *next;
} alsaMidiInputDevice;
+
typedef struct midiDevFile_ {
unsigned char buf[BUF_SIZE];
int fd;
@@ -665,29 +668,89 @@ static void rtclose_(CSOUND *csound)
}
}
-static int midi_in_open(CSOUND *csound, void **userData, const char *devName)
+static alsaMidiInputDevice* open_midi_device(CSOUND *csound, const char *s)
{
- alsaMidiInputDevice *dev;
- const char *s = "hw:0,0";
int err;
+ alsaMidiInputDevice *dev;
- (*userData) = NULL;
dev = (alsaMidiInputDevice*) malloc(sizeof(alsaMidiInputDevice));
if (dev == NULL) {
csound->ErrorMsg(csound, Str("ALSA MIDI: memory allocation failure"));
- return -1;
+ return dev;
}
memset(dev, 0, sizeof(alsaMidiInputDevice));
- if (devName != NULL && devName[0] != '\0')
- s = devName;
err = snd_rawmidi_open(&(dev->dev), NULL, s, SND_RAWMIDI_NONBLOCK);
if (err != 0) {
- csound->ErrorMsg(csound, Str("ALSA: error opening MIDI input device"));
- free((void*) dev);
- return -1;
+ csound->ErrorMsg(csound, Str("ALSA: error opening MIDI input device: '%s'"), s);
+ free(dev);
+ return NULL;
}
csound->Message(csound, Str("ALSA: opened MIDI input device '%s'\n"), s);
- (*userData) = (void*) dev;
+ return dev;
+}
+
+// This is the function which contains code from amidi
+static int midi_in_open(CSOUND *csound, void **userData, const char *devName)
+{
+ alsaMidiInputDevice *dev, *newdev, *olddev;
+ const char *s = "hw:0,0";
+ int card, err;
+ int device;
+ snd_ctl_t *ctl;
+ char* name;
+ name = (char *) calloc(32, sizeof(char));
+
+ (*userData) = NULL;
+ olddev = NULL;
+ if (devName[0] == 'a') {
+ csound->Message(csound, Str("ALSA midi: Using all devices.\n"));
+ card = -1;
+ if (snd_card_next(&card) >= 0 && card >= 0) {
+ do {
+ sprintf(name, "hw:%d", card);
+ if (snd_ctl_open(&ctl, name, 0) >= 0) {
+ device = -1;
+ for (;;) {
+ if (snd_ctl_rawmidi_next_device(ctl, &device) < 0) {
+ break;
+ }
+ if (device < 0)
+ break;
+ sprintf(name, "hw:%d,%d", card, device);
+ newdev = open_midi_device(csound, name);
+ if (newdev != NULL) { /* Device opened successfully */
+ if (olddev != NULL) {
+ olddev->next = newdev;
+ }
+ else { /* First Device */
+ dev = newdev;
+ }
+ olddev = newdev;
+ newdev = NULL;
+ }
+ else { /* Device couldn't be opened */
+ csound->Message(csound,
+ Str("ALSA midi: Error opening device: %s\n"),
+ name);
+ }
+ }
+ }
+ if (snd_card_next(&card) < 0)
+ break;
+ } while (card >= 0);
+
+ snd_ctl_close(ctl);
+ }
+ }
+ else if (devName != NULL && devName[0] != '\0') {
+ dev = open_midi_device(csound, devName);
+ if (dev == NULL) {
+ free(name);
+ return -1;
+ }
+ }
+ *userData = (void*) dev;
+ free(name);
return 0;
}
@@ -698,58 +761,74 @@ static int midi_in_read(CSOUND *csound,
int bufpos = 0;
unsigned char c;
- (void) csound;
- while ((nbytes - bufpos) >= 3) {
- if (dev->bufpos >= dev->nbytes) { /* read from device */
- int n = (int) snd_rawmidi_read(dev->dev, &(dev->buf[0]), BUF_SIZE);
- dev->bufpos = 0;
- if (n <= 0) { /* until there is no more data left */
- dev->nbytes = 0;
- break;
+ if (!dev) { /* No devices */
+ /* fprintf(stderr, "No devices!"); */
+ return 0;
+ }
+ /* (void) csound; */
+ dev->bufpos = 0;
+ while (dev && dev->dev) {
+ while ((nbytes - bufpos) >= 3) {
+ if (dev->bufpos >= dev->nbytes) { /* read from device */
+ int n = (int) snd_rawmidi_read(dev->dev, &(dev->buf[0]), BUF_SIZE);
+ dev->bufpos = 0;
+ if (n <= 0) { /* until there is no more data left */
+ dev->nbytes = 0;
+ break;
+ }
+ dev->nbytes = n;
}
- dev->nbytes = n;
- }
- c = dev->buf[dev->bufpos++];
- if (c >= (unsigned char) 0xF8) { /* real time message */
- buf[bufpos++] = c;
- continue;
- }
- if (c == (unsigned char) 0xF7) /* end of system exclusive */
- c = dev->prvStatus;
- if (c < (unsigned char) 0x80) { /* data byte */
- if (dev->datreq <= 0)
+ c = dev->buf[dev->bufpos++];
+ if (c >= (unsigned char) 0xF8) { /* real time message */
+ buf[bufpos++] = c;
continue;
- if (dev->datreq == (int) dataBytes[(int) dev->prvStatus >> 4])
- dev->dat1 = c;
- else
- dev->dat2 = c;
- if (--(dev->datreq) != 0)
+ }
+ if (c == (unsigned char) 0xF7) /* end of system exclusive */
+ c = dev->prvStatus;
+ if (c < (unsigned char) 0x80) { /* data byte */
+ if (dev->datreq <= 0)
+ continue;
+ if (dev->datreq == (int) dataBytes[(int) dev->prvStatus >> 4])
+ dev->dat1 = c;
+ else
+ dev->dat2 = c;
+ if (--(dev->datreq) != 0)
+ continue;
+ dev->datreq = dataBytes[(int) dev->prvStatus >> 4];
+ buf[bufpos] = dev->prvStatus;
+ buf[bufpos + 1] = dev->dat1;
+ buf[bufpos + 2] = dev->dat2;
+ bufpos += (dev->datreq + 1);
continue;
- dev->datreq = dataBytes[(int) dev->prvStatus >> 4];
- buf[bufpos] = dev->prvStatus;
- buf[bufpos + 1] = dev->dat1;
- buf[bufpos + 2] = dev->dat2;
- bufpos += (dev->datreq + 1);
- continue;
- }
- else if (c < (unsigned char) 0xF0) { /* channel message */
- dev->prvStatus = c;
- dev->datreq = dataBytes[(int) c >> 4];
- continue;
+ }
+ else if (c < (unsigned char) 0xF0) { /* channel message */
+ dev->prvStatus = c;
+ dev->datreq = dataBytes[(int) c >> 4];
+ continue;
+ }
+ if (c < (unsigned char) 0xF4) /* ignore system messages */
+ dev->datreq = -1;
}
- if (c < (unsigned char) 0xF4) /* ignore system messages */
- dev->datreq = -1;
+ dev = dev->next;
}
return bufpos;
}
static int midi_in_close(CSOUND *csound, void *userData)
{
- int retval = 0;
+ int ret, retval = 0;
+ alsaMidiInputDevice *olddev, *dev = NULL;
(void) csound;
- if (userData != NULL) {
- retval = snd_rawmidi_close(((alsaMidiInputDevice*) userData)->dev);
- free(userData);
+ dev = (alsaMidiInputDevice*) userData;
+ while (dev != NULL) {
+ if (dev->dev) {
+ ret = snd_rawmidi_close(dev->dev);
+ }
+ olddev = dev;
+ dev = dev->next;
+ free(olddev);
+ if (retval != -1)
+ retval = ret;
}
return retval;
}
@@ -765,8 +844,8 @@ static int midi_out_open(CSOUND *csound, void **userData, const char *devName)
s = devName;
err = snd_rawmidi_open(NULL, &dev, s, SND_RAWMIDI_NONBLOCK);
if (err != 0) {
- csound->ErrorMsg(csound, Str("ALSA: error opening MIDI output device"));
- return -1;
+ csound->ErrorMsg(csound, Str("ALSA: error opening MIDI output device '%s'"));
+ return 0;
}
csound->Message(csound, Str("ALSA: opened MIDI output device '%s'\n"), s);
(*userData) = (void*) dev;