提交 21b2c57a 编写于 作者: I ihse

8071469: Cleanup include and exclude of sound native libraries

Reviewed-by: amenkov, erikj
上级 e21e372e
......@@ -23,101 +23,50 @@
# questions.
#
LIBJSOUND_SRC_DIRS := \
LIBJSOUND_SRC_DIRS := $(wildcard \
$(TOPDIR)/src/java.desktop/share/native/libjsound \
$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjsound \
#
$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libjsound \
)
LIBJSOUND_CFLAGS := \
-I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
$(LIBJAVA_HEADER_FLAGS) \
$(foreach dir, $(LIBJSOUND_SRC_DIRS), -I$(dir)) \
-DUSE_PORTS=TRUE \
-DUSE_DAUDIO=TRUE \
#
LIBJSOUND_SRC_FILES := Utilities.c Platform.c
EXTRA_SOUND_JNI_LIBS :=
LIBJSOUND_MIDIFILES := \
MidiInDevice.c \
MidiInDeviceProvider.c \
MidiOutDevice.c \
MidiOutDeviceProvider.c \
PlatformMidi.c
# files needed for ports
LIBJSOUND_PORTFILES := \
PortMixerProvider.c \
PortMixer.c
# files needed for direct audio
LIBJSOUND_DAUDIOFILES := \
DirectAudioDeviceProvider.c \
DirectAudioDevice.c
ifeq ($(OPENJDK_TARGET_OS), windows)
EXTRA_SOUND_JNI_LIBS += jsoundds
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_WINDOWS \
ifneq ($(OPENJDK_TARGET_OS), solaris)
LIBJSOUND_CFLAGS += \
-DUSE_PLATFORM_MIDI_OUT=TRUE \
-DUSE_PLATFORM_MIDI_IN=TRUE \
-DUSE_PORTS=TRUE
LIBJSOUND_SRC_FILES += \
PLATFORM_API_WinOS_Charset_Util.cpp \
PLATFORM_API_WinOS_MidiIn.cpp \
PLATFORM_API_WinOS_MidiOut.c \
PLATFORM_API_WinOS_Util.c \
PLATFORM_API_WinOS_Ports.c
LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
endif # OPENJDK_TARGET_OS windows
#
endif
ifeq ($(OPENJDK_TARGET_OS), windows)
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_WINDOWS
endif
ifeq ($(OPENJDK_TARGET_OS), linux)
EXTRA_SOUND_JNI_LIBS += jsoundalsa
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_LINUX
endif # OPENJDK_TARGET_OS linux
endif
ifeq ($(OPENJDK_TARGET_OS), aix)
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_AIX
endif # OPENJDK_TARGET_OS aix
endif
ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBJSOUND_TOOLCHAIN := TOOLCHAIN_LINK_CXX
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_MACOSX \
-DUSE_PORTS=TRUE \
-DUSE_DAUDIO=TRUE \
-DUSE_PLATFORM_MIDI_OUT=TRUE \
-DUSE_PLATFORM_MIDI_IN=TRUE
LIBJSOUND_SRC_DIRS += $(TOPDIR)/src/java.desktop/macosx/native/libjsound
LIBJSOUND_SRC_FILES += \
PLATFORM_API_MacOSX_Utils.cpp \
PLATFORM_API_MacOSX_PCM.cpp \
PLATFORM_API_MacOSX_Ports.cpp \
PLATFORM_API_MacOSX_MidiIn.c \
PLATFORM_API_MacOSX_MidiOut.c \
PLATFORM_API_MacOSX_MidiUtils.c
LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_DAUDIOFILES)
endif # OPENJDK_TARGET_OS macosx
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_MACOSX
endif
ifeq ($(OPENJDK_TARGET_OS), solaris)
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_SOLARIS \
-DUSE_PORTS=TRUE \
-DUSE_DAUDIO=TRUE
LIBJSOUND_SRC_FILES += \
PLATFORM_API_SolarisOS_Utils.c \
PLATFORM_API_SolarisOS_Ports.c \
PLATFORM_API_SolarisOS_PCM.c
LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_DAUDIOFILES)
endif # OPENJDK_TARGET_OS solaris
LIBJSOUND_CFLAGS += -DEXTRA_SOUND_JNI_LIBS='"$(EXTRA_SOUND_JNI_LIBS)"'
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_SOLARIS
endif
$(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \
NAME := jsound, \
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := $(LIBJSOUND_SRC_FILES), \
TOOLCHAIN := $(LIBJSOUND_TOOLCHAIN), \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
......@@ -127,10 +76,11 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS_unix := -ljava -ljvm, \
LIBS_linux := $(ALSA_LIBS), \
LIBS_macosx := -framework CoreAudio -framework CoreFoundation \
-framework CoreServices -framework AudioUnit $(LIBCXX) \
-framework CoreMIDI -framework AudioToolbox, \
LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib winmm.lib, \
-framework CoreServices -framework AudioUnit \
-framework CoreMIDI -framework AudioToolbox $(LIBCXX), \
LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib dsound.lib winmm.lib user32.lib ole32.lib, \
))
$(BUILD_LIBJSOUND): $(call FindLib, java.base, java)
......@@ -138,61 +88,3 @@ $(BUILD_LIBJSOUND): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBJSOUND)
##########################################################################################
ifneq ($(filter jsoundalsa, $(EXTRA_SOUND_JNI_LIBS)), )
$(eval $(call SetupJdkLibrary, BUILD_LIBJSOUNDALSA, \
NAME := jsoundalsa, \
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := Utilities.c $(LIBJSOUND_MIDIFILES) $(LIBJSOUND_PORTFILES) \
$(LIBJSOUND_DAUDIOFILES) \
PLATFORM_API_LinuxOS_ALSA_CommonUtils.c \
PLATFORM_API_LinuxOS_ALSA_PCM.c \
PLATFORM_API_LinuxOS_ALSA_PCMUtils.c \
PLATFORM_API_LinuxOS_ALSA_MidiIn.c \
PLATFORM_API_LinuxOS_ALSA_MidiOut.c \
PLATFORM_API_LinuxOS_ALSA_MidiUtils.c \
PLATFORM_API_LinuxOS_ALSA_Ports.c, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(ALSA_CFLAGS) \
$(LIBJSOUND_CFLAGS) \
-DUSE_DAUDIO=TRUE \
-DUSE_PORTS=TRUE \
-DUSE_PLATFORM_MIDI_OUT=TRUE \
-DUSE_PLATFORM_MIDI_IN=TRUE, \
MAPFILE := $(TOPDIR)/make/mapfiles/libjsoundalsa/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(ALSA_LIBS) -ljava -ljvm, \
))
$(BUILD_LIBJSOUNDALSA): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBJSOUNDALSA)
endif
##########################################################################################
ifneq ($(filter jsoundds, $(EXTRA_SOUND_JNI_LIBS)), )
$(eval $(call SetupJdkLibrary, BUILD_LIBJSOUNDDS, \
NAME := jsoundds, \
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := Utilities.c $(LIBJSOUND_DAUDIOFILES) \
PLATFORM_API_WinOS_Charset_Util.cpp \
PLATFORM_API_WinOS_DirectSound.cpp, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJSOUND_CFLAGS) \
-DUSE_DAUDIO=TRUE, \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(JDKLIB_LIBS) dsound.lib winmm.lib user32.lib ole32.lib, \
))
$(BUILD_LIBJSOUNDDS): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBJSOUNDDS)
endif
......@@ -65,8 +65,6 @@ SUNWprivate_1.1 {
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVendor;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVersion;
Java_com_sun_media_sound_Platform_nGetExtraLibraries;
Java_com_sun_media_sound_Platform_nGetLibraryForFeature;
Java_com_sun_media_sound_Platform_nIsBigEndian;
Java_com_sun_media_sound_PortMixer_nClose;
Java_com_sun_media_sound_PortMixer_nControlGetFloatValue;
......
#
# Copyright (c) 2005, 2013, 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 library interface.
SUNWprivate_1.1 {
global:
Java_com_sun_media_sound_DirectAudioDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_DirectAudioDeviceProvider_nNewDirectAudioDeviceInfo;
Java_com_sun_media_sound_DirectAudioDevice_nAvailable;
Java_com_sun_media_sound_DirectAudioDevice_nClose;
Java_com_sun_media_sound_DirectAudioDevice_nFlush;
Java_com_sun_media_sound_DirectAudioDevice_nGetBufferSize;
Java_com_sun_media_sound_DirectAudioDevice_nGetBytePosition;
Java_com_sun_media_sound_DirectAudioDevice_nGetFormats;
Java_com_sun_media_sound_DirectAudioDevice_nIsStillDraining;
Java_com_sun_media_sound_DirectAudioDevice_nOpen;
Java_com_sun_media_sound_DirectAudioDevice_nRead;
Java_com_sun_media_sound_DirectAudioDevice_nRequiresServicing;
Java_com_sun_media_sound_DirectAudioDevice_nService;
Java_com_sun_media_sound_DirectAudioDevice_nSetBytePosition;
Java_com_sun_media_sound_DirectAudioDevice_nStart;
Java_com_sun_media_sound_DirectAudioDevice_nStop;
Java_com_sun_media_sound_DirectAudioDevice_nWrite;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetDescription;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetName;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetVendor;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetVersion;
Java_com_sun_media_sound_MidiInDevice_nClose;
Java_com_sun_media_sound_MidiInDevice_nGetMessages;
Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp;
Java_com_sun_media_sound_MidiInDevice_nOpen;
Java_com_sun_media_sound_MidiInDevice_nStart;
Java_com_sun_media_sound_MidiInDevice_nStop;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetDescription;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetName;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVendor;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVersion;
Java_com_sun_media_sound_MidiOutDevice_nClose;
Java_com_sun_media_sound_MidiOutDevice_nGetTimeStamp;
Java_com_sun_media_sound_MidiOutDevice_nOpen;
Java_com_sun_media_sound_MidiOutDevice_nSendLongMessage;
Java_com_sun_media_sound_MidiOutDevice_nSendShortMessage;
Java_com_sun_media_sound_PortMixerProvider_nGetNumDevices;
Java_com_sun_media_sound_PortMixerProvider_nNewPortMixerInfo;
Java_com_sun_media_sound_PortMixer_nClose;
Java_com_sun_media_sound_PortMixer_nControlGetFloatValue;
Java_com_sun_media_sound_PortMixer_nControlGetIntValue;
Java_com_sun_media_sound_PortMixer_nControlSetFloatValue;
Java_com_sun_media_sound_PortMixer_nControlSetIntValue;
Java_com_sun_media_sound_PortMixer_nGetControls;
Java_com_sun_media_sound_PortMixer_nGetPortCount;
Java_com_sun_media_sound_PortMixer_nGetPortName;
Java_com_sun_media_sound_PortMixer_nGetPortType;
Java_com_sun_media_sound_PortMixer_nOpen;
local:
*;
};
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2018, 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
......@@ -38,23 +38,9 @@ import java.util.StringTokenizer;
final class Platform {
// native library we need to load
private static final String libNameMain = "jsound";
private static final String libNameALSA = "jsoundalsa";
private static final String libNameDSound = "jsoundds";
private static final String libName = "jsound";
// extra libs handling: bit flags for each different library
public static final int LIB_MAIN = 1;
public static final int LIB_ALSA = 2;
public static final int LIB_DSOUND = 4;
// bit field of the constants above. Willbe set in loadLibraries
private static int loadedLibs = 0;
// features: the main native library jsound reports which feature is
// contained in which lib
public static final int FEATURE_MIDIIO = 1;
public static final int FEATURE_PORTS = 2;
public static final int FEATURE_DIRECT_AUDIO = 3;
private static boolean isNativeLibLoaded;
// SYSTEM CHARACTERISTICS
// vary according to hardware architecture
......@@ -66,7 +52,6 @@ final class Platform {
if(Printer.trace)Printer.trace(">> Platform.java: static");
loadLibraries();
readProperties();
}
/**
......@@ -95,72 +80,37 @@ final class Platform {
private static void loadLibraries() {
if(Printer.trace)Printer.trace(">>Platform.loadLibraries");
// load the main library
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
System.loadLibrary(libNameMain);
return null;
});
// just for the heck of it...
loadedLibs |= LIB_MAIN;
// now try to load extra libs. They are defined at compile time in the Makefile
// with the define EXTRA_SOUND_JNI_LIBS
String extraLibs = nGetExtraLibraries();
// the string is the libraries, separated by white space
StringTokenizer st = new StringTokenizer(extraLibs);
while (st.hasMoreTokens()) {
final String lib = st.nextToken();
try {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
System.loadLibrary(lib);
return null;
});
if (lib.equals(libNameALSA)) {
loadedLibs |= LIB_ALSA;
if (Printer.debug) Printer.debug("Loaded ALSA lib successfully.");
} else if (lib.equals(libNameDSound)) {
loadedLibs |= LIB_DSOUND;
if (Printer.debug) Printer.debug("Loaded DirectSound lib successfully.");
} else {
if (Printer.err) Printer.err("Loaded unknown lib '"+lib+"' successfully.");
}
} catch (Throwable t) {
if (Printer.err) Printer.err("Couldn't load library "+lib+": "+t.toString());
}
// load the native library
isNativeLibLoaded = true;
try {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
System.loadLibrary(libName);
return null;
});
} catch (Throwable t) {
if (Printer.err) Printer.err("Couldn't load library "+libName+": "+t.toString());
isNativeLibLoaded = false;
}
if (isNativeLibLoaded) {
bigEndian = nIsBigEndian();
}
}
static boolean isMidiIOEnabled() {
return isFeatureLibLoaded(FEATURE_MIDIIO);
if (Printer.debug) Printer.debug("Platform: Checking for MidiIO; library is loaded=" + isNativeLibLoaded);
return isNativeLibLoaded;
}
static boolean isPortsEnabled() {
return isFeatureLibLoaded(FEATURE_PORTS);
if (Printer.debug) Printer.debug("Platform: Checking for Ports; library is loaded=" + isNativeLibLoaded);
return isNativeLibLoaded;
}
static boolean isDirectAudioEnabled() {
return isFeatureLibLoaded(FEATURE_DIRECT_AUDIO);
}
private static boolean isFeatureLibLoaded(int feature) {
if (Printer.debug) Printer.debug("Platform: Checking for feature "+feature+"...");
int requiredLib = nGetLibraryForFeature(feature);
boolean isLoaded = (requiredLib != 0) && ((loadedLibs & requiredLib) == requiredLib);
if (Printer.debug) Printer.debug(" ...needs library "+requiredLib+". Result is loaded="+isLoaded);
return isLoaded;
if (Printer.debug) Printer.debug("Platform: Checking for DirectAudio; library is loaded=" + isNativeLibLoaded);
return isNativeLibLoaded;
}
// the following native methods are implemented in Platform.c
// the following native method is implemented in Platform.c
private static native boolean nIsBigEndian();
private static native String nGetExtraLibraries();
private static native int nGetLibraryForFeature(int feature);
/**
* Read the required system properties.
*/
private static void readProperties() {
// $$fb 2002-03-06: implement check for endianness in native. Facilitates porting !
bigEndian = nIsBigEndian();
}
}
/*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2018, 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
......@@ -41,83 +41,3 @@ DEF_STATIC_JNI_OnLoad
JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_Platform_nIsBigEndian(JNIEnv *env, jclass clss) {
return UTIL_IsBigEndianPlatform();
}
/*
* Class: com_sun_media_sound_Platform
* Method: nGetExtraLibraries
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_sun_media_sound_Platform_nGetExtraLibraries(JNIEnv *env, jclass clss) {
return (*env)->NewStringUTF(env, EXTRA_SOUND_JNI_LIBS);
}
/*
* Class: com_sun_media_sound_Platform
* Method: nGetLibraryForFeature
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_sun_media_sound_Platform_nGetLibraryForFeature
(JNIEnv *env, jclass clazz, jint feature) {
// for every OS
#if X_PLATFORM == X_WINDOWS
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_DSOUND;
}
#endif
#if (X_PLATFORM == X_SOLARIS)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_MAIN;
}
#endif
#if (X_PLATFORM == X_LINUX)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_ALSA;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_ALSA;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_ALSA;
}
#endif
#if (X_PLATFORM == X_MACOSX)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_MAIN;
}
#endif
#if (X_PLATFORM == X_BSD)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
#ifdef __FreeBSD__
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_ALSA;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_ALSA;
#else
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
// XXXBSD: When native Direct Audio support is ported change
// this back to returning com_sun_media_sound_Platform_LIB_MAIN
return 0;
#endif
}
#endif
return 0;
}
/*
* 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_CommonUtils.h"
static void alsaDebugOutput(const char *file, int line, const char *function, int err, const char *fmt, ...) {
#ifdef USE_ERROR
va_list args;
va_start(args, fmt);
printf("%s:%d function %s: error %d: %s\n", file, line, function, err, snd_strerror(err));
if (strlen(fmt) > 0) {
vprintf(fmt, args);
}
va_end(args);
#endif
}
static int alsa_inited = 0;
static int alsa_enumerate_pcm_subdevices = FALSE; // default: no
static int alsa_enumerate_midi_subdevices = FALSE; // default: no
void initAlsaSupport() {
char* enumerate;
if (!alsa_inited) {
alsa_inited = TRUE;
snd_lib_error_set_handler(&alsaDebugOutput);
enumerate = getenv(ENV_ENUMERATE_PCM_SUBDEVICES);
if (enumerate != NULL && strlen(enumerate) > 0
&& (enumerate[0] != 'f') // false
&& (enumerate[0] != 'F') // False
&& (enumerate[0] != 'n') // no
&& (enumerate[0] != 'N')) { // NO
alsa_enumerate_pcm_subdevices = TRUE;
}
#ifdef ALSA_MIDI_ENUMERATE_SUBDEVICES
alsa_enumerate_midi_subdevices = TRUE;
#endif
}
}
/* if true (non-zero), ALSA sub devices should be listed as separate devices
*/
int needEnumerateSubdevices(int isMidi) {
initAlsaSupport();
return isMidi ? alsa_enumerate_midi_subdevices
: alsa_enumerate_pcm_subdevices;
}
/*
* deviceID contains packed card, device and subdevice numbers
* each number takes 10 bits
* "default" device has id == ALSA_DEFAULT_DEVICE_ID
*/
UINT32 encodeDeviceID(int card, int device, int subdevice) {
return (((card & 0x3FF) << 20) | ((device & 0x3FF) << 10)
| (subdevice & 0x3FF)) + 1;
}
void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice,
int isMidi) {
deviceID--;
*card = (deviceID >> 20) & 0x3FF;
*device = (deviceID >> 10) & 0x3FF;
if (needEnumerateSubdevices(isMidi)) {
*subdevice = deviceID & 0x3FF;
} else {
*subdevice = -1; // ALSA will choose any subdevices
}
}
void getDeviceString(char* buffer, int card, int device, int subdevice,
int usePlugHw, int isMidi) {
if (needEnumerateSubdevices(isMidi)) {
sprintf(buffer, "%s:%d,%d,%d",
usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE,
card, device, subdevice);
} else {
sprintf(buffer, "%s:%d,%d",
usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE,
card, device);
}
}
void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID,
int usePlugHw, int isMidi) {
int card, device, subdevice;
if (deviceID == ALSA_DEFAULT_DEVICE_ID) {
strcpy(buffer, ALSA_DEFAULT_DEVICE_NAME);
} else {
decodeDeviceID(deviceID, &card, &device, &subdevice, isMidi);
getDeviceString(buffer, card, device, subdevice, usePlugHw, isMidi);
}
}
static int hasGottenALSAVersion = FALSE;
#define ALSAVersionString_LENGTH 200
static char ALSAVersionString[ALSAVersionString_LENGTH];
void getALSAVersion(char* buffer, int len) {
if (!hasGottenALSAVersion) {
// get alsa version from proc interface
FILE* file;
int curr, len, totalLen, inVersionString;
file = fopen(ALSA_VERSION_PROC_FILE, "r");
ALSAVersionString[0] = 0;
if (file) {
if (NULL != fgets(ALSAVersionString, ALSAVersionString_LENGTH, file)) {
// parse for version number
totalLen = strlen(ALSAVersionString);
inVersionString = FALSE;
len = 0;
curr = 0;
while (curr < totalLen) {
if (!inVersionString) {
// is this char the beginning of a version string ?
if (ALSAVersionString[curr] >= '0'
&& ALSAVersionString[curr] <= '9') {
inVersionString = TRUE;
}
}
if (inVersionString) {
// the version string ends with white space
if (ALSAVersionString[curr] <= 32) {
break;
}
if (curr != len) {
// copy this char to the beginning of the string
ALSAVersionString[len] = ALSAVersionString[curr];
}
len++;
}
curr++;
}
// remove trailing dots
while ((len > 0) && (ALSAVersionString[len - 1] == '.')) {
len--;
}
// null terminate
ALSAVersionString[len] = 0;
}
fclose(file);
hasGottenALSAVersion = TRUE;
}
}
strncpy(buffer, ALSAVersionString, len);
}
/* end */
/*
* 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.
*/
#include <alsa/asoundlib.h>
#include "Utilities.h"
#ifndef PLATFORM_API_BSDOS_ALSA_COMMONUTILS_H_INCLUDED
#define PLATFORM_API_BSDOS_ALSA_COMMONUTILS_H_INCLUDED
#define ALSA_VERSION_PROC_FILE "/proc/asound/version"
#define ALSA_HARDWARE "hw"
#define ALSA_HARDWARE_CARD ALSA_HARDWARE":%d"
#define ALSA_HARDWARE_DEVICE ALSA_HARDWARE_CARD",%d"
#define ALSA_HARDWARE_SUBDEVICE ALSA_HARDWARE_DEVICE",%d"
#define ALSA_PLUGHARDWARE "plughw"
#define ALSA_DEFAULT_DEVICE_NAME "default"
#define ALSA_DEFAULT_DEVICE_ID (0)
#define ALSA_PCM (0)
#define ALSA_RAWMIDI (1)
// for use in info objects
#define ALSA_VENDOR "ALSA (http://www.alsa-project.org)"
// Environment variable for inclusion of subdevices in device listing.
// If this variable is unset or "no", then subdevices are ignored, and
// it's ALSA's choice which one to use (enables hardware mixing)
#define ENV_ENUMERATE_PCM_SUBDEVICES "ALSA_ENUMERATE_PCM_SUBDEVICES"
// if defined, subdevices are listed.
//#undef ALSA_MIDI_ENUMERATE_SUBDEVICES
#define ALSA_MIDI_ENUMERATE_SUBDEVICES
// must be called before any ALSA calls
void initAlsaSupport();
/* if true (non-zero), ALSA sub devices should be listed as separate devices
*/
int needEnumerateSubdevices(int isMidi);
/*
* deviceID contains packed card, device and subdevice numbers
* each number takes 10 bits
* "default" device has id == ALSA_DEFAULT_DEVICE_ID
*/
UINT32 encodeDeviceID(int card, int device, int subdevice);
void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice,
int isMidi);
void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID,
int usePlugHw, int isMidi);
void getALSAVersion(char* buffer, int len);
#endif // PLATFORM_API_BSDOS_ALSA_COMMONUTILS_H_INCLUDED
/*
* 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
#if USE_PLATFORM_MIDI_IN == TRUE
#include <alsa/asoundlib.h>
#include "PlatformMidi.h"
#include "PLATFORM_API_BsdOS_ALSA_MidiUtils.h"
#if defined(i586)
#include <sys/utsname.h>
#endif
/*
* Helper methods
*/
static inline UINT32 packMessage(int status, int data1, int data2) {
return ((status & 0xFF) | ((data1 & 0xFF) << 8) | ((data2 & 0xFF) << 16));
}
static void setShortMessage(MidiMessage* message,
int status, int data1, int data2) {
message->type = SHORT_MESSAGE;
message->data.s.packedMsg = packMessage(status, data1, data2);
}
static void setRealtimeMessage(MidiMessage* message, int status) {
setShortMessage(message, status, 0, 0);
}
static void set14bitMessage(MidiMessage* message, int status, int value) {
TRACE3("14bit value: %d, lsb: %d, msb: %d\n", value, value & 0x7F, (value >> 7) & 0x7F);
value &= 0x3FFF;
TRACE3("14bit value (2): %d, lsb: %d, msb: %d\n", value, value & 0x7F, (value >> 7) & 0x7F);
setShortMessage(message, status,
value & 0x7F,
(value >> 7) & 0x7F);
}
/*
* implementation of the platform-dependent
* MIDI in functions declared in PlatformMidi.h
*/
char* MIDI_IN_GetErrorStr(INT32 err) {
return (char*) getErrorStr(err);
}
INT32 MIDI_IN_GetNumDevices() {
/* Workaround for 6842956: 32bit app on 64bit bsd
* gets assertion failure trying to open midiIn ports.
* Untill the issue is fixed in ALSA
* (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4807)
* report no midi in devices in the configuration.
*/
#if defined(i586)
static int jre32onbsd64 = -1;
if (jre32onbsd64 < 0) {
jre32onbsd64 = 0;
/* The workaround may be disabled setting "JAVASOUND_ENABLE_MIDIIN"
* environment variable.
*/
if (getenv("JAVASOUND_ENABLE_MIDIIN") == NULL) {
struct utsname u;
jre32onbsd64 = 0;
if (uname(&u) == 0) {
if (strstr(u.machine, "64") != NULL) {
TRACE0("jre32 on bsd64 detected - report no midiIn devices\n");
jre32onbsd64 = 1;
}
}
}
}
if (jre32onbsd64) {
return 0;
}
#endif
TRACE0("MIDI_IN_GetNumDevices()\n");
return getMidiDeviceCount(SND_RAWMIDI_STREAM_INPUT);
}
INT32 MIDI_IN_GetDeviceName(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceName(SND_RAWMIDI_STREAM_INPUT, deviceIndex,
name, nameLength);
return ret;
}
INT32 MIDI_IN_GetDeviceVendor(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceVendor(deviceIndex, name, nameLength);
return ret;
}
INT32 MIDI_IN_GetDeviceDescription(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceDescription(SND_RAWMIDI_STREAM_INPUT, deviceIndex,
name, nameLength);
return ret;
}
INT32 MIDI_IN_GetDeviceVersion(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceVersion(deviceIndex, name, nameLength);
return ret;
}
/*************************************************************************/
INT32 MIDI_IN_OpenDevice(INT32 deviceIndex, MidiDeviceHandle** handle) {
INT32 ret;
TRACE0("> MIDI_IN_OpenDevice\n");
ret = openMidiDevice(SND_RAWMIDI_STREAM_INPUT, deviceIndex, handle);
TRACE1("< MIDI_IN_OpenDevice: returning %d\n", (int) ret);
return ret;
}
INT32 MIDI_IN_CloseDevice(MidiDeviceHandle* handle) {
INT32 ret;
TRACE0("> MIDI_IN_CloseDevice\n");
ret = closeMidiDevice(handle);
TRACE1("< MIDI_IN_CloseDevice: returning %d\n", (int) ret);
return ret;
}
INT32 MIDI_IN_StartDevice(MidiDeviceHandle* handle) {
TRACE0("MIDI_IN_StartDevice\n");
return MIDI_SUCCESS;
}
INT32 MIDI_IN_StopDevice(MidiDeviceHandle* handle) {
TRACE0("MIDI_IN_StopDevice\n");
return MIDI_SUCCESS;
}
INT64 MIDI_IN_GetTimeStamp(MidiDeviceHandle* handle) {
return getMidiTimestamp(handle);
}
/* read the next message from the queue */
MidiMessage* MIDI_IN_GetMessage(MidiDeviceHandle* handle) {
snd_seq_event_t alsa_message;
MidiMessage* jdk_message;
int err;
char buffer[1];
int status;
TRACE0("> MIDI_IN_GetMessage\n");
if (!handle) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): handle is NULL\n");
return NULL;
}
if (!handle->deviceHandle) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): native handle is NULL\n");
return NULL;
}
if (!handle->platformData) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): platformData is NULL\n");
return NULL;
}
/* For MIDI In, the device is left in non blocking mode. So if there is
no data from the device, snd_rawmidi_read() returns with -11 (EAGAIN).
This results in jumping back to the Java layer. */
while (TRUE) {
TRACE0("before snd_rawmidi_read()\n");
err = snd_rawmidi_read((snd_rawmidi_t*) handle->deviceHandle, buffer, 1);
TRACE0("after snd_rawmidi_read()\n");
if (err != 1) {
ERROR2("< ERROR: MIDI_IN_GetMessage(): snd_rawmidi_read() returned %d : %s\n", err, snd_strerror(err));
return NULL;
}
// printf("received byte: %d\n", buffer[0]);
err = snd_midi_event_encode_byte((snd_midi_event_t*) handle->platformData,
(int) buffer[0],
&alsa_message);
if (err == 1) {
break;
} else if (err < 0) {
ERROR1("< ERROR: MIDI_IN_GetMessage(): snd_midi_event_encode_byte() returned %d\n", err);
return NULL;
}
}
jdk_message = (MidiMessage*) calloc(sizeof(MidiMessage), 1);
if (!jdk_message) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): out of memory\n");
return NULL;
}
// TODO: tra
switch (alsa_message.type) {
case SND_SEQ_EVENT_NOTEON:
case SND_SEQ_EVENT_NOTEOFF:
case SND_SEQ_EVENT_KEYPRESS:
status = (alsa_message.type == SND_SEQ_EVENT_KEYPRESS) ? 0xA0 :
(alsa_message.type == SND_SEQ_EVENT_NOTEON) ? 0x90 : 0x80;
status |= alsa_message.data.note.channel;
setShortMessage(jdk_message, status,
alsa_message.data.note.note,
alsa_message.data.note.velocity);
break;
case SND_SEQ_EVENT_CONTROLLER:
status = 0xB0 | alsa_message.data.control.channel;
setShortMessage(jdk_message, status,
alsa_message.data.control.param,
alsa_message.data.control.value);
break;
case SND_SEQ_EVENT_PGMCHANGE:
case SND_SEQ_EVENT_CHANPRESS:
status = (alsa_message.type == SND_SEQ_EVENT_PGMCHANGE) ? 0xC0 : 0xD0;
status |= alsa_message.data.control.channel;
setShortMessage(jdk_message, status,
alsa_message.data.control.value, 0);
break;
case SND_SEQ_EVENT_PITCHBEND:
status = 0xE0 | alsa_message.data.control.channel;
// $$mp 2003-09-23:
// possible hack to work around a bug in ALSA. Necessary for
// ALSA 0.9.2. May be fixed in newer versions of ALSA.
// alsa_message.data.control.value ^= 0x2000;
// TRACE1("pitchbend value: %d\n", alsa_message.data.control.value);
set14bitMessage(jdk_message, status,
alsa_message.data.control.value);
break;
/* System exclusive messages */
case SND_SEQ_EVENT_SYSEX:
jdk_message->type = LONG_MESSAGE;
jdk_message->data.l.size = alsa_message.data.ext.len;
jdk_message->data.l.data = malloc(alsa_message.data.ext.len);
if (jdk_message->data.l.data == NULL) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): out of memory\n");
free(jdk_message);
jdk_message = NULL;
} else {
memcpy(jdk_message->data.l.data, alsa_message.data.ext.ptr, alsa_message.data.ext.len);
}
break;
/* System common messages */
case SND_SEQ_EVENT_QFRAME:
setShortMessage(jdk_message, 0xF1,
alsa_message.data.control.value & 0x7F, 0);
break;
case SND_SEQ_EVENT_SONGPOS:
set14bitMessage(jdk_message, 0xF2,
alsa_message.data.control.value);
break;
case SND_SEQ_EVENT_SONGSEL:
setShortMessage(jdk_message, 0xF3,
alsa_message.data.control.value & 0x7F, 0);
break;
case SND_SEQ_EVENT_TUNE_REQUEST:
setRealtimeMessage(jdk_message, 0xF6);
break;
/* System realtime messages */
case SND_SEQ_EVENT_CLOCK:
setRealtimeMessage(jdk_message, 0xF8);
break;
case SND_SEQ_EVENT_START:
setRealtimeMessage(jdk_message, 0xFA);
break;
case SND_SEQ_EVENT_CONTINUE:
setRealtimeMessage(jdk_message, 0xFB);
break;
case SND_SEQ_EVENT_STOP:
setRealtimeMessage(jdk_message, 0xFC);
break;
case SND_SEQ_EVENT_SENSING:
setRealtimeMessage(jdk_message, 0xFE);
break;
case SND_SEQ_EVENT_RESET:
setRealtimeMessage(jdk_message, 0xFF);
break;
default:
ERROR0("< ERROR: MIDI_IN_GetMessage(): unhandled ALSA MIDI message type\n");
free(jdk_message);
jdk_message = NULL;
}
// set timestamp
if (jdk_message != NULL) {
jdk_message->timestamp = getMidiTimestamp(handle);
}
TRACE1("< MIDI_IN_GetMessage: returning %p\n", jdk_message);
return jdk_message;
}
void MIDI_IN_ReleaseMessage(MidiDeviceHandle* handle, MidiMessage* msg) {
if (!msg) {
ERROR0("< ERROR: MIDI_IN_ReleaseMessage(): message is NULL\n");
return;
}
if (msg->type == LONG_MESSAGE && msg->data.l.data) {
free(msg->data.l.data);
}
free(msg);
}
#endif /* USE_PLATFORM_MIDI_IN */
/*
* 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
#if USE_PLATFORM_MIDI_OUT == TRUE
#include <alsa/asoundlib.h>
#include "PlatformMidi.h"
#include "PLATFORM_API_BsdOS_ALSA_MidiUtils.h"
static int CHANNEL_MESSAGE_LENGTH[] = {
-1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 3, 3, 2, 2, 3 };
/* 8x 9x Ax Bx Cx Dx Ex */
static int SYSTEM_MESSAGE_LENGTH[] = {
-1, 2, 3, 2, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1 };
/* F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF */
// the returned length includes the status byte.
// for illegal messages, -1 is returned.
static int getShortMessageLength(int status) {
int dataLength = 0;
if (status < 0xF0) { // channel voice message
dataLength = CHANNEL_MESSAGE_LENGTH[(status >> 4) & 0xF];
} else {
dataLength = SYSTEM_MESSAGE_LENGTH[status & 0xF];
}
return dataLength;
}
/*
* implementation of the platform-dependent
* MIDI out functions declared in PlatformMidi.h
*/
char* MIDI_OUT_GetErrorStr(INT32 err) {
return (char*) getErrorStr(err);
}
INT32 MIDI_OUT_GetNumDevices() {
TRACE0("MIDI_OUT_GetNumDevices()\n");
return getMidiDeviceCount(SND_RAWMIDI_STREAM_OUTPUT);
}
INT32 MIDI_OUT_GetDeviceName(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceName()\n");
return getMidiDeviceName(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex,
name, nameLength);
}
INT32 MIDI_OUT_GetDeviceVendor(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceVendor()\n");
return getMidiDeviceVendor(deviceIndex, name, nameLength);
}
INT32 MIDI_OUT_GetDeviceDescription(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceDescription()\n");
return getMidiDeviceDescription(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex,
name, nameLength);
}
INT32 MIDI_OUT_GetDeviceVersion(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceVersion()\n");
return getMidiDeviceVersion(deviceIndex, name, nameLength);
}
/* *************************** MidiOutDevice implementation *************** */
INT32 MIDI_OUT_OpenDevice(INT32 deviceIndex, MidiDeviceHandle** handle) {
TRACE1("MIDI_OUT_OpenDevice(): deviceIndex: %d\n", (int) deviceIndex);
return openMidiDevice(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex, handle);
}
INT32 MIDI_OUT_CloseDevice(MidiDeviceHandle* handle) {
TRACE0("MIDI_OUT_CloseDevice()\n");
return closeMidiDevice(handle);
}
INT64 MIDI_OUT_GetTimeStamp(MidiDeviceHandle* handle) {
return getMidiTimestamp(handle);
}
INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg,
UINT32 timestamp) {
int err;
int status;
int data1;
int data2;
char buffer[3];
TRACE2("> MIDI_OUT_SendShortMessage() %x, time: %u\n", packedMsg, (unsigned int) timestamp);
if (!handle) {
ERROR0("< ERROR: MIDI_OUT_SendShortMessage(): handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
if (!handle->deviceHandle) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): native handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
status = (packedMsg & 0xFF);
buffer[0] = (char) status;
buffer[1] = (char) ((packedMsg >> 8) & 0xFF);
buffer[2] = (char) ((packedMsg >> 16) & 0xFF);
TRACE4("status: %d, data1: %d, data2: %d, length: %d\n", (int) buffer[0], (int) buffer[1], (int) buffer[2], getShortMessageLength(status));
err = snd_rawmidi_write((snd_rawmidi_t*) handle->deviceHandle, buffer, getShortMessageLength(status));
if (err < 0) {
ERROR1(" ERROR: MIDI_OUT_SendShortMessage(): snd_rawmidi_write() returned %d\n", err);
}
TRACE0("< MIDI_OUT_SendShortMessage()\n");
return err;
}
INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data,
UINT32 size, UINT32 timestamp) {
int err;
TRACE2("> MIDI_OUT_SendLongMessage() size %u, time: %u\n", (unsigned int) size, (unsigned int) timestamp);
if (!handle) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
if (!handle->deviceHandle) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): native handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
if (!data) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): data is NULL\n");
return MIDI_INVALID_HANDLE;
}
err = snd_rawmidi_write((snd_rawmidi_t*) handle->deviceHandle,
data, size);
if (err < 0) {
ERROR1(" ERROR: MIDI_OUT_SendLongMessage(): snd_rawmidi_write() returned %d\n", err);
}
TRACE0("< MIDI_OUT_SendLongMessage()\n");
return err;
}
#endif /* USE_PLATFORM_MIDI_OUT */
/*
* Copyright (c) 2003, 2014, 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]='[';
// 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;
}
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 */
/*
* 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.
*/
#include <alsa/asoundlib.h>
#include "Utilities.h"
#include "PlatformMidi.h"
#ifndef PLATFORM_API_BSDOS_ALSA_MIDIUTILS_H_INCLUDED
#define PLATFORM_API_BSDOS_ALSA_MIDIUTILS_H_INCLUDED
#define EVENT_PARSER_BUFSIZE (2048)
// if this is defined, use plughw: devices
//#define ALSA_MIDI_USE_PLUGHW
#undef ALSA_MIDI_USE_PLUGHW
typedef struct tag_ALSA_MIDIDeviceDescription {
int index; // in
int strLen; // in
INT32 deviceID; // out
char* name; // out
char* description; // out
} ALSA_MIDIDeviceDescription;
const char* getErrorStr(INT32 err);
/* Returns the number of devices. */
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
int getMidiDeviceCount(snd_rawmidi_stream_t direction);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
int getMidiDeviceName(snd_rawmidi_stream_t direction, int index,
char *name, UINT32 nameLength);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
int getMidiDeviceVendor(int index, char *name, UINT32 nameLength);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
int getMidiDeviceDescription(snd_rawmidi_stream_t direction, int index,
char *name, UINT32 nameLength);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
int getMidiDeviceVersion(int index, char *name, UINT32 nameLength);
// returns 0 on success, otherwise MIDI_OUT_OF_MEMORY or ALSA error code
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
INT32 openMidiDevice(snd_rawmidi_stream_t direction, INT32 deviceIndex,
MidiDeviceHandle** handle);
// returns 0 on success, otherwise a (negative) ALSA error code
INT32 closeMidiDevice(MidiDeviceHandle* handle);
INT64 getMidiTimestamp(MidiDeviceHandle* handle);
#endif // PLATFORM_API_BSDOS_ALSA_MIDIUTILS_H_INCLUDED
/*
* Copyright (c) 2003, 2014, 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_PCMUtils.h"
#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
// callback for iteration through devices
// returns TRUE if iteration should continue
// NOTE: cardinfo may be NULL (for "default" device)
typedef int (*DeviceIteratorPtr)(UINT32 deviceID, snd_pcm_info_t* pcminfo,
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
int iteratePCMDevices(DeviceIteratorPtr iterator, void* userData) {
int count = 0;
int subdeviceCount;
int card, dev, subDev;
char devname[16];
int err;
snd_ctl_t *handle;
snd_pcm_t *pcm;
snd_pcm_info_t* pcminfo;
snd_ctl_card_info_t *cardinfo, *defcardinfo = NULL;
UINT32 deviceID;
int doContinue = TRUE;
snd_pcm_info_malloc(&pcminfo);
snd_ctl_card_info_malloc(&cardinfo);
// 1st try "default" device
err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0) {
// try with the other direction
err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
}
if (err < 0) {
ERROR1("ERROR: snd_pcm_open (\"default\"): %s\n", snd_strerror(err));
} else {
err = snd_pcm_info(pcm, pcminfo);
snd_pcm_close(pcm);
if (err < 0) {
ERROR1("ERROR: snd_pcm_info (\"default\"): %s\n",
snd_strerror(err));
} else {
// try to get card info
card = snd_pcm_info_get_card(pcminfo);
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, cardinfo) >= 0) {
defcardinfo = cardinfo;
}
snd_ctl_close(handle);
}
}
// call callback function for the device
if (iterator != NULL) {
doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, pcminfo,
defcardinfo, userData);
}
count++;
}
}
// iterate cards
card = -1;
while (doContinue) {
if (snd_card_next(&card) < 0) {
break;
}
if (card < 0) {
break;
}
sprintf(devname, ALSA_HARDWARE_CARD, card);
TRACE1("Opening alsa 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 {
err = snd_ctl_card_info(handle, cardinfo);
if (err < 0) {
ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n",
card, snd_strerror(err));
} else {
dev = -1;
while (doContinue) {
if (snd_ctl_pcm_next_device(handle, &dev) < 0) {
ERROR0("snd_ctl_pcm_next_device\n");
}
if (dev < 0) {
break;
}
snd_pcm_info_set_device(pcminfo, dev);
snd_pcm_info_set_subdevice(pcminfo, 0);
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
err = snd_ctl_pcm_info(handle, pcminfo);
if (err == -ENOENT) {
// try with the other direction
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
err = snd_ctl_pcm_info(handle, pcminfo);
}
if (err < 0) {
if (err != -ENOENT) {
ERROR2("ERROR: snd_ctl_pcm_info, card=%d: %s",
card, snd_strerror(err));
}
} else {
subdeviceCount = needEnumerateSubdevices(ALSA_PCM) ?
snd_pcm_info_get_subdevices_count(pcminfo) : 1;
if (iterator!=NULL) {
for (subDev = 0; subDev < subdeviceCount; subDev++) {
deviceID = encodeDeviceID(card, dev, subDev);
doContinue = (*iterator)(deviceID, pcminfo,
cardinfo, userData);
count++;
if (!doContinue) {
break;
}
}
} else {
count += subdeviceCount;
}
}
} // of while(doContinue)
}
snd_ctl_close(handle);
}
}
snd_ctl_card_info_free(cardinfo);
snd_pcm_info_free(pcminfo);
return count;
}
int getAudioDeviceCount() {
initAlsaSupport();
return iteratePCMDevices(NULL, NULL);
}
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;
}
// 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;
}
int getAudioDeviceDescriptionByIndex(ALSA_AudioDeviceDescription* desc) {
initAlsaSupport();
TRACE1(" getAudioDeviceDescriptionByIndex(mixerIndex = %d\n", desc->index);
iteratePCMDevices(&deviceInfoIterator, desc);
return (desc->index == 0)?TRUE:FALSE;
}
// returns 1 if successful
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
int* sampleSizeInBytes, int* significantBits,
int* isSigned, int* isBigEndian, int* enc) {
*sampleSizeInBytes = (snd_pcm_format_physical_width(alsaFormat) + 7) / 8;
*significantBits = snd_pcm_format_width(alsaFormat);
// defaults
*enc = 0; // PCM
*isSigned = (snd_pcm_format_signed(alsaFormat) > 0);
*isBigEndian = (snd_pcm_format_big_endian(alsaFormat) > 0);
// non-PCM formats
if (alsaFormat == SND_PCM_FORMAT_MU_LAW) { // Mu-Law
*sampleSizeInBytes = 8; *enc = 1; *significantBits = *sampleSizeInBytes;
}
else if (alsaFormat == SND_PCM_FORMAT_A_LAW) { // A-Law
*sampleSizeInBytes = 8; *enc = 2; *significantBits = *sampleSizeInBytes;
}
else if (snd_pcm_format_linear(alsaFormat) < 1) {
return 0;
}
return (*sampleSizeInBytes > 0);
}
// returns 1 if successful
int getAlsaFormatFromFormat(snd_pcm_format_t* alsaFormat,
int sampleSizeInBytes, int significantBits,
int isSigned, int isBigEndian, int enc) {
*alsaFormat = SND_PCM_FORMAT_UNKNOWN;
if (enc == 0) {
*alsaFormat = snd_pcm_build_linear_format(significantBits,
sampleSizeInBytes * 8,
isSigned?0:1,
isBigEndian?1:0);
}
else if ((sampleSizeInBytes == 1) && (significantBits == 8)) {
if (enc == 1) { // ULAW
*alsaFormat = SND_PCM_FORMAT_MU_LAW;
}
else if (enc == 2) { // ALAW
*alsaFormat = SND_PCM_FORMAT_A_LAW;
}
}
return (*alsaFormat == SND_PCM_FORMAT_UNKNOWN)?0:1;
}
/* end */
/*
* 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 this with a later version of ALSA than 0.9.0rc3
// (starting from 1.0.0 it became default behaviour)
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include "Utilities.h"
#ifndef PLATFORM_API_BSDOS_ALSA_PCMUTILS_H_INCLUDED
#define PLATFORM_API_BSDOS_ALSA_PCMUTILS_H_INCLUDED
// if this is defined, use plughw: devices
#define ALSA_PCM_USE_PLUGHW
//#undef ALSA_PCM_USE_PLUGHW
// maximum number of channels that is listed in the formats. If more, than
// just -1 for channel count is used.
#define MAXIMUM_LISTED_CHANNELS 32
typedef struct tag_ALSA_AudioDeviceDescription {
int index; // in
int strLen; // in
INT32* deviceID; // out
int* maxSimultaneousLines; // out
char* name; // out
char* vendor; // out
char* description; // out
char* version; // out
} ALSA_AudioDeviceDescription;
int getAudioDeviceCount();
int getAudioDeviceDescriptionByIndex(ALSA_AudioDeviceDescription* desc);
// returns ALSA error code, or 0 if successful
int openPCMfromDeviceID(int deviceID, snd_pcm_t** handle, int isSource, int hardware);
// returns 1 if successful
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
int* sampleSizeInBytes, int* significantBits,
int* isSigned, int* isBigEndian, int* enc);
int getAlsaFormatFromFormat(snd_pcm_format_t* alsaFormat,
int sampleSizeInBytes, int significantBits,
int isSigned, int isBigEndian, int enc);
#endif // PLATFORM_API_BSDOS_ALSA_PCMUTILS_H_INCLUDED
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册