void list_midi_devices_on_card(int card) { snd_ctl_t *ctl; char name[32]; int device = -1; int status; sprintf(name, "hw:%d", card); if ((status = snd_ctl_open(&ctl, name, 0)) < 0) { error("cannot open control for card %d: %s", card, snd_strerror(status)); return; } do { status = snd_ctl_rawmidi_next_device(ctl, &device); if (status < 0) { error("cannot determine device number: %s", snd_strerror(status)); break; } if (device >= 0) { list_subdevice_info(ctl, card, device); } } while (device >= 0); snd_ctl_close(ctl); }
static void scan_card(scan_t *scan) { int device = -1; int err; while ((err = snd_ctl_rawmidi_next_device(scan->ctl, &device))>=0 && device >=0) { snd_rawmidi_info_set_device(scan->info, device); snd_rawmidi_info_set_stream(scan->info, SND_RAWMIDI_STREAM_INPUT); snd_rawmidi_info_set_subdevice(scan->info, 0); if ((err = snd_ctl_rawmidi_info(scan->ctl, scan->info))>=0) scan_device(scan); else if (err != -ENOENT) alsa_error("scan: snd_ctl_rawmidi_info on device", err); snd_rawmidi_info_set_stream(scan->info, SND_RAWMIDI_STREAM_OUTPUT); snd_rawmidi_info_set_subdevice(scan->info, 0); if ((err = snd_ctl_rawmidi_info(scan->ctl, scan->info))>=0) scan_device(scan); else if (err != -ENOENT) alsa_error("scan: snd_ctl_rawmidi_info on device", err); } }
// for each ALSA device, call iterator. userData is passed to the iterator // returns total number of iterations static int iterateRawmidiDevices(snd_rawmidi_stream_t direction, DeviceIteratorPtr iterator, void* userData) { int count = 0; int subdeviceCount; int card, dev, subDev; char devname[16]; int err; snd_ctl_t *handle; snd_rawmidi_t *rawmidi; snd_rawmidi_info_t *rawmidi_info; snd_ctl_card_info_t *card_info, *defcardinfo = NULL; UINT32 deviceID; int doContinue = TRUE; snd_rawmidi_info_malloc(&rawmidi_info); snd_ctl_card_info_malloc(&card_info); // 1st try "default" device if (direction == SND_RAWMIDI_STREAM_INPUT) { err = snd_rawmidi_open(&rawmidi, NULL, ALSA_DEFAULT_DEVICE_NAME, SND_RAWMIDI_NONBLOCK); } else if (direction == SND_RAWMIDI_STREAM_OUTPUT) { err = snd_rawmidi_open(NULL, &rawmidi, ALSA_DEFAULT_DEVICE_NAME, SND_RAWMIDI_NONBLOCK); } else { ERROR0("ERROR: iterateRawmidiDevices(): direction is neither" " SND_RAWMIDI_STREAM_INPUT nor SND_RAWMIDI_STREAM_OUTPUT\n"); err = MIDI_INVALID_ARGUMENT; } if (err < 0) { ERROR1("ERROR: snd_rawmidi_open (\"default\"): %s\n", snd_strerror(err)); } else { err = snd_rawmidi_info(rawmidi, rawmidi_info); snd_rawmidi_close(rawmidi); if (err < 0) { ERROR1("ERROR: snd_rawmidi_info (\"default\"): %s\n", snd_strerror(err)); } else { // try to get card info card = snd_rawmidi_info_get_card(rawmidi_info); if (card >= 0) { sprintf(devname, ALSA_HARDWARE_CARD, card); if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) { if (snd_ctl_card_info(handle, card_info) >= 0) { defcardinfo = card_info; } snd_ctl_close(handle); } } // call calback function for the device if (iterator != NULL) { doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, rawmidi_info, defcardinfo, userData); } count++; } } // iterate cards card = -1; TRACE0("testing for cards...\n"); if (snd_card_next(&card) >= 0) { TRACE1("Found card %d\n", card); while (doContinue && (card >= 0)) { sprintf(devname, ALSA_HARDWARE_CARD, card); TRACE1("Opening control for alsa rawmidi device \"%s\"...\n", devname); err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK); if (err < 0) { ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err)); } else { TRACE0("snd_ctl_open() SUCCESS\n"); err = snd_ctl_card_info(handle, card_info); if (err < 0) { ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", card, snd_strerror(err)); } else { TRACE0("snd_ctl_card_info() SUCCESS\n"); dev = -1; while (doContinue) { if (snd_ctl_rawmidi_next_device(handle, &dev) < 0) { ERROR0("snd_ctl_rawmidi_next_device\n"); } TRACE0("snd_ctl_rawmidi_next_device() SUCCESS\n"); if (dev < 0) { break; } snd_rawmidi_info_set_device(rawmidi_info, dev); snd_rawmidi_info_set_subdevice(rawmidi_info, 0); snd_rawmidi_info_set_stream(rawmidi_info, direction); err = snd_ctl_rawmidi_info(handle, rawmidi_info); TRACE0("after snd_ctl_rawmidi_info()\n"); if (err < 0) { if (err != -ENOENT) { ERROR2("ERROR: snd_ctl_rawmidi_info, card=%d: %s", card, snd_strerror(err)); } } else { TRACE0("snd_ctl_rawmidi_info() SUCCESS\n"); subdeviceCount = needEnumerateSubdevices(ALSA_RAWMIDI) ? snd_rawmidi_info_get_subdevices_count(rawmidi_info) : 1; if (iterator!=NULL) { for (subDev = 0; subDev < subdeviceCount; subDev++) { TRACE3(" Iterating %d,%d,%d\n", card, dev, subDev); deviceID = encodeDeviceID(card, dev, subDev); doContinue = (*iterator)(deviceID, rawmidi_info, card_info, userData); count++; TRACE0("returned from iterator\n"); if (!doContinue) { break; } } } else { count += subdeviceCount; } } } // of while(doContinue) } snd_ctl_close(handle); } if (snd_card_next(&card) < 0) { break; } } } else { ERROR0("No cards found!\n"); } snd_ctl_card_info_free(card_info); snd_rawmidi_info_free(rawmidi_info); return count; }
//list all the midi interfaces void list_midi_interfaces(char* midi_dev, int bufsize) { register int err; int cardNum; char devices[5][14]; char user_midi[bufsize]; // Start with first card cardNum = -1; for (;;) { snd_ctl_t *cardHandle; // Get next sound card's card number. When "cardNum" == -1, then ALSA // fetches the first card if ((err = snd_card_next(&cardNum)) < 0) { printf("Can't get the next card number: %s\n", snd_strerror(err)); break; } // No more cards? ALSA sets "cardNum" to -1 if so if (cardNum < 0) break; // Open this card's control interface. We specify only the card number -- not // any device nor sub-device too { char str[64]; sprintf(str, "hw:%i", cardNum); if ((err = snd_ctl_open(&cardHandle, str, 0)) < 0) { printf("Can't open card %i: %s\n", cardNum, snd_strerror(err)); continue; } } { int devNum; // Start with the first MIDI device on this card devNum = -1; for (;;) { snd_rawmidi_info_t *rawMidiInfo; register int subDevCount, i; // Get the number of the next MIDI device on this card if ((err = snd_ctl_rawmidi_next_device(cardHandle, &devNum)) < 0) { printf("Can't get next MIDI device number: %s\n", snd_strerror(err)); break; } // No more MIDI devices on this card? ALSA sets "devNum" to -1 if so. // NOTE: It's possible that this sound card may have no MIDI devices on it // at all, for example if it's only a digital audio card if (devNum < 0) break; // To get some info about the subdevices of this MIDI device (on the card), we need a // snd_rawmidi_info_t, so let's allocate one on the stack snd_rawmidi_info_alloca(&rawMidiInfo); memset(rawMidiInfo, 0, snd_rawmidi_info_sizeof()); // Tell ALSA which device (number) we want info about snd_rawmidi_info_set_device(rawMidiInfo, devNum); // Get info on the MIDI outs of this device snd_rawmidi_info_set_stream(rawMidiInfo, SND_RAWMIDI_STREAM_INPUT); i = -1; subDevCount = 1; // More subdevices? while (++i < subDevCount) { // Tell ALSA to fill in our snd_rawmidi_info_t with info on this subdevice snd_rawmidi_info_set_subdevice(rawMidiInfo, i); if ((err = snd_ctl_rawmidi_info(cardHandle, rawMidiInfo)) < 0) { printf("Can't get info for MIDI input subdevice hw:%i,%i,%i: %s\n", cardNum, devNum, i, snd_strerror(err)); continue; } // Print out how many subdevices (once only) if (!i) { subDevCount = snd_rawmidi_info_get_subdevices_count(rawMidiInfo); printf("\nFound %i MIDI input subdevices on card %i\n", subDevCount, cardNum); } // NOTE: If there's only one subdevice, then the subdevice number is immaterial, // and can be omitted when you specify the hardware name printf((subDevCount > 1 ? "[%i] - hw:%i,%i,%i\n" : "[%i] - hw:%i,%i\n"), i, cardNum, devNum, i); sprintf(devices[i], (subDevCount > 1 ? "hw:%i,%i,%i\n":"hw:%i,%i\n"),cardNum, devNum, i); } } } // Close the card's control interface after we're done with it snd_ctl_close(cardHandle); } snd_config_update_free_global(); printf("\nEnter the MIDI input to use (eg hw:1,0) > "); scanf("%s",user_midi); strncpy(midi_dev,user_midi,bufsize); }