// returns 0 if successful int openPCMfromDeviceID(int deviceID, snd_pcm_t** handle, int isSource, int hardware) { char buffer[200]; int ret; initAlsaSupport(); getDeviceStringFromDeviceID(buffer, deviceID, !hardware, ALSA_PCM); TRACE1("Opening ALSA device %s\n", buffer); ret = snd_pcm_open(handle, buffer, isSource?SND_PCM_STREAM_PLAYBACK:SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if (ret != 0) { ERROR1("snd_pcm_open returned error code %d \n", ret); *handle = NULL; } return ret; }
/* userData is assumed to be a pointer to ALSA_MIDIDeviceDescription. ALSA_MIDIDeviceDescription->index has to be set to the index of the device we want to get information of before this method is called the first time via iterateRawmidiDevices(). On each call of this method, ALSA_MIDIDeviceDescription->index is decremented. If it is equal to zero, we have reached the desired device, so action is taken. So after successful completion of iterateRawmidiDevices(), ALSA_MIDIDeviceDescription->index is zero. If it isn't, this is an indication of an error. */ static int deviceInfoIterator(UINT32 deviceID, snd_rawmidi_info_t *rawmidi_info, snd_ctl_card_info_t *cardinfo, void *userData) { char buffer[300]; ALSA_MIDIDeviceDescription* desc = (ALSA_MIDIDeviceDescription*)userData; #ifdef ALSA_MIDI_USE_PLUGHW int usePlugHw = 1; #else int usePlugHw = 0; #endif TRACE0("deviceInfoIterator\n"); initAlsaSupport(); if (desc->index == 0) { // we found the device with correct index desc->deviceID = deviceID; buffer[0]=' '; buffer[1]='['; // buffer[300] is enough to store the actual device string w/o overrun getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_RAWMIDI); strncat(buffer, "]", sizeof(buffer) - strlen(buffer) - 1); strncpy(desc->name, (cardinfo != NULL) ? snd_ctl_card_info_get_id(cardinfo) : snd_rawmidi_info_get_id(rawmidi_info), desc->strLen - strlen(buffer)); strncat(desc->name, buffer, desc->strLen - strlen(desc->name)); desc->description[0] = 0; if (cardinfo != NULL) { strncpy(desc->description, snd_ctl_card_info_get_name(cardinfo), desc->strLen); strncat(desc->description, ", ", desc->strLen - strlen(desc->description)); } strncat(desc->description, snd_rawmidi_info_get_id(rawmidi_info), desc->strLen - strlen(desc->description)); strncat(desc->description, ", ", desc->strLen - strlen(desc->description)); strncat(desc->description, snd_rawmidi_info_get_name(rawmidi_info), desc->strLen - strlen(desc->description)); TRACE2("Returning %s, %s\n", desc->name, desc->description); return FALSE; // do not continue iteration } desc->index--; return TRUE; }
int deviceInfoIterator(UINT32 deviceID, snd_pcm_info_t* pcminfo, snd_ctl_card_info_t* cardinfo, void* userData) { char buffer[300]; ALSA_AudioDeviceDescription* desc = (ALSA_AudioDeviceDescription*)userData; #ifdef ALSA_PCM_USE_PLUGHW int usePlugHw = 1; #else int usePlugHw = 0; #endif initAlsaSupport(); if (desc->index == 0) { // we found the device with correct index *(desc->maxSimultaneousLines) = needEnumerateSubdevices(ALSA_PCM) ? 1 : snd_pcm_info_get_subdevices_count(pcminfo); *desc->deviceID = deviceID; buffer[0]=' '; buffer[1]='['; // buffer[300] is enough to store the actual device string w/o overrun getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_PCM); strncat(buffer, "]", sizeof(buffer) - strlen(buffer) - 1); strncpy(desc->name, (cardinfo != NULL) ? snd_ctl_card_info_get_id(cardinfo) : snd_pcm_info_get_id(pcminfo), desc->strLen - strlen(buffer)); strncat(desc->name, buffer, desc->strLen - strlen(desc->name)); strncpy(desc->vendor, "ALSA (http://www.alsa-project.org)", desc->strLen); strncpy(desc->description, (cardinfo != NULL) ? snd_ctl_card_info_get_name(cardinfo) : snd_pcm_info_get_name(pcminfo), desc->strLen); strncat(desc->description, ", ", desc->strLen - strlen(desc->description)); strncat(desc->description, snd_pcm_info_get_id(pcminfo), desc->strLen - strlen(desc->description)); strncat(desc->description, ", ", desc->strLen - strlen(desc->description)); strncat(desc->description, snd_pcm_info_get_name(pcminfo), desc->strLen - strlen(desc->description)); getALSAVersion(desc->version, desc->strLen); TRACE4("Returning %s, %s, %s, %s\n", desc->name, desc->vendor, desc->description, desc->version); return FALSE; // do not continue iteration } desc->index--; return TRUE; }
/* direction has to be either SND_RAWMIDI_STREAM_INPUT or SND_RAWMIDI_STREAM_OUTPUT. Returns 0 on success. Otherwise, MIDI_OUT_OF_MEMORY, MIDI_INVALID_ARGUMENT or a negative ALSA error code is returned. */ INT32 openMidiDevice(snd_rawmidi_stream_t direction, INT32 deviceIndex, MidiDeviceHandle** handle) { snd_rawmidi_t* native_handle; snd_midi_event_t* event_parser = NULL; int err; UINT32 deviceID; char devicename[100]; #ifdef ALSA_MIDI_USE_PLUGHW int usePlugHw = 1; #else int usePlugHw = 0; #endif TRACE0("> openMidiDevice()\n"); (*handle) = (MidiDeviceHandle*) calloc(sizeof(MidiDeviceHandle), 1); if (!(*handle)) { ERROR0("ERROR: openDevice: out of memory\n"); return MIDI_OUT_OF_MEMORY; } // TODO: iterate to get dev ID from index err = getMidiDeviceID(direction, deviceIndex, &deviceID); TRACE1(" openMidiDevice(): deviceID: %d\n", (int) deviceID); getDeviceStringFromDeviceID(devicename, deviceID, usePlugHw, ALSA_RAWMIDI); TRACE1(" openMidiDevice(): deviceString: %s\n", devicename); // finally open the device if (direction == SND_RAWMIDI_STREAM_INPUT) { err = snd_rawmidi_open(&native_handle, NULL, devicename, SND_RAWMIDI_NONBLOCK); } else if (direction == SND_RAWMIDI_STREAM_OUTPUT) { err = snd_rawmidi_open(NULL, &native_handle, devicename, SND_RAWMIDI_NONBLOCK); } else { ERROR0(" ERROR: openMidiDevice(): direction is neither SND_RAWMIDI_STREAM_INPUT nor SND_RAWMIDI_STREAM_OUTPUT\n"); err = MIDI_INVALID_ARGUMENT; } if (err < 0) { ERROR1("< ERROR: openMidiDevice(): snd_rawmidi_open() returned %d\n", err); free(*handle); (*handle) = NULL; return err; } /* We opened with non-blocking behaviour to not get hung if the device is used by a different process. Writing, however, should be blocking. So we change it here. */ if (direction == SND_RAWMIDI_STREAM_OUTPUT) { err = snd_rawmidi_nonblock(native_handle, 0); if (err < 0) { ERROR1(" ERROR: openMidiDevice(): snd_rawmidi_nonblock() returned %d\n", err); snd_rawmidi_close(native_handle); free(*handle); (*handle) = NULL; return err; } } if (direction == SND_RAWMIDI_STREAM_INPUT) { err = snd_midi_event_new(EVENT_PARSER_BUFSIZE, &event_parser); if (err < 0) { ERROR1(" ERROR: openMidiDevice(): snd_midi_event_new() returned %d\n", err); snd_rawmidi_close(native_handle); free(*handle); (*handle) = NULL; return err; } } (*handle)->deviceHandle = (void*) native_handle; (*handle)->startTime = getTimeInMicroseconds(); (*handle)->platformData = event_parser; TRACE0("< openMidiDevice(): succeeded\n"); return err; }