void scan_cycle(alsa_rawmidi_t *midi) { int card = -1, err; scan_t scan; midi_port_t **ports; //debug_log("scan: cleanup"); scan_cleanup(midi); scan.midi = midi; scan.iterator = &midi->scan.ports; snd_rawmidi_info_alloca(&scan.info); //debug_log("scan: rescan"); while ((err = snd_card_next(&card))>=0 && card>=0) { char name[32]; snprintf(name, sizeof(name), "hw:%d", card); if ((err = snd_ctl_open(&scan.ctl, name, SND_CTL_NONBLOCK))>=0) { scan_card(&scan); snd_ctl_close(scan.ctl); } else alsa_error("scan: snd_ctl_open", err); } // delayed open to workaround alsa<1.0.14 bug (can't open more than 1 subdevice if ctl is opened). ports = &midi->scan.ports; while (*ports) { midi_port_t *port = *ports; if (port->state == PORT_CREATED) ports = scan_port_open(midi, ports); else ports = &port->next; } }
int is_output(snd_ctl_t *ctl, int card, int device, int sub) { snd_rawmidi_info_t *info; int status; snd_rawmidi_info_alloca(&info); snd_rawmidi_info_set_device(info, device); snd_rawmidi_info_set_subdevice(info, sub); snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT); if ((status = snd_ctl_rawmidi_info(ctl, info)) < 0 && status != -ENXIO) { return status; } else if (status == 0) { return 1; } return 0; }
//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); }
void list_subdevice_info(snd_ctl_t *ctl, int card, int device) { snd_rawmidi_info_t *info; const char *name; const char *sub_name; int subs, subs_in, subs_out; int sub, in, out; int status; snd_rawmidi_info_alloca(&info); snd_rawmidi_info_set_device(info, device); snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT); snd_ctl_rawmidi_info(ctl, info); subs_in = snd_rawmidi_info_get_subdevices_count(info); snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT); snd_ctl_rawmidi_info(ctl, info); subs_out = snd_rawmidi_info_get_subdevices_count(info); subs = subs_in > subs_out ? subs_in : subs_out; sub = 0; in = out = 0; if ((status = is_output(ctl, card, device, sub)) < 0) { error("cannot get rawmidi information %d:%d: %s", card, device, snd_strerror(status)); return; } else if (status) out = 1; if (status == 0) { if ((status = is_input(ctl, card, device, sub)) < 0) { error("cannot get rawmidi information %d:%d: %s", card, device, snd_strerror(status)); return; } } else if (status) in = 1; if (status == 0) return; name = snd_rawmidi_info_get_name(info); sub_name = snd_rawmidi_info_get_subdevice_name(info); if (sub_name[0] == '\0') { if (subs == 1) { printf("%c%c hw:%d,%d %s\n", in ? 'I' : ' ', out ? 'O' : ' ', card, device, name); } else printf("%c%c hw:%d,%d %s (%d subdevices)\n", in ? 'I' : ' ', out ? 'O' : ' ', card, device, name, subs); } else { sub = 0; for (;;) { printf("%c%c hw:%d,%d,%d %s\n", in ? 'I' : ' ', out ? 'O' : ' ', card, device, sub, sub_name); if (++sub >= subs) break; in = is_input(ctl, card, device, sub); out = is_output(ctl, card, device, sub); snd_rawmidi_info_set_subdevice(info, sub); if (out) { snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT); if ((status = snd_ctl_rawmidi_info(ctl, info)) < 0) { error("cannot get rawmidi information %d:%d:%d: %s", card, device, sub, snd_strerror(status)); break; } } else { snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT); if ((status = snd_ctl_rawmidi_info(ctl, info)) < 0) { error("cannot get rawmidi information %d:%d:%d: %s", card, device, sub, snd_strerror(status)); break; } } sub_name = snd_rawmidi_info_get_subdevice_name(info); } } }