alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (PLATFORM_API_BsdOS_ALSA_MidiUtils.c)

This example Java source code file (PLATFORM_API_BsdOS_ALSA_MidiUtils.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

alsa_mididevicedescription, error, error0, error1, error2, midi_success, null, snd_rawmidi_nonblock, snd_rawmidi_stream_input, snd_rawmidi_stream_output, success\\n, trace0, trace1, uint32

The PLATFORM_API_BsdOS_ALSA_MidiUtils.c Java example source code

/*
 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#define USE_ERROR
#define USE_TRACE

#include "PLATFORM_API_BsdOS_ALSA_MidiUtils.h"
#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
#include <string.h>
#include <sys/time.h>

static INT64 getTimeInMicroseconds() {
    struct timeval tv;

    gettimeofday(&tv, NULL);
    return (tv.tv_sec * 1000000UL) + tv.tv_usec;
}


const char* getErrorStr(INT32 err) {
        return snd_strerror((int) err);
}



// callback for iteration through devices
// returns TRUE if iteration should continue
typedef int (*DeviceIteratorPtr)(UINT32 deviceID,
                                 snd_rawmidi_info_t* rawmidi_info,
                                 snd_ctl_card_info_t* cardinfo,
                                 void *userData);

// 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;
}



int getMidiDeviceCount(snd_rawmidi_stream_t direction) {
    int deviceCount;
    TRACE0("> getMidiDeviceCount()\n");
    initAlsaSupport();
    deviceCount = iterateRawmidiDevices(direction, NULL, NULL);
    TRACE0("< getMidiDeviceCount()\n");
    return deviceCount;
}



/*
  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]='[';
        getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_RAWMIDI);
        strcat(buffer, "]");
        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;
}


static int getMIDIDeviceDescriptionByIndex(snd_rawmidi_stream_t direction,
                                           ALSA_MIDIDeviceDescription* desc) {
    initAlsaSupport();
    TRACE1(" getMIDIDeviceDescriptionByIndex (index = %d)\n", desc->index);
    iterateRawmidiDevices(direction, &deviceInfoIterator, desc);
    return (desc->index == 0) ? MIDI_SUCCESS : MIDI_INVALID_DEVICEID;
}



int initMIDIDeviceDescription(ALSA_MIDIDeviceDescription* desc, int index) {
    int ret = MIDI_SUCCESS;
    desc->index = index;
    desc->strLen = 200;
    desc->name = (char*) calloc(desc->strLen + 1, 1);
    desc->description = (char*) calloc(desc->strLen + 1, 1);
    if (! desc->name ||
        ! desc->description) {
        ret = MIDI_OUT_OF_MEMORY;
    }
    return ret;
}


void freeMIDIDeviceDescription(ALSA_MIDIDeviceDescription* desc) {
    if (desc->name) {
        free(desc->name);
    }
    if (desc->description) {
        free(desc->description);
    }
}


int getMidiDeviceName(snd_rawmidi_stream_t direction, int index, char *name,
                      UINT32 nameLength) {
    ALSA_MIDIDeviceDescription desc;
    int ret;

    TRACE1("getMidiDeviceName: nameLength: %d\n", (int) nameLength);
    ret = initMIDIDeviceDescription(&desc, index);
    if (ret == MIDI_SUCCESS) {
        TRACE0("getMidiDeviceName: initMIDIDeviceDescription() SUCCESS\n");
        ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
        if (ret == MIDI_SUCCESS) {
            TRACE1("getMidiDeviceName: desc.name: %s\n", desc.name);
            strncpy(name, desc.name, nameLength - 1);
            name[nameLength - 1] = 0;
        }
    }
    freeMIDIDeviceDescription(&desc);
    return ret;
}


int getMidiDeviceVendor(int index, char *name, UINT32 nameLength) {
    strncpy(name, ALSA_VENDOR, nameLength - 1);
    name[nameLength - 1] = 0;
    return MIDI_SUCCESS;
}


int getMidiDeviceDescription(snd_rawmidi_stream_t direction,
                             int index, char *name, UINT32 nameLength) {
    ALSA_MIDIDeviceDescription desc;
    int ret;

    ret = initMIDIDeviceDescription(&desc, index);
    if (ret == MIDI_SUCCESS) {
        ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
        if (ret == MIDI_SUCCESS) {
            strncpy(name, desc.description, nameLength - 1);
            name[nameLength - 1] = 0;
        }
    }
    freeMIDIDeviceDescription(&desc);
    return ret;
}


int getMidiDeviceVersion(int index, char *name, UINT32 nameLength) {
    getALSAVersion(name, nameLength);
    return MIDI_SUCCESS;
}


static int getMidiDeviceID(snd_rawmidi_stream_t direction, int index,
                           UINT32* deviceID) {
    ALSA_MIDIDeviceDescription desc;
    int ret;

    ret = initMIDIDeviceDescription(&desc, index);
    if (ret == MIDI_SUCCESS) {
        ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
        if (ret == MIDI_SUCCESS) {
            // TRACE1("getMidiDeviceName: desc.name: %s\n", desc.name);
            *deviceID = desc.deviceID;
        }
    }
    freeMIDIDeviceDescription(&desc);
    return ret;
}


/*
  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 = 0;
    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;
}



INT32 closeMidiDevice(MidiDeviceHandle* handle) {
    int err;

    TRACE0("> closeMidiDevice()\n");
    if (!handle) {
        ERROR0("< ERROR: closeMidiDevice(): handle is NULL\n");
        return MIDI_INVALID_HANDLE;
    }
    if (!handle->deviceHandle) {
        ERROR0("< ERROR: closeMidiDevice(): native handle is NULL\n");
        return MIDI_INVALID_HANDLE;
    }
    err = snd_rawmidi_close((snd_rawmidi_t*) handle->deviceHandle);
    TRACE1("  snd_rawmidi_close() returns %d\n", err);
    if (handle->platformData) {
        snd_midi_event_free((snd_midi_event_t*) handle->platformData);
    }
    free(handle);
    TRACE0("< closeMidiDevice: succeeded\n");
    return err;
}


INT64 getMidiTimestamp(MidiDeviceHandle* handle) {
    if (!handle) {
        ERROR0("< ERROR: closeMidiDevice(): handle is NULL\n");
        return MIDI_INVALID_HANDLE;
    }
    return getTimeInMicroseconds() - handle->startTime;
}


/* end */

Other Java examples (source code examples)

Here is a short list of links related to this Java PLATFORM_API_BsdOS_ALSA_MidiUtils.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.