--- a/.hgtags Fri Mar 23 18:01:52 2018 +0000
+++ b/.hgtags Fri Mar 23 18:44:47 2018 +0000
@@ -476,3 +476,4 @@
1fd4d6068f54561cfc67d54fc9ca84af7212c4f8 jdk-11+3
e59941f7247d451fa7df9eaef3fce0f492f8420c jdk-11+4
d5c43e9f08fb9a7c74aae0d48daf17f2ad2afaef jdk-11+5
+3acb379b86725c47e7f33358cb22efa8752ae532 jdk-11+6
--- a/doc/testing.html Fri Mar 23 18:01:52 2018 +0000
+++ b/doc/testing.html Fri Mar 23 18:44:47 2018 +0000
@@ -40,7 +40,7 @@
$ make run-test-jdk_lang JTREG="JOBS=8"
$ make run-test TEST=jdk_lang
$ make run-test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
-$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"
+$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make run-test TEST="jtreg:hotspot/test:hotspot_gc hotspot/test/native_sanity/JniVersion.java"
$ make exploded-run-test TEST=hotspot_tier1</code></pre>
<h3 id="configuration">Configuration</h3>
@@ -77,8 +77,8 @@
<h2 id="test-suite-control">Test suite control</h2>
<p>It is possible to control various aspects of the test suites using make control variables.</p>
<p>These variables use a keyword=value approach to allow multiple values to be set. So, for instance, <code>JTREG="JOBS=1;TIMEOUT=8"</code> will set the JTReg concurrency level to 1 and the timeout factor to 8. This is equivalent to setting <code>JTREG_JOBS=1 JTREG_TIMEOUT=8</code>, but using the keyword format means that the <code>JTREG</code> variable is parsed and verified for correctness, so <code>JTREG="TMIEOUT=8"</code> would give an error, while <code>JTREG_TMIEOUT=8</code> would just pass unnoticed.</p>
-<p>To separate multiple keyword=value pairs, use <code>;</code> (semicolon). Since the shell normally eats <code>;</code>, the recommended usage is to write the assignment inside qoutes, e.g. <code>JTREG="...;..."</code>. This will also make sure spaces are preserved, as in <code>JTREG="VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"</code>.</p>
-<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
+<p>To separate multiple keyword=value pairs, use <code>;</code> (semicolon). Since the shell normally eats <code>;</code>, the recommended usage is to write the assignment inside qoutes, e.g. <code>JTREG="...;..."</code>. This will also make sure spaces are preserved, as in <code>JTREG="VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"</code>.</p>
+<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
<p>As far as possible, the names of the keywords have been standardized between test suites.</p>
<h3 id="jtreg-keywords">JTReg keywords</h3>
<h4 id="jobs">JOBS</h4>
--- a/doc/testing.md Fri Mar 23 18:01:52 2018 +0000
+++ b/doc/testing.md Fri Mar 23 18:44:47 2018 +0000
@@ -18,7 +18,7 @@
$ make run-test-jdk_lang JTREG="JOBS=8"
$ make run-test TEST=jdk_lang
$ make run-test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
- $ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"
+ $ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make run-test TEST="jtreg:hotspot/test:hotspot_gc hotspot/test/native_sanity/JniVersion.java"
$ make exploded-run-test TEST=hotspot_tier1
@@ -140,11 +140,11 @@
To separate multiple keyword=value pairs, use `;` (semicolon). Since the shell
normally eats `;`, the recommended usage is to write the assignment inside
qoutes, e.g. `JTREG="...;..."`. This will also make sure spaces are preserved,
-as in `JTREG="VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"`.
+as in `JTREG="VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"`.
(Other ways are possible, e.g. using backslash: `JTREG=JOBS=1\;TIMEOUT=8`.
Also, as a special technique, the string `%20` will be replaced with space for
-certain options, e.g. `JTREG=VM_OTIONS=-XshowSettings%20-Xlog:gc+ref=debug`.
+certain options, e.g. `JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug`.
This can be useful if you have layers of scripts and have trouble getting
proper quoting of command line arguments through.)
--- a/make/lib/SoundLibraries.gmk Fri Mar 23 18:01:52 2018 +0000
+++ b/make/lib/SoundLibraries.gmk Fri Mar 23 18:44:47 2018 +0000
@@ -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
+ifneq ($(OPENJDK_TARGET_OS), solaris)
+ LIBJSOUND_CFLAGS += \
+ -DUSE_PLATFORM_MIDI_OUT=TRUE \
+ -DUSE_PLATFORM_MIDI_IN=TRUE \
+ #
+endif
ifeq ($(OPENJDK_TARGET_OS), windows)
- EXTRA_SOUND_JNI_LIBS += jsoundds
- LIBJSOUND_CFLAGS += -DX_PLATFORM=X_WINDOWS \
- -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
+ 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 @@
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 @@
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
--- a/make/mapfiles/libjsound/mapfile-vers Fri Mar 23 18:01:52 2018 +0000
+++ b/make/mapfiles/libjsound/mapfile-vers Fri Mar 23 18:44:47 2018 +0000
@@ -65,8 +65,6 @@
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;
--- a/make/mapfiles/libjsoundalsa/mapfile-vers Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-#
-# 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:
- *;
-};
--- a/make/mapfiles/libnio/mapfile-linux Fri Mar 23 18:01:52 2018 +0000
+++ b/make/mapfiles/libnio/mapfile-linux Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 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
@@ -37,23 +37,12 @@
Java_sun_nio_ch_DatagramDispatcher_readv0;
Java_sun_nio_ch_DatagramDispatcher_write0;
Java_sun_nio_ch_DatagramDispatcher_writev0;
- Java_sun_nio_ch_EPollArrayWrapper_epollCreate;
- Java_sun_nio_ch_EPollArrayWrapper_epollCtl;
- Java_sun_nio_ch_EPollArrayWrapper_epollWait;
- Java_sun_nio_ch_EPollArrayWrapper_init;
- Java_sun_nio_ch_EPollArrayWrapper_interrupt;
- Java_sun_nio_ch_EPollArrayWrapper_offsetofData;
- Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent;
Java_sun_nio_ch_EPoll_eventSize;
Java_sun_nio_ch_EPoll_eventsOffset;
Java_sun_nio_ch_EPoll_dataOffset;
- Java_sun_nio_ch_EPoll_epollCreate;
- Java_sun_nio_ch_EPoll_epollCtl;
- Java_sun_nio_ch_EPoll_epollWait;
- Java_sun_nio_ch_EPollPort_close0;
- Java_sun_nio_ch_EPollPort_drain1;
- Java_sun_nio_ch_EPollPort_interrupt;
- Java_sun_nio_ch_EPollPort_socketpair;
+ Java_sun_nio_ch_EPoll_create;
+ Java_sun_nio_ch_EPoll_ctl;
+ Java_sun_nio_ch_EPoll_wait;
Java_sun_nio_ch_FileChannelImpl_initIDs;
Java_sun_nio_ch_FileChannelImpl_map0;
Java_sun_nio_ch_FileChannelImpl_position0;
@@ -95,6 +84,7 @@
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
+ Java_sun_nio_ch_IOUtil_write1;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
--- a/make/mapfiles/libnio/mapfile-macosx Fri Mar 23 18:01:52 2018 +0000
+++ b/make/mapfiles/libnio/mapfile-macosx Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 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
@@ -42,7 +42,7 @@
Java_sun_nio_ch_FileChannelImpl_position0;
Java_sun_nio_ch_FileChannelImpl_transferTo0;
Java_sun_nio_ch_FileChannelImpl_unmap0;
- Java_sun_nio_ch_FileDispatcherImpl_allocate0;
+ Java_sun_nio_ch_FileDispatcherImpl_allocate0;
Java_sun_nio_ch_FileDispatcherImpl_close0;
Java_sun_nio_ch_FileDispatcherImpl_closeIntFD;
Java_sun_nio_ch_FileDispatcherImpl_force0;
@@ -71,117 +71,115 @@
Java_sun_nio_ch_IOUtil_configureBlocking;
Java_sun_nio_ch_IOUtil_drain;
Java_sun_nio_ch_IOUtil_fdVal;
+ Java_sun_nio_ch_IOUtil_fdLimit;
Java_sun_nio_ch_IOUtil_initIDs;
+ Java_sun_nio_ch_IOUtil_iovMax;
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
- Java_sun_nio_ch_IOUtil_iovMax;
- Java_sun_nio_ch_KQueue_kqueue;
- Java_sun_nio_ch_KQueue_keventRegister;
- Java_sun_nio_ch_KQueue_keventPoll;
- Java_sun_nio_ch_KQueue_keventSize;
- Java_sun_nio_ch_KQueue_identOffset;
- Java_sun_nio_ch_KQueue_filterOffset;
- Java_sun_nio_ch_KQueue_flagsOffset;
- Java_sun_nio_ch_KQueuePort_socketpair;
- Java_sun_nio_ch_KQueuePort_interrupt;
- Java_sun_nio_ch_KQueuePort_drain1;
- Java_sun_nio_ch_KQueuePort_close0;
- Java_sun_nio_ch_NativeThread_current;
- Java_sun_nio_ch_NativeThread_init;
- Java_sun_nio_ch_NativeThread_signal;
- Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0;
- Java_sun_nio_ch_Net_canJoin6WithIPv4Group0;
- Java_sun_nio_ch_Net_socket0;
- Java_sun_nio_ch_Net_bind0;
- Java_sun_nio_ch_Net_connect0;
- Java_sun_nio_ch_Net_listen;
- Java_sun_nio_ch_Net_localPort;
- Java_sun_nio_ch_Net_localInetAddress;
- Java_sun_nio_ch_Net_getIntOption0;
- Java_sun_nio_ch_Net_setIntOption0;
+ Java_sun_nio_ch_IOUtil_write1;
+ Java_sun_nio_ch_KQueue_create;
+ Java_sun_nio_ch_KQueue_register;
+ Java_sun_nio_ch_KQueue_poll;
+ Java_sun_nio_ch_KQueue_keventSize;
+ Java_sun_nio_ch_KQueue_identOffset;
+ Java_sun_nio_ch_KQueue_filterOffset;
+ Java_sun_nio_ch_KQueue_flagsOffset;
+ Java_sun_nio_ch_NativeThread_current;
+ Java_sun_nio_ch_NativeThread_init;
+ Java_sun_nio_ch_NativeThread_signal;
+ Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0;
+ Java_sun_nio_ch_Net_canJoin6WithIPv4Group0;
+ Java_sun_nio_ch_Net_socket0;
+ Java_sun_nio_ch_Net_bind0;
+ Java_sun_nio_ch_Net_connect0;
+ Java_sun_nio_ch_Net_listen;
+ Java_sun_nio_ch_Net_localPort;
+ Java_sun_nio_ch_Net_localInetAddress;
+ Java_sun_nio_ch_Net_getIntOption0;
+ Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
Java_sun_nio_ch_Net_isIPv6Available0;
Java_sun_nio_ch_Net_isReusePortAvailable0;
- Java_sun_nio_ch_Net_joinOrDrop4;
- Java_sun_nio_ch_Net_blockOrUnblock4;
- Java_sun_nio_ch_Net_joinOrDrop6;
- Java_sun_nio_ch_Net_blockOrUnblock6;
- Java_sun_nio_ch_Net_setInterface4;
- Java_sun_nio_ch_Net_getInterface4;
- Java_sun_nio_ch_Net_setInterface6;
- Java_sun_nio_ch_Net_getInterface6;
- Java_sun_nio_ch_Net_shutdown;
- Java_sun_nio_ch_Net_poll;
- Java_sun_nio_ch_Net_pollinValue;
- Java_sun_nio_ch_Net_polloutValue;
- Java_sun_nio_ch_Net_pollerrValue;
- Java_sun_nio_ch_Net_pollhupValue;
- Java_sun_nio_ch_Net_pollnvalValue;
- Java_sun_nio_ch_Net_pollconnValue;
+ Java_sun_nio_ch_Net_joinOrDrop4;
+ Java_sun_nio_ch_Net_blockOrUnblock4;
+ Java_sun_nio_ch_Net_joinOrDrop6;
+ Java_sun_nio_ch_Net_blockOrUnblock6;
+ Java_sun_nio_ch_Net_setInterface4;
+ Java_sun_nio_ch_Net_getInterface4;
+ Java_sun_nio_ch_Net_setInterface6;
+ Java_sun_nio_ch_Net_getInterface6;
+ Java_sun_nio_ch_Net_shutdown;
+ Java_sun_nio_ch_Net_poll;
+ Java_sun_nio_ch_Net_pollinValue;
+ Java_sun_nio_ch_Net_polloutValue;
+ Java_sun_nio_ch_Net_pollerrValue;
+ Java_sun_nio_ch_Net_pollhupValue;
+ Java_sun_nio_ch_Net_pollnvalValue;
+ Java_sun_nio_ch_Net_pollconnValue;
Java_sun_nio_ch_Net_isExclusiveBindAvailable;
Java_sun_nio_ch_PollArrayWrapper_interrupt;
Java_sun_nio_ch_PollArrayWrapper_poll0;
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
- Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
- Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
- Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
- Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
- Java_sun_nio_fs_BsdNativeDispatcher_initIDs;
- Java_sun_nio_fs_BsdNativeDispatcher_getfsstat;
- Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry;
- Java_sun_nio_fs_BsdNativeDispatcher_endfsstat;
- Java_sun_nio_fs_UnixNativeDispatcher_init;
- Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
- Java_sun_nio_fs_UnixNativeDispatcher_strerror;
- Java_sun_nio_fs_UnixNativeDispatcher_dup;
- Java_sun_nio_fs_UnixNativeDispatcher_access0;
- Java_sun_nio_fs_UnixNativeDispatcher_exists0;
- Java_sun_nio_fs_UnixNativeDispatcher_stat0;
+ Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
+ Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
+ Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
+ Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
+ Java_sun_nio_fs_BsdNativeDispatcher_initIDs;
+ Java_sun_nio_fs_BsdNativeDispatcher_getfsstat;
+ Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry;
+ Java_sun_nio_fs_BsdNativeDispatcher_endfsstat;
+ Java_sun_nio_fs_UnixNativeDispatcher_init;
+ Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
+ Java_sun_nio_fs_UnixNativeDispatcher_strerror;
+ Java_sun_nio_fs_UnixNativeDispatcher_dup;
+ Java_sun_nio_fs_UnixNativeDispatcher_access0;
+ Java_sun_nio_fs_UnixNativeDispatcher_exists0;
+ Java_sun_nio_fs_UnixNativeDispatcher_stat0;
Java_sun_nio_fs_UnixNativeDispatcher_stat1;
- Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
- Java_sun_nio_fs_UnixNativeDispatcher_fstat;
- Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
- Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
- Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
- Java_sun_nio_fs_UnixNativeDispatcher_chown0;
- Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
- Java_sun_nio_fs_UnixNativeDispatcher_fchown;
- Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
- Java_sun_nio_fs_UnixNativeDispatcher_futimes;
- Java_sun_nio_fs_UnixNativeDispatcher_open0;
- Java_sun_nio_fs_UnixNativeDispatcher_openat0;
- Java_sun_nio_fs_UnixNativeDispatcher_close0;
- Java_sun_nio_fs_UnixNativeDispatcher_read;
- Java_sun_nio_fs_UnixNativeDispatcher_write;
- Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
- Java_sun_nio_fs_UnixNativeDispatcher_fclose;
- Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
- Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
- Java_sun_nio_fs_UnixNativeDispatcher_readdir;
- Java_sun_nio_fs_UnixNativeDispatcher_closedir;
- Java_sun_nio_fs_UnixNativeDispatcher_link0;
- Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
- Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
- Java_sun_nio_fs_UnixNativeDispatcher_rename0;
- Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
- Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
- Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
- Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
- Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
- Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
- Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
- Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
- Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
- Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
- Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
- Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
- Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
- Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
- Java_sun_nio_fs_UnixCopyFile_transfer;
- handleSocketError;
+ Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
+ Java_sun_nio_fs_UnixNativeDispatcher_fstat;
+ Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
+ Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
+ Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
+ Java_sun_nio_fs_UnixNativeDispatcher_chown0;
+ Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
+ Java_sun_nio_fs_UnixNativeDispatcher_fchown;
+ Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
+ Java_sun_nio_fs_UnixNativeDispatcher_futimes;
+ Java_sun_nio_fs_UnixNativeDispatcher_open0;
+ Java_sun_nio_fs_UnixNativeDispatcher_openat0;
+ Java_sun_nio_fs_UnixNativeDispatcher_close0;
+ Java_sun_nio_fs_UnixNativeDispatcher_read;
+ Java_sun_nio_fs_UnixNativeDispatcher_write;
+ Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
+ Java_sun_nio_fs_UnixNativeDispatcher_fclose;
+ Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
+ Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
+ Java_sun_nio_fs_UnixNativeDispatcher_readdir;
+ Java_sun_nio_fs_UnixNativeDispatcher_closedir;
+ Java_sun_nio_fs_UnixNativeDispatcher_link0;
+ Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
+ Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
+ Java_sun_nio_fs_UnixNativeDispatcher_rename0;
+ Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
+ Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
+ Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
+ Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
+ Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
+ Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
+ Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
+ Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
+ Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
+ Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
+ Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
+ Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
+ Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
+ Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
+ Java_sun_nio_fs_UnixCopyFile_transfer;
+ handleSocketError;
local:
*;
--- a/make/mapfiles/libnio/mapfile-solaris Fri Mar 23 18:01:52 2018 +0000
+++ b/make/mapfiles/libnio/mapfile-solaris Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 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,7 +38,6 @@
Java_sun_nio_ch_DatagramDispatcher_write0;
Java_sun_nio_ch_DatagramDispatcher_writev0;
Java_sun_nio_ch_DevPollArrayWrapper_init;
- Java_sun_nio_ch_DevPollArrayWrapper_interrupt;
Java_sun_nio_ch_DevPollArrayWrapper_poll0;
Java_sun_nio_ch_DevPollArrayWrapper_register;
Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple;
@@ -83,6 +82,7 @@
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
+ Java_sun_nio_ch_IOUtil_write1;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
--- a/make/scripts/compare.sh Fri Mar 23 18:01:52 2018 +0000
+++ b/make/scripts/compare.sh Fri Mar 23 18:44:47 2018 +0000
@@ -1298,22 +1298,37 @@
# Find the common images to compare, prioritizing later build stages
if [ -d "$THIS/install/jdk" ] && [ -d "$OTHER/install/jdk" ]; then
THIS_JDK="$THIS/install/jdk"
- THIS_JRE="$THIS/install/jre"
OTHER_JDK="$OTHER/install/jdk"
- OTHER_JRE="$OTHER/install/jre"
- echo "Selecting install images for compare"
+ echo "Selecting install images for JDK compare"
+ if [ -d "$THIS/install/jre" ] && [ -d "$OTHER/install/jre" ]; then
+ THIS_JRE="$THIS/install/jre"
+ OTHER_JRE="$OTHER/install/jre"
+ echo "Also selecting install images for JRE compare"
+ else
+ echo "No install JRE image found"
+ fi
elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/deploy/images/jdk" ]; then
THIS_JDK="$THIS/images/jdk"
- THIS_JRE="$THIS/images/jre"
OTHER_JDK="$OTHER/deploy/images/jdk"
- OTHER_JRE="$OTHER/deploy/images/jre"
- echo "Selecting deploy images for compare"
+ echo "Selecting deploy images for JDK compare"
+ if [ -d "$THIS/images/jre" ] && [ -d "$OTHER/deploy/images/jre" ]; then
+ THIS_JRE="$THIS/images/jre"
+ OTHER_JRE="$OTHER/deploy/images/jre"
+ echo "Selecting deploy images for JRE compare"
+ else
+ echo "No deploy JRE image found"
+ fi
elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/images/jdk" ]; then
THIS_JDK="$THIS/images/jdk"
- THIS_JRE="$THIS/images/jre"
OTHER_JDK="$OTHER/images/jdk"
- OTHER_JRE="$OTHER/images/jre"
- echo "Selecting jdk images for compare"
+ echo "Selecting normal images for JDK compare"
+ if [ -d "$THIS/images/jre" ] && [ -d "$OTHER/images/jre" ]; then
+ THIS_JRE="$THIS/images/jre"
+ OTHER_JRE="$OTHER/images/jre"
+ echo "Selecting normal images for JRE compare"
+ else
+ echo "No normal JRE image found"
+ fi
elif [ -d "$(ls -d $THIS/licensee-src/build/*/images/jdk 2> /dev/null)" ] \
&& [ -d "$(ls -d $OTHER/licensee-src/build/*/images/jdk 2> /dev/null)" ]
then
@@ -1406,9 +1421,11 @@
else
OTHER_SEC_DIR="$OTHER/tmp"
fi
- OTHER_SEC_BIN="$OTHER_SEC_DIR/sec-bin.zip"
- THIS_SEC_DIR="$THIS/images"
- THIS_SEC_BIN="$THIS_SEC_DIR/sec-bin.zip"
+ if [ -f "$THIS_SEC_DIR/sec-bin.zip" ]; then
+ OTHER_SEC_BIN="$OTHER_SEC_DIR/sec-bin.zip"
+ THIS_SEC_DIR="$THIS/images"
+ THIS_SEC_BIN="$THIS_SEC_DIR/sec-bin.zip"
+ fi
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
if [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
JGSS_WINDOWS_BIN="jgss-windows-x64-bin.zip"
@@ -1437,11 +1454,12 @@
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
compare_dirs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+ echo -n "JDK "
+ compare_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+ fi
+ if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
echo -n "JRE "
compare_dirs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
-
- echo -n "JDK "
- compare_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
echo -n "JRE "
compare_files $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
@@ -1480,49 +1498,38 @@
fi
fi
-if [ "$CMP_PERMS" = "true" ]; then
+if [ "$CMP_LIBS" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
- compare_permissions $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
- echo -n "JRE "
- compare_permissions $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
+ compare_all_libs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
- compare_permissions $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+ compare_all_libs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
- compare_permissions $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+ compare_all_libs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
- compare_permissions $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+ compare_all_libs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi
-if [ "$CMP_TYPES" = "true" ]; then
+if [ "$CMP_EXECS" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
- echo -n "JDK "
- compare_file_types $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
- echo -n "JRE "
- compare_file_types $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
- fi
- if [ -n "$THIS_JDK_BUNDLE" ] && [ -n "$OTHER_JDK_BUNDLE" ]; then
- echo -n "JDK Bundle "
- compare_file_types $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
- echo -n "JRE Bundle "
- compare_file_types $THIS_JRE_BUNDLE $OTHER_JRE_BUNDLE $COMPARE_ROOT/jre-bundle
+ compare_all_execs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
- compare_file_types $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+ compare_all_execs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
- compare_file_types $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+ compare_all_execs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
- compare_file_types $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+ compare_all_execs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi
@@ -1530,6 +1537,8 @@
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
compare_general_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+ fi
+ if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
echo -n "JRE "
compare_general_files $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
@@ -1601,46 +1610,53 @@
fi
fi
-if [ "$CMP_LIBS" = "true" ]; then
+if [ "$CMP_PERMS" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
- compare_all_libs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
- if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
- echo -n "JRE "
- compare_all_libs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
- fi
+ compare_permissions $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+ fi
+ if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
+ echo -n "JRE "
+ compare_permissions $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
- compare_all_libs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+ compare_permissions $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
- compare_all_libs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+ compare_permissions $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
- compare_all_libs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+ compare_permissions $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi
-if [ "$CMP_EXECS" = "true" ]; then
+if [ "$CMP_TYPES" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
- compare_all_execs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
- if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
- echo -n "JRE "
- compare_all_execs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
- fi
+ echo -n "JDK "
+ compare_file_types $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+ fi
+ if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
+ echo -n "JRE "
+ compare_file_types $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
+ fi
+ if [ -n "$THIS_JDK_BUNDLE" ] && [ -n "$OTHER_JDK_BUNDLE" ]; then
+ echo -n "JDK Bundle "
+ compare_file_types $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
+ echo -n "JRE Bundle "
+ compare_file_types $THIS_JRE_BUNDLE $OTHER_JRE_BUNDLE $COMPARE_ROOT/jre-bundle
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
- compare_all_execs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+ compare_file_types $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
- compare_all_execs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+ compare_file_types $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
- compare_all_execs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+ compare_file_types $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi
--- a/make/scripts/compare_exceptions.sh.incl Fri Mar 23 18:01:52 2018 +0000
+++ b/make/scripts/compare_exceptions.sh.incl Fri Mar 23 18:44:47 2018 +0000
@@ -339,7 +339,7 @@
DIS_DIFF_FILTER="$SED \
-e 's/^[0-9a-f]\{16\}/<ADDR>:/' \
- -e 's/^ *[0-9a-f]\{3,8\}:/ <ADDR>:/' \
+ -e 's/^ *[0-9a-f]\{3,12\}:/ <ADDR>:/' \
-e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: <NUMS>/' \
-e 's/\$[a-zA-Z0-9_\$]\{15\}\./<SYM>./' \
-e 's/, [0-9a-fx\-]\{1,8\}/, <ADDR>/g' \
--- a/src/java.base/linux/classes/sun/nio/ch/EPoll.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/linux/classes/sun/nio/ch/EPoll.java Fri Mar 23 18:44:47 2018 +0000
@@ -109,11 +109,11 @@
private static native int dataOffset();
- static native int epollCreate() throws IOException;
+ static native int create() throws IOException;
- static native int epollCtl(int epfd, int opcode, int fd, int events);
+ static native int ctl(int epfd, int opcode, int fd, int events);
- static native int epollWait(int epfd, long pollAddress, int numfds)
+ static native int wait(int epfd, long pollAddress, int numfds, int timeout)
throws IOException;
static {
--- a/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-/*
- * Copyright (c) 2005, 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
- * 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.
- */
-
-package sun.nio.ch;
-
-import java.io.IOException;
-import java.security.AccessController;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
-import sun.security.action.GetIntegerAction;
-
-/**
- * Manipulates a native array of epoll_event structs on Linux:
- *
- * typedef union epoll_data {
- * void *ptr;
- * int fd;
- * __uint32_t u32;
- * __uint64_t u64;
- * } epoll_data_t;
- *
- * struct epoll_event {
- * __uint32_t events;
- * epoll_data_t data;
- * };
- *
- * The system call to wait for I/O events is epoll_wait(2). It populates an
- * array of epoll_event structures that are passed to the call. The data
- * member of the epoll_event structure contains the same data as was set
- * when the file descriptor was registered to epoll via epoll_ctl(2). In
- * this implementation we set data.fd to be the file descriptor that we
- * register. That way, we have the file descriptor available when we
- * process the events.
- */
-
-class EPollArrayWrapper {
- // EPOLL_EVENTS
- private static final int EPOLLIN = 0x001;
-
- // opcodes
- private static final int EPOLL_CTL_ADD = 1;
- private static final int EPOLL_CTL_DEL = 2;
- private static final int EPOLL_CTL_MOD = 3;
-
- // Miscellaneous constants
- private static final int SIZE_EPOLLEVENT = sizeofEPollEvent();
- private static final int EVENT_OFFSET = 0;
- private static final int DATA_OFFSET = offsetofData();
- private static final int FD_OFFSET = DATA_OFFSET;
- private static final int OPEN_MAX = IOUtil.fdLimit();
- private static final int NUM_EPOLLEVENTS = Math.min(OPEN_MAX, 8192);
-
- // Special value to indicate that an update should be ignored
- private static final byte KILLED = (byte)-1;
-
- // Initial size of arrays for fd registration changes
- private static final int INITIAL_PENDING_UPDATE_SIZE = 64;
-
- // maximum size of updatesLow
- private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged(
- new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024)));
-
- // The fd of the epoll driver
- private final int epfd;
-
- // The epoll_event array for results from epoll_wait
- private final AllocatedNativeObject pollArray;
-
- // Base address of the epoll_event array
- private final long pollArrayAddress;
-
- // The fd of the interrupt line going out
- private final int outgoingInterruptFD;
-
- // Number of updated pollfd entries
- private int updated;
-
- // object to synchronize fd registration changes
- private final Object updateLock = new Object();
-
- // number of file descriptors with registration changes pending
- private int updateCount;
-
- // file descriptors with registration changes pending
- private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
-
- // events for file descriptors with registration changes pending, indexed
- // by file descriptor and stored as bytes for efficiency reasons. For
- // file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
- // least) then the update is stored in a map.
- private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE];
- private final Map<Integer,Byte> eventsHigh = new HashMap<>();
-
- // Used by release and updateRegistrations to track whether a file
- // descriptor is registered with epoll.
- private final BitSet registered = new BitSet();
-
-
- EPollArrayWrapper(int fd0, int fd1) throws IOException {
- // creates the epoll file descriptor
- epfd = epollCreate();
-
- // the epoll_event array passed to epoll_wait
- int allocationSize = NUM_EPOLLEVENTS * SIZE_EPOLLEVENT;
- pollArray = new AllocatedNativeObject(allocationSize, true);
- pollArrayAddress = pollArray.address();
-
- outgoingInterruptFD = fd1;
- epollCtl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
- }
-
- void putEventOps(int i, int event) {
- int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
- pollArray.putInt(offset, event);
- }
-
- void putDescriptor(int i, int fd) {
- int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
- pollArray.putInt(offset, fd);
- }
-
- int getEventOps(int i) {
- int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
- return pollArray.getInt(offset);
- }
-
- int getDescriptor(int i) {
- int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
- return pollArray.getInt(offset);
- }
-
- /**
- * Returns {@code true} if updates for the given key (file
- * descriptor) are killed.
- */
- private boolean isEventsHighKilled(Integer key) {
- assert key >= MAX_UPDATE_ARRAY_SIZE;
- Byte value = eventsHigh.get(key);
- return (value != null && value == KILLED);
- }
-
- /**
- * Sets the pending update events for the given file descriptor. This
- * method has no effect if the update events is already set to KILLED,
- * unless {@code force} is {@code true}.
- */
- private void setUpdateEvents(int fd, byte events, boolean force) {
- if (fd < MAX_UPDATE_ARRAY_SIZE) {
- if ((eventsLow[fd] != KILLED) || force) {
- eventsLow[fd] = events;
- }
- } else {
- Integer key = Integer.valueOf(fd);
- if (!isEventsHighKilled(key) || force) {
- eventsHigh.put(key, Byte.valueOf(events));
- }
- }
- }
-
- /**
- * Returns the pending update events for the given file descriptor.
- */
- private byte getUpdateEvents(int fd) {
- if (fd < MAX_UPDATE_ARRAY_SIZE) {
- return eventsLow[fd];
- } else {
- Byte result = eventsHigh.get(Integer.valueOf(fd));
- // result should never be null
- return result.byteValue();
- }
- }
-
- /**
- * Update the events for a given file descriptor
- */
- void setInterest(int fd, int mask) {
- synchronized (updateLock) {
- // record the file descriptor and events
- int oldCapacity = updateDescriptors.length;
- if (updateCount == oldCapacity) {
- int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
- int[] newDescriptors = new int[newCapacity];
- System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
- updateDescriptors = newDescriptors;
- }
- updateDescriptors[updateCount++] = fd;
-
- // events are stored as bytes for efficiency reasons
- byte b = (byte)mask;
- assert (b == mask) && (b != KILLED);
- setUpdateEvents(fd, b, false);
- }
- }
-
- /**
- * Add a file descriptor
- */
- void add(int fd) {
- // force the initial update events to 0 as it may be KILLED by a
- // previous registration.
- synchronized (updateLock) {
- assert !registered.get(fd);
- setUpdateEvents(fd, (byte)0, true);
- }
- }
-
- /**
- * Remove a file descriptor
- */
- void remove(int fd) {
- synchronized (updateLock) {
- // kill pending and future update for this file descriptor
- setUpdateEvents(fd, KILLED, false);
-
- // remove from epoll
- if (registered.get(fd)) {
- epollCtl(epfd, EPOLL_CTL_DEL, fd, 0);
- registered.clear(fd);
- }
- }
- }
-
- /**
- * Close epoll file descriptor and free poll array
- */
- void close() throws IOException {
- FileDispatcherImpl.closeIntFD(epfd);
- pollArray.free();
- }
-
- int poll(long timeout) throws IOException {
- updateRegistrations();
- return epollWait(pollArrayAddress, NUM_EPOLLEVENTS, timeout, epfd);
- }
-
- /**
- * Update the pending registrations.
- */
- private void updateRegistrations() {
- synchronized (updateLock) {
- int j = 0;
- while (j < updateCount) {
- int fd = updateDescriptors[j];
- short events = getUpdateEvents(fd);
- boolean isRegistered = registered.get(fd);
- int opcode = 0;
-
- if (events != KILLED) {
- if (isRegistered) {
- opcode = (events != 0) ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
- } else {
- opcode = (events != 0) ? EPOLL_CTL_ADD : 0;
- }
- if (opcode != 0) {
- epollCtl(epfd, opcode, fd, events);
- if (opcode == EPOLL_CTL_ADD) {
- registered.set(fd);
- } else if (opcode == EPOLL_CTL_DEL) {
- registered.clear(fd);
- }
- }
- }
- j++;
- }
- updateCount = 0;
- }
- }
-
- public void interrupt() {
- interrupt(outgoingInterruptFD);
- }
-
- static {
- IOUtil.load();
- init();
- }
-
- private native int epollCreate();
- private native void epollCtl(int epfd, int opcode, int fd, int events);
- private native int epollWait(long pollAddress, int numfds, long timeout,
- int epfd) throws IOException;
- private static native int sizeofEPollEvent();
- private static native int offsetofData();
- private static native void interrupt(int fd);
- private static native void init();
-}
--- a/src/java.base/linux/classes/sun/nio/ch/EPollPort.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/linux/classes/sun/nio/ch/EPollPort.java Fri Mar 23 18:44:47 2018 +0000
@@ -30,7 +30,13 @@
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
-import static sun.nio.ch.EPoll.*;
+
+import static sun.nio.ch.EPoll.EPOLLIN;
+import static sun.nio.ch.EPoll.EPOLLONESHOT;
+import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
+import static sun.nio.ch.EPoll.EPOLL_CTL_DEL;
+import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
+
/**
* AsynchronousChannelGroup implementation based on the Linux epoll facility.
@@ -48,6 +54,9 @@
// epoll file descriptor
private final int epfd;
+ // address of the poll array passed to epoll_wait
+ private final long address;
+
// true if epoll closed
private boolean closed;
@@ -57,9 +66,6 @@
// number of wakeups pending
private final AtomicInteger wakeupCount = new AtomicInteger();
- // address of the poll array passed to epoll_wait
- private final long address;
-
// encapsulates an event for a channel
static class Event {
final PollableChannel channel;
@@ -85,23 +91,21 @@
{
super(provider, pool);
- // open epoll
- this.epfd = epollCreate();
+ this.epfd = EPoll.create();
+ this.address = EPoll.allocatePollArray(MAX_EPOLL_EVENTS);
// create socket pair for wakeup mechanism
- int[] sv = new int[2];
try {
- socketpair(sv);
- // register one end with epoll
- epollCtl(epfd, EPOLL_CTL_ADD, sv[0], EPOLLIN);
- } catch (IOException x) {
- close0(epfd);
- throw x;
+ long fds = IOUtil.makePipe(true);
+ this.sp = new int[]{(int) (fds >>> 32), (int) fds};
+ } catch (IOException ioe) {
+ EPoll.freePollArray(address);
+ FileDispatcherImpl.closeIntFD(epfd);
+ throw ioe;
}
- this.sp = sv;
- // allocate the poll array
- this.address = allocatePollArray(MAX_EPOLL_EVENTS);
+ // register one end with epoll
+ EPoll.ctl(epfd, EPOLL_CTL_ADD, sp[0], EPOLLIN);
// create the queue and offer the special event to ensure that the first
// threads polls
@@ -123,17 +127,17 @@
return;
closed = true;
}
- freePollArray(address);
- close0(sp[0]);
- close0(sp[1]);
- close0(epfd);
+ try { FileDispatcherImpl.closeIntFD(epfd); } catch (IOException ioe) { }
+ try { FileDispatcherImpl.closeIntFD(sp[0]); } catch (IOException ioe) { }
+ try { FileDispatcherImpl.closeIntFD(sp[1]); } catch (IOException ioe) { }
+ EPoll.freePollArray(address);
}
private void wakeup() {
if (wakeupCount.incrementAndGet() == 1) {
// write byte to socketpair to force wakeup
try {
- interrupt(sp[1]);
+ IOUtil.write1(sp[1], (byte)0);
} catch (IOException x) {
throw new AssertionError(x);
}
@@ -171,9 +175,9 @@
@Override
void startPoll(int fd, int events) {
// update events (or add to epoll on first usage)
- int err = epollCtl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
+ int err = EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
if (err == ENOENT)
- err = epollCtl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
+ err = EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
if (err != 0)
throw new AssertionError(); // should not happen
}
@@ -191,7 +195,11 @@
private Event poll() throws IOException {
try {
for (;;) {
- int n = epollWait(epfd, address, MAX_EPOLL_EVENTS);
+ int n;
+ do {
+ n = EPoll.wait(epfd, address, MAX_EPOLL_EVENTS, -1);
+ } while (n == IOStatus.INTERRUPTED);
+
/*
* 'n' events have been read. Here we map them to their
* corresponding channel in batch and queue n-1 so that
@@ -201,14 +209,14 @@
fdToChannelLock.readLock().lock();
try {
while (n-- > 0) {
- long eventAddress = getEvent(address, n);
- int fd = getDescriptor(eventAddress);
+ long eventAddress = EPoll.getEvent(address, n);
+ int fd = EPoll.getDescriptor(eventAddress);
// wakeup
if (fd == sp[0]) {
if (wakeupCount.decrementAndGet() == 0) {
// no more wakeups so drain pipe
- drain1(sp[0]);
+ IOUtil.drain(sp[0]);
}
// queue special event if there are more events
@@ -222,7 +230,7 @@
PollableChannel channel = fdToChannel.get(fd);
if (channel != null) {
- int events = getEvents(eventAddress);
+ int events = EPoll.getEvents(eventAddress);
Event ev = new Event(channel, events);
// n-1 events are queued; This thread handles
@@ -306,18 +314,4 @@
}
}
}
-
- // -- Native methods --
-
- private static native void socketpair(int[] sv) throws IOException;
-
- private static native void interrupt(int fd) throws IOException;
-
- private static native void drain1(int fd) throws IOException;
-
- private static native void close0(int fd);
-
- static {
- IOUtil.load();
- }
}
--- a/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -26,33 +26,59 @@
package sun.nio.ch;
import java.io.IOException;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.util.*;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.ArrayDeque;
+import java.util.BitSet;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static sun.nio.ch.EPoll.EPOLLIN;
+import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
+import static sun.nio.ch.EPoll.EPOLL_CTL_DEL;
+import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
+
/**
- * An implementation of Selector for Linux 2.6+ kernels that uses
- * the epoll event notification facility.
+ * Linux epoll based Selector implementation
*/
-class EPollSelectorImpl
- extends SelectorImpl
-{
- // File descriptors used for interrupt
+
+class EPollSelectorImpl extends SelectorImpl {
+
+ // maximum number of events to poll in one call to epoll_wait
+ private static final int NUM_EPOLLEVENTS = Math.min(IOUtil.fdLimit(), 1024);
+
+ // epoll file descriptor
+ private final int epfd;
+
+ // address of poll array when polling with epoll_wait
+ private final long pollArrayAddress;
+
+ // file descriptors used for interrupt
private final int fd0;
private final int fd1;
- // The poll object
- private final EPollArrayWrapper pollWrapper;
+ // maps file descriptor to selection key, synchronize on selector
+ private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
- // Maps from file descriptors to keys
- private final Map<Integer, SelectionKeyImpl> fdToKey;
+ // file descriptors registered with epoll, synchronize on selector
+ private final BitSet registered = new BitSet();
- // True if this Selector has been closed
- private volatile boolean closed;
+ // pending new registrations/updates, queued by implRegister and putEventOps
+ private final Object updateLock = new Object();
+ private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
+ private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
+ private final Deque<Integer> updateOps = new ArrayDeque<>();
- // Lock for interrupt triggering and clearing
+ // interrupt triggering and clearing
private final Object interruptLock = new Object();
- private boolean interruptTriggered = false;
+ private boolean interruptTriggered;
/**
* Package private constructor called by factory method in
@@ -60,40 +86,57 @@
*/
EPollSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
- long pipeFds = IOUtil.makePipe(false);
- fd0 = (int) (pipeFds >>> 32);
- fd1 = (int) pipeFds;
+
+ this.epfd = EPoll.create();
+ this.pollArrayAddress = EPoll.allocatePollArray(NUM_EPOLLEVENTS);
+
try {
- pollWrapper = new EPollArrayWrapper(fd0, fd1);
- fdToKey = new HashMap<>();
- } catch (Throwable t) {
- try {
- FileDispatcherImpl.closeIntFD(fd0);
- } catch (IOException ioe0) {
- t.addSuppressed(ioe0);
- }
- try {
- FileDispatcherImpl.closeIntFD(fd1);
- } catch (IOException ioe1) {
- t.addSuppressed(ioe1);
- }
- throw t;
+ long fds = IOUtil.makePipe(false);
+ this.fd0 = (int) (fds >>> 32);
+ this.fd1 = (int) fds;
+ } catch (IOException ioe) {
+ EPoll.freePollArray(pollArrayAddress);
+ FileDispatcherImpl.closeIntFD(epfd);
+ throw ioe;
}
+
+ // register one end of the socket pair for wakeups
+ EPoll.ctl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
}
private void ensureOpen() {
- if (closed)
+ if (!isOpen())
throw new ClosedSelectorException();
}
@Override
protected int doSelect(long timeout) throws IOException {
- ensureOpen();
+ assert Thread.holdsLock(this);
+
int numEntries;
+ processUpdateQueue();
processDeregisterQueue();
try {
begin();
- numEntries = pollWrapper.poll(timeout);
+
+ // epoll_wait timeout is int
+ int to = (int) Math.min(timeout, Integer.MAX_VALUE);
+ boolean timedPoll = (to > 0);
+ do {
+ long startTime = timedPoll ? System.nanoTime() : 0;
+ numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, to);
+ if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
+ // timed poll interrupted so need to adjust timeout
+ long adjust = System.nanoTime() - startTime;
+ to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
+ if (to <= 0) {
+ // timeout expired so no retry
+ numEntries = 0;
+ }
+ }
+ } while (numEntries == IOStatus.INTERRUPTED);
+ assert IOStatus.check(numEntries);
+
} finally {
end();
}
@@ -102,20 +145,69 @@
}
/**
+ * Process new registrations and changes to the interest ops.
+ */
+ private void processUpdateQueue() {
+ assert Thread.holdsLock(this);
+
+ synchronized (updateLock) {
+ SelectionKeyImpl ski;
+
+ // new registrations
+ while ((ski = newKeys.pollFirst()) != null) {
+ if (ski.isValid()) {
+ SelChImpl ch = ski.channel;
+ int fd = ch.getFDVal();
+ SelectionKeyImpl previous = fdToKey.put(fd, ski);
+ assert previous == null;
+ assert registered.get(fd) == false;
+ }
+ }
+
+ // changes to interest ops
+ assert updateKeys.size() == updateOps.size();
+ while ((ski = updateKeys.pollFirst()) != null) {
+ int ops = updateOps.pollFirst();
+ int fd = ski.channel.getFDVal();
+ if (ski.isValid() && fdToKey.containsKey(fd)) {
+ if (registered.get(fd)) {
+ if (ops == 0) {
+ // remove from epoll
+ EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
+ registered.clear(fd);
+ } else {
+ // modify events
+ EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, ops);
+ }
+ } else if (ops != 0) {
+ // add to epoll
+ EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, ops);
+ registered.set(fd);
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Update the keys whose fd's have been selected by the epoll.
* Add the ready keys to the ready queue.
*/
private int updateSelectedKeys(int numEntries) throws IOException {
+ assert Thread.holdsLock(this);
+ assert Thread.holdsLock(nioSelectedKeys());
+
boolean interrupted = false;
int numKeysUpdated = 0;
for (int i=0; i<numEntries; i++) {
- int nextFD = pollWrapper.getDescriptor(i);
- if (nextFD == fd0) {
+ long event = EPoll.getEvent(pollArrayAddress, i);
+ int fd = EPoll.getDescriptor(event);
+ if (fd == fd0) {
interrupted = true;
} else {
- SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
+ SelectionKeyImpl ski = fdToKey.get(fd);
if (ski != null) {
- int rOps = pollWrapper.getEventOps(i);
+ int rOps = EPoll.getEvents(event);
if (selectedKeys.contains(ski)) {
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
numKeysUpdated++;
@@ -140,16 +232,17 @@
@Override
protected void implClose() throws IOException {
- if (closed)
- return;
- closed = true;
+ assert Thread.holdsLock(this);
+ assert Thread.holdsLock(nioKeys());
// prevent further wakeup
synchronized (interruptLock) {
interruptTriggered = true;
}
- pollWrapper.close();
+ FileDispatcherImpl.closeIntFD(epfd);
+ EPoll.freePollArray(pollArrayAddress);
+
FileDispatcherImpl.closeIntFD(fd0);
FileDispatcherImpl.closeIntFD(fd1);
@@ -167,42 +260,57 @@
@Override
protected void implRegister(SelectionKeyImpl ski) {
+ assert Thread.holdsLock(nioKeys());
ensureOpen();
- SelChImpl ch = ski.channel;
- int fd = Integer.valueOf(ch.getFDVal());
- fdToKey.put(fd, ski);
- pollWrapper.add(fd);
+ synchronized (updateLock) {
+ newKeys.addLast(ski);
+ }
keys.add(ski);
}
@Override
protected void implDereg(SelectionKeyImpl ski) throws IOException {
- assert (ski.getIndex() >= 0);
- SelChImpl ch = ski.channel;
- int fd = ch.getFDVal();
- fdToKey.remove(Integer.valueOf(fd));
- pollWrapper.remove(fd);
- ski.setIndex(-1);
+ assert !ski.isValid();
+ assert Thread.holdsLock(this);
+ assert Thread.holdsLock(nioKeys());
+ assert Thread.holdsLock(nioSelectedKeys());
+
+ int fd = ski.channel.getFDVal();
+ fdToKey.remove(fd);
+ if (registered.get(fd)) {
+ EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
+ registered.clear(fd);
+ }
+
+ selectedKeys.remove(ski);
keys.remove(ski);
- selectedKeys.remove(ski);
+
+ // remove from channel's key set
deregister(ski);
+
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
- ((SelChImpl)selch).kill();
+ ((SelChImpl) selch).kill();
}
@Override
public void putEventOps(SelectionKeyImpl ski, int ops) {
ensureOpen();
- SelChImpl ch = ski.channel;
- pollWrapper.setInterest(ch.getFDVal(), ops);
+ synchronized (updateLock) {
+ updateOps.addLast(ops); // ops first in case adding the key fails
+ updateKeys.addLast(ski);
+ }
}
@Override
public Selector wakeup() {
synchronized (interruptLock) {
if (!interruptTriggered) {
- pollWrapper.interrupt();
+ try {
+ IOUtil.write1(fd1, (byte)0);
+ } catch (IOException ioe) {
+ throw new InternalError(ioe);
+ }
interruptTriggered = true;
}
}
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -103,8 +103,8 @@
@Override
FileTypeDetector getFileTypeDetector() {
String userHome = GetPropertyAction.privilegedGetProperty("user.home");
- Path userMimeTypes = Paths.get(userHome, ".mime.types");
- Path etcMimeTypes = Paths.get("/etc/mime.types");
+ Path userMimeTypes = Path.of(userHome, ".mime.types");
+ Path etcMimeTypes = Path.of("/etc/mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
new MimeTypesFileTypeDetector(etcMimeTypes));
--- a/src/java.base/linux/native/libnio/ch/EPoll.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/linux/native/libnio/ch/EPoll.c Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -23,53 +23,51 @@
* questions.
*/
+ #include <dlfcn.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/epoll.h>
+
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
+#include "nio.h"
#include "nio_util.h"
#include "sun_nio_ch_EPoll.h"
-#include <dlfcn.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/epoll.h>
-
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass this)
+Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass clazz)
{
return sizeof(struct epoll_event);
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct epoll_event, events);
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct epoll_event, data);
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_epollCreate(JNIEnv *env, jclass c) {
- /*
- * epoll_create expects a size as a hint to the kernel about how to
- * dimension internal structures. We can't predict the size in advance.
- */
+Java_sun_nio_ch_EPoll_create(JNIEnv *env, jclass clazz) {
+ /* size hint not used in modern kernels */
int epfd = epoll_create(256);
if (epfd < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
+ JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
}
return epfd;
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_epollCtl(JNIEnv *env, jclass c, jint epfd,
- jint opcode, jint fd, jint events)
+Java_sun_nio_ch_EPoll_ctl(JNIEnv *env, jclass clazz, jint epfd,
+ jint opcode, jint fd, jint events)
{
struct epoll_event event;
int res;
@@ -77,21 +75,23 @@
event.events = events;
event.data.fd = fd;
- RESTARTABLE(epoll_ctl(epfd, (int)opcode, (int)fd, &event), res);
-
+ res = epoll_ctl(epfd, (int)opcode, (int)fd, &event);
return (res == 0) ? 0 : errno;
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_epollWait(JNIEnv *env, jclass c,
- jint epfd, jlong address, jint numfds)
+Java_sun_nio_ch_EPoll_wait(JNIEnv *env, jclass clazz, jint epfd,
+ jlong address, jint numfds, jint timeout)
{
struct epoll_event *events = jlong_to_ptr(address);
- int res;
-
- RESTARTABLE(epoll_wait(epfd, events, numfds, -1), res);
+ int res = epoll_wait(epfd, events, numfds, timeout);
if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
+ if (errno == EINTR) {
+ return IOS_INTERRUPTED;
+ } else {
+ JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
+ return IOS_THROWN;
+ }
}
return res;
}
--- a/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2005, 2016, 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 "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-
-#include "sun_nio_ch_EPollArrayWrapper.h"
-
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/epoll.h>
-
-#define RESTARTABLE(_cmd, _result) do { \
- do { \
- _result = _cmd; \
- } while((_result == -1) && (errno == EINTR)); \
-} while(0)
-
-
-static int
-iepoll(int epfd, struct epoll_event *events, int numfds, jlong timeout)
-{
- jlong start, now;
- int remaining = timeout;
- struct timeval t;
- int diff;
-
- gettimeofday(&t, NULL);
- start = t.tv_sec * 1000 + t.tv_usec / 1000;
-
- for (;;) {
- int res = epoll_wait(epfd, events, numfds, remaining);
- if (res < 0 && errno == EINTR) {
- if (remaining >= 0) {
- gettimeofday(&t, NULL);
- now = t.tv_sec * 1000 + t.tv_usec / 1000;
- diff = now - start;
- remaining -= diff;
- if (diff < 0 || remaining <= 0) {
- return 0;
- }
- start = now;
- }
- } else {
- return res;
- }
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_init(JNIEnv *env, jclass this)
-{
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_epollCreate(JNIEnv *env, jobject this)
-{
- /*
- * epoll_create expects a size as a hint to the kernel about how to
- * dimension internal structures. We can't predict the size in advance.
- */
- int epfd = epoll_create(256);
- if (epfd < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
- }
- return epfd;
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent(JNIEnv* env, jclass this)
-{
- return sizeof(struct epoll_event);
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_offsetofData(JNIEnv* env, jclass this)
-{
- return offsetof(struct epoll_event, data);
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_epollCtl(JNIEnv *env, jobject this, jint epfd,
- jint opcode, jint fd, jint events)
-{
- struct epoll_event event;
- int res;
-
- event.events = events;
- event.data.fd = fd;
-
- RESTARTABLE(epoll_ctl(epfd, (int)opcode, (int)fd, &event), res);
-
- /*
- * A channel may be registered with several Selectors. When each Selector
- * is polled a EPOLL_CTL_DEL op will be inserted into its pending update
- * list to remove the file descriptor from epoll. The "last" Selector will
- * close the file descriptor which automatically unregisters it from each
- * epoll descriptor. To avoid costly synchronization between Selectors we
- * allow pending updates to be processed, ignoring errors. The errors are
- * harmless as the last update for the file descriptor is guaranteed to
- * be EPOLL_CTL_DEL.
- */
- if (res < 0 && errno != EBADF && errno != ENOENT && errno != EPERM) {
- JNU_ThrowIOExceptionWithLastError(env, "epoll_ctl failed");
- }
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_epollWait(JNIEnv *env, jobject this,
- jlong address, jint numfds,
- jlong timeout, jint epfd)
-{
- struct epoll_event *events = jlong_to_ptr(address);
- int res;
-
- if (timeout <= 0) { /* Indefinite or no wait */
- RESTARTABLE(epoll_wait(epfd, events, numfds, timeout), res);
- } else { /* Bounded wait; bounded restarts */
- res = iepoll(epfd, events, numfds, timeout);
- }
-
- if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
- }
- return res;
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_interrupt(JNIEnv *env, jobject this, jint fd)
-{
- int fakebuf[1];
- fakebuf[0] = 1;
- if (write(fd, fakebuf, 1) < 0) {
- JNU_ThrowIOExceptionWithLastError(env,"write to interrupt fd failed");
- }
-}
--- a/src/java.base/linux/native/libnio/ch/EPollPort.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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 "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include "sun_nio_ch_EPollPort.h"
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
- int sp[2];
- if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
- JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
- } else {
- jint res[2];
- res[0] = (jint)sp[0];
- res[1] = (jint)sp[1];
- (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
- int res;
- int buf[1];
- buf[0] = 1;
- RESTARTABLE(write(fd, buf, 1), res);
- if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "write failed");
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
- int res;
- char buf[1];
- RESTARTABLE(read(fd, buf, 1), res);
- if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_close0(JNIEnv *env, jclass c, jint fd) {
- int res;
- RESTARTABLE(close(fd), res);
-}
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueue.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueue.java Fri Mar 23 18:44:47 2018 +0000
@@ -84,17 +84,17 @@
}
/**
- * Returns the file descriptor from a kevent (assuming to be in ident field)
+ * Returns the file descriptor from a kevent (assuming it is in the ident field)
*/
static int getDescriptor(long address) {
return unsafe.getInt(address + OFFSET_IDENT);
}
- static int getFilter(long address) {
+ static short getFilter(long address) {
return unsafe.getShort(address + OFFSET_FILTER);
}
- static int getFlags(long address) {
+ static short getFlags(long address) {
return unsafe.getShort(address + OFFSET_FLAGS);
}
@@ -108,11 +108,11 @@
private static native int flagsOffset();
- static native int kqueue() throws IOException;
+ static native int create() throws IOException;
- static native int keventRegister(int kqpfd, int fd, int filter, int flags);
+ static native int register(int kqfd, int fd, int filter, int flags);
- static native int keventPoll(int kqpfd, long pollAddress, int nevents)
+ static native int poll(int kqfd, long pollAddress, int nevents, long timeout)
throws IOException;
static {
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2011, 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
- * 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.
- */
-
-/*
- * KQueueArrayWrapper.java
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- * Derived from Sun's DevPollArrayWrapper
- */
-
-package sun.nio.ch;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedList;
-import sun.security.action.GetPropertyAction;
-
-/*
- * struct kevent { // 32-bit 64-bit
- * uintptr_t ident; // 4 8
- * short filter; // 2 2
- * u_short flags; // 2 2
- * u_int fflags; // 4 4
- * intptr_t data; // 4 8
- * void *udata; // 4 8
- * } // Total: 20 32
- *
- * The implementation works in 32-bit and 64-bit world. We do this by calling a
- * native function that actually sets the sizes and offsets of the fields based
- * on which mode we're in.
- */
-
-class KQueueArrayWrapper {
- // kevent filters
- static short EVFILT_READ;
- static short EVFILT_WRITE;
-
- // kevent struct
- // These fields are now set by initStructSizes in the static initializer.
- static short SIZEOF_KEVENT;
- static short FD_OFFSET;
- static short FILTER_OFFSET;
-
- // kevent array size
- static final int NUM_KEVENTS = 128;
-
- // Are we in a 64-bit VM?
- static boolean is64bit;
-
- // The kevent array (used for outcoming events only)
- private final AllocatedNativeObject keventArray;
- private final long keventArrayAddress;
-
- // The kqueue fd
- private final int kq;
-
- // The fd of the interrupt line going out
- private final int outgoingInterruptFD;
-
-
- static {
- IOUtil.load();
- initStructSizes();
- String datamodel =
- GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
- is64bit = "64".equals(datamodel);
- }
-
- KQueueArrayWrapper(int fd0, int fd1) throws IOException {
- int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
- keventArray = new AllocatedNativeObject(allocationSize, true);
- keventArrayAddress = keventArray.address();
- kq = init();
- register0(kq, fd0, 1, 0);
- outgoingInterruptFD = fd1;
- }
-
- // Used to update file description registrations
- private static class Update {
- SelChImpl channel;
- int events;
- Update(SelChImpl channel, int events) {
- this.channel = channel;
- this.events = events;
- }
- }
-
- private LinkedList<Update> updateList = new LinkedList<Update>();
-
- int getReventOps(int index) {
- int result = 0;
- int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
- short filter = keventArray.getShort(offset);
-
- // This is all that's necessary based on inspection of usage:
- // SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
- // ServerSocketChannelImpl, SocketChannelImpl
- if (filter == EVFILT_READ) {
- result |= Net.POLLIN;
- } else if (filter == EVFILT_WRITE) {
- result |= Net.POLLOUT;
- }
-
- return result;
- }
-
- int getDescriptor(int index) {
- int offset = SIZEOF_KEVENT*index + FD_OFFSET;
- /* The ident field is 8 bytes in 64-bit world, however the API wants us
- * to return an int. Hence read the 8 bytes but return as an int.
- */
- if (is64bit) {
- long fd = keventArray.getLong(offset);
- assert fd <= Integer.MAX_VALUE;
- return (int) fd;
- } else {
- return keventArray.getInt(offset);
- }
- }
-
- void setInterest(SelChImpl channel, int events) {
- synchronized (updateList) {
- // update existing registration
- updateList.add(new Update(channel, events));
- }
- }
-
- void release(SelChImpl channel) {
- synchronized (updateList) {
- // flush any pending updates
- for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {
- if (it.next().channel == channel) {
- it.remove();
- }
- }
-
- // remove
- register0(kq, channel.getFDVal(), 0, 0);
- }
- }
-
- void updateRegistrations() {
- synchronized (updateList) {
- Update u;
- while ((u = updateList.poll()) != null) {
- SelChImpl ch = u.channel;
- if (!ch.isOpen())
- continue;
-
- register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);
- }
- }
- }
-
- void close() throws IOException {
- FileDispatcherImpl.closeIntFD(kq);
- keventArray.free();
- }
-
- int poll(long timeout) {
- updateRegistrations();
- return kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
- }
-
- void interrupt() {
- interrupt(outgoingInterruptFD);
- }
-
- private native int init();
- private static native void initStructSizes();
-
- private native void register0(int kq, int fd, int read, int write);
- private native int kevent0(int kq, long keventAddress, int keventCount,
- long timeout);
- private static native void interrupt(int fd);
-}
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -30,7 +30,11 @@
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
-import static sun.nio.ch.KQueue.*;
+
+import static sun.nio.ch.KQueue.EVFILT_READ;
+import static sun.nio.ch.KQueue.EVFILT_WRITE;
+import static sun.nio.ch.KQueue.EV_ADD;
+import static sun.nio.ch.KQueue.EV_ONESHOT;
/**
* AsynchronousChannelGroup implementation based on the BSD kqueue facility.
@@ -45,6 +49,9 @@
// kqueue file descriptor
private final int kqfd;
+ // address of the poll array passed to kqueue_wait
+ private final long address;
+
// true if kqueue closed
private boolean closed;
@@ -54,9 +61,6 @@
// number of wakeups pending
private final AtomicInteger wakeupCount = new AtomicInteger();
- // address of the poll array passed to kqueue_wait
- private final long address;
-
// encapsulates an event for a channel
static class Event {
final PollableChannel channel;
@@ -82,28 +86,25 @@
{
super(provider, pool);
- // open kqueue
- this.kqfd = kqueue();
+ this.kqfd = KQueue.create();
+ this.address = KQueue.allocatePollArray(MAX_KEVENTS_TO_POLL);
// create socket pair for wakeup mechanism
- int[] sv = new int[2];
try {
- socketpair(sv);
+ long fds = IOUtil.makePipe(true);
+ this.sp = new int[]{(int) (fds >>> 32), (int) fds};
+ } catch (IOException ioe) {
+ KQueue.freePollArray(address);
+ FileDispatcherImpl.closeIntFD(kqfd);
+ throw ioe;
+ }
- // register one end with kqueue
- keventRegister(kqfd, sv[0], EVFILT_READ, EV_ADD);
- } catch (IOException x) {
- close0(kqfd);
- throw x;
- }
- this.sp = sv;
-
- // allocate the poll array
- this.address = allocatePollArray(MAX_KEVENTS_TO_POLL);
+ // register one end with kqueue
+ KQueue.register(kqfd, sp[0], EVFILT_READ, EV_ADD);
// create the queue and offer the special event to ensure that the first
// threads polls
- this.queue = new ArrayBlockingQueue<Event>(MAX_KEVENTS_TO_POLL);
+ this.queue = new ArrayBlockingQueue<>(MAX_KEVENTS_TO_POLL);
this.queue.offer(NEED_TO_POLL);
}
@@ -121,17 +122,18 @@
return;
closed = true;
}
- freePollArray(address);
- close0(sp[0]);
- close0(sp[1]);
- close0(kqfd);
+
+ try { FileDispatcherImpl.closeIntFD(kqfd); } catch (IOException ioe) { }
+ try { FileDispatcherImpl.closeIntFD(sp[0]); } catch (IOException ioe) { }
+ try { FileDispatcherImpl.closeIntFD(sp[1]); } catch (IOException ioe) { }
+ KQueue.freePollArray(address);
}
private void wakeup() {
if (wakeupCount.incrementAndGet() == 1) {
// write byte to socketpair to force wakeup
try {
- interrupt(sp[1]);
+ IOUtil.write1(sp[1], (byte)0);
} catch (IOException x) {
throw new AssertionError(x);
}
@@ -173,9 +175,9 @@
int err = 0;
int flags = (EV_ADD|EV_ONESHOT);
if ((events & Net.POLLIN) > 0)
- err = keventRegister(kqfd, fd, EVFILT_READ, flags);
+ err = KQueue.register(kqfd, fd, EVFILT_READ, flags);
if (err == 0 && (events & Net.POLLOUT) > 0)
- err = keventRegister(kqfd, fd, EVFILT_WRITE, flags);
+ err = KQueue.register(kqfd, fd, EVFILT_WRITE, flags);
if (err != 0)
throw new InternalError("kevent failed: " + err); // should not happen
}
@@ -193,7 +195,11 @@
private Event poll() throws IOException {
try {
for (;;) {
- int n = keventPoll(kqfd, address, MAX_KEVENTS_TO_POLL);
+ int n;
+ do {
+ n = KQueue.poll(kqfd, address, MAX_KEVENTS_TO_POLL, -1L);
+ } while (n == IOStatus.INTERRUPTED);
+
/*
* 'n' events have been read. Here we map them to their
* corresponding channel in batch and queue n-1 so that
@@ -203,14 +209,14 @@
fdToChannelLock.readLock().lock();
try {
while (n-- > 0) {
- long keventAddress = getEvent(address, n);
- int fd = getDescriptor(keventAddress);
+ long keventAddress = KQueue.getEvent(address, n);
+ int fd = KQueue.getDescriptor(keventAddress);
// wakeup
if (fd == sp[0]) {
if (wakeupCount.decrementAndGet() == 0) {
// no more wakeups so drain pipe
- drain1(sp[0]);
+ IOUtil.drain(sp[0]);
}
// queue special event if there are more events
@@ -224,7 +230,7 @@
PollableChannel channel = fdToChannel.get(fd);
if (channel != null) {
- int filter = getFilter(keventAddress);
+ int filter = KQueue.getFilter(keventAddress);
int events = 0;
if (filter == EVFILT_READ)
events = Net.POLLIN;
@@ -314,18 +320,4 @@
}
}
}
-
- // -- Native methods --
-
- private static native void socketpair(int[] sv) throws IOException;
-
- private static native void interrupt(int fd) throws IOException;
-
- private static native void drain1(int fd) throws IOException;
-
- private static native void close0(int fd);
-
- static {
- IOUtil.load();
- }
}
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -23,11 +23,6 @@
* questions.
*/
-/*
- * KQueueSelectorImpl.java
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- */
-
package sun.nio.ch;
import java.io.IOException;
@@ -36,85 +31,111 @@
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
+import java.util.ArrayDeque;
+import java.util.BitSet;
+import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
-class KQueueSelectorImpl
- extends SelectorImpl
-{
- // File descriptors used for interrupt
+import static sun.nio.ch.KQueue.EVFILT_READ;
+import static sun.nio.ch.KQueue.EVFILT_WRITE;
+import static sun.nio.ch.KQueue.EV_ADD;
+import static sun.nio.ch.KQueue.EV_DELETE;
+
+/**
+ * KQueue based Selector implementation for macOS
+ */
+
+class KQueueSelectorImpl extends SelectorImpl {
+
+ // maximum number of events to poll in one call to kqueue
+ private static final int MAX_KEVENTS = 256;
+
+ // kqueue file descriptor
+ private final int kqfd;
+
+ // address of poll array (event list) when polling for pending events
+ private final long pollArrayAddress;
+
+ // file descriptors used for interrupt
private final int fd0;
private final int fd1;
- // The kqueue manipulator
- private final KQueueArrayWrapper kqueueWrapper;
+ // maps file descriptor to selection key, synchronize on selector
+ private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
+
+ // file descriptors registered with kqueue, synchronize on selector
+ private final BitSet registeredReadFilter = new BitSet();
+ private final BitSet registeredWriteFilter = new BitSet();
- // Map from a file descriptor to an entry containing the selection key
- private final HashMap<Integer, MapEntry> fdMap;
+ // pending new registrations/updates, queued by implRegister and putEventOps
+ private final Object updateLock = new Object();
+ private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
+ private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
+ private final Deque<Integer> updateOps = new ArrayDeque<>();
- // True if this Selector has been closed
- private boolean closed;
-
- // Lock for interrupt triggering and clearing
+ // interrupt triggering and clearing
private final Object interruptLock = new Object();
private boolean interruptTriggered;
// used by updateSelectedKeys to handle cases where the same file
// descriptor is polled by more than one filter
- private long updateCount;
+ private int pollCount;
- // Used to map file descriptors to a selection key and "update count"
- // (see updateSelectedKeys for usage).
- private static class MapEntry {
- SelectionKeyImpl ski;
- long updateCount;
- MapEntry(SelectionKeyImpl ski) {
- this.ski = ski;
- }
- }
-
- /**
- * Package private constructor called by factory method in
- * the abstract superclass Selector.
- */
KQueueSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
- long fds = IOUtil.makePipe(false);
- fd0 = (int)(fds >>> 32);
- fd1 = (int)fds;
+
+ this.kqfd = KQueue.create();
+ this.pollArrayAddress = KQueue.allocatePollArray(MAX_KEVENTS);
+
try {
- kqueueWrapper = new KQueueArrayWrapper(fd0, fd1);
- fdMap = new HashMap<>();
- } catch (Throwable t) {
- try {
- FileDispatcherImpl.closeIntFD(fd0);
- } catch (IOException ioe0) {
- t.addSuppressed(ioe0);
- }
- try {
- FileDispatcherImpl.closeIntFD(fd1);
- } catch (IOException ioe1) {
- t.addSuppressed(ioe1);
- }
- throw t;
+ long fds = IOUtil.makePipe(false);
+ this.fd0 = (int) (fds >>> 32);
+ this.fd1 = (int) fds;
+ } catch (IOException ioe) {
+ KQueue.freePollArray(pollArrayAddress);
+ FileDispatcherImpl.closeIntFD(kqfd);
+ throw ioe;
}
+
+ // register one end of the socket pair for wakeups
+ KQueue.register(kqfd, fd0, EVFILT_READ, EV_ADD);
}
private void ensureOpen() {
- if (closed)
+ if (!isOpen())
throw new ClosedSelectorException();
}
@Override
- protected int doSelect(long timeout)
- throws IOException
- {
- ensureOpen();
+ protected int doSelect(long timeout) throws IOException {
+ assert Thread.holdsLock(this);
+
int numEntries;
+ processUpdateQueue();
processDeregisterQueue();
try {
begin();
- numEntries = kqueueWrapper.poll(timeout);
+
+ long to = Math.min(timeout, Integer.MAX_VALUE); // max kqueue timeout
+ boolean timedPoll = (to > 0);
+ do {
+ long startTime = timedPoll ? System.nanoTime() : 0;
+ numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, to);
+ if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
+ // timed poll interrupted so need to adjust timeout
+ long adjust = System.nanoTime() - startTime;
+ to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
+ if (to <= 0) {
+ // timeout expired so no retry
+ numEntries = 0;
+ }
+ }
+ } while (numEntries == IOStatus.INTERRUPTED);
+ assert IOStatus.check(numEntries);
+
} finally {
end();
}
@@ -123,39 +144,100 @@
}
/**
+ * Process new registrations and changes to the interest ops.
+ */
+ private void processUpdateQueue() {
+ assert Thread.holdsLock(this);
+
+ synchronized (updateLock) {
+ SelectionKeyImpl ski;
+
+ // new registrations
+ while ((ski = newKeys.pollFirst()) != null) {
+ if (ski.isValid()) {
+ SelChImpl ch = ski.channel;
+ int fd = ch.getFDVal();
+ SelectionKeyImpl previous = fdToKey.put(fd, ski);
+ assert previous == null;
+ assert registeredReadFilter.get(fd) == false;
+ assert registeredWriteFilter.get(fd) == false;
+ }
+ }
+
+ // changes to interest ops
+ assert updateKeys.size() == updateOps.size();
+ while ((ski = updateKeys.pollFirst()) != null) {
+ int ops = updateOps.pollFirst();
+ int fd = ski.channel.getFDVal();
+ if (ski.isValid() && fdToKey.containsKey(fd)) {
+ // add or delete interest in read events
+ if (registeredReadFilter.get(fd)) {
+ if ((ops & Net.POLLIN) == 0) {
+ KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
+ registeredReadFilter.clear(fd);
+ }
+ } else if ((ops & Net.POLLIN) != 0) {
+ KQueue.register(kqfd, fd, EVFILT_READ, EV_ADD);
+ registeredReadFilter.set(fd);
+ }
+
+ // add or delete interest in write events
+ if (registeredWriteFilter.get(fd)) {
+ if ((ops & Net.POLLOUT) == 0) {
+ KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
+ registeredWriteFilter.clear(fd);
+ }
+ } else if ((ops & Net.POLLOUT) != 0) {
+ KQueue.register(kqfd, fd, EVFILT_WRITE, EV_ADD);
+ registeredWriteFilter.set(fd);
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Update the keys whose fd's have been selected by kqueue.
* Add the ready keys to the selected key set.
* If the interrupt fd has been selected, drain it and clear the interrupt.
*/
- private int updateSelectedKeys(int numEntries)
- throws IOException
- {
+ private int updateSelectedKeys(int numEntries) throws IOException {
+ assert Thread.holdsLock(this);
+ assert Thread.holdsLock(nioSelectedKeys());
+
int numKeysUpdated = 0;
boolean interrupted = false;
// A file descriptor may be registered with kqueue with more than one
- // filter and so there may be more than one event for a fd. The update
- // count in the MapEntry tracks when the fd was last updated and this
- // ensures that the ready ops are updated rather than replaced by a
- // second or subsequent event.
- updateCount++;
+ // filter and so there may be more than one event for a fd. The poll
+ // count is incremented here and compared against the SelectionKey's
+ // "lastPolled" field. This ensures that the ready ops is updated rather
+ // than replaced when a file descriptor is polled by both the read and
+ // write filter.
+ pollCount++;
for (int i = 0; i < numEntries; i++) {
- int nextFD = kqueueWrapper.getDescriptor(i);
- if (nextFD == fd0) {
+ long kevent = KQueue.getEvent(pollArrayAddress, i);
+ int fd = KQueue.getDescriptor(kevent);
+ if (fd == fd0) {
interrupted = true;
} else {
- MapEntry me = fdMap.get(Integer.valueOf(nextFD));
- if (me != null) {
- int rOps = kqueueWrapper.getReventOps(i);
- SelectionKeyImpl ski = me.ski;
+ SelectionKeyImpl ski = fdToKey.get(fd);
+ if (ski != null) {
+ int rOps = 0;
+ short filter = KQueue.getFilter(kevent);
+ if (filter == EVFILT_READ) {
+ rOps |= Net.POLLIN;
+ } else if (filter == EVFILT_WRITE) {
+ rOps |= Net.POLLOUT;
+ }
+
if (selectedKeys.contains(ski)) {
- // first time this file descriptor has been encountered on this
- // update?
- if (me.updateCount != updateCount) {
+ // file descriptor may be polled more than once per poll
+ if (ski.lastPolled != pollCount) {
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
numKeysUpdated++;
- me.updateCount = updateCount;
+ ski.lastPolled = pollCount;
}
} else {
// ready ops have already been set on this update
@@ -166,7 +248,7 @@
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
selectedKeys.add(ski);
numKeysUpdated++;
- me.updateCount = updateCount;
+ ski.lastPolled = pollCount;
}
}
}
@@ -181,63 +263,90 @@
@Override
protected void implClose() throws IOException {
- if (!closed) {
- closed = true;
+ assert !isOpen();
+ assert Thread.holdsLock(this);
+ assert Thread.holdsLock(nioKeys());
- // prevent further wakeup
- synchronized (interruptLock) {
- interruptTriggered = true;
- }
+ // prevent further wakeup
+ synchronized (interruptLock) {
+ interruptTriggered = true;
+ }
+
+ FileDispatcherImpl.closeIntFD(kqfd);
+ KQueue.freePollArray(pollArrayAddress);
- kqueueWrapper.close();
- FileDispatcherImpl.closeIntFD(fd0);
- FileDispatcherImpl.closeIntFD(fd1);
+ FileDispatcherImpl.closeIntFD(fd0);
+ FileDispatcherImpl.closeIntFD(fd1);
- // Deregister channels
- Iterator<SelectionKey> i = keys.iterator();
- while (i.hasNext()) {
- SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
- deregister(ski);
- SelectableChannel selch = ski.channel();
- if (!selch.isOpen() && !selch.isRegistered())
- ((SelChImpl)selch).kill();
- i.remove();
- }
+ // Deregister channels
+ Iterator<SelectionKey> i = keys.iterator();
+ while (i.hasNext()) {
+ SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
+ deregister(ski);
+ SelectableChannel selch = ski.channel();
+ if (!selch.isOpen() && !selch.isRegistered())
+ ((SelChImpl)selch).kill();
+ i.remove();
}
}
@Override
protected void implRegister(SelectionKeyImpl ski) {
+ assert Thread.holdsLock(nioKeys());
ensureOpen();
- int fd = IOUtil.fdVal(ski.channel.getFD());
- fdMap.put(Integer.valueOf(fd), new MapEntry(ski));
+ synchronized (updateLock) {
+ newKeys.addLast(ski);
+ }
keys.add(ski);
}
@Override
protected void implDereg(SelectionKeyImpl ski) throws IOException {
+ assert !ski.isValid();
+ assert Thread.holdsLock(this);
+ assert Thread.holdsLock(nioKeys());
+ assert Thread.holdsLock(nioSelectedKeys());
+
int fd = ski.channel.getFDVal();
- fdMap.remove(Integer.valueOf(fd));
- kqueueWrapper.release(ski.channel);
+ fdToKey.remove(fd);
+ if (registeredReadFilter.get(fd)) {
+ KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
+ registeredReadFilter.clear(fd);
+ }
+ if (registeredWriteFilter.get(fd)) {
+ KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
+ registeredWriteFilter.clear(fd);
+ }
+
+ selectedKeys.remove(ski);
keys.remove(ski);
- selectedKeys.remove(ski);
+
+ // remove from channel's key set
deregister(ski);
+
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
- ((SelChImpl)selch).kill();
+ ((SelChImpl) selch).kill();
}
@Override
public void putEventOps(SelectionKeyImpl ski, int ops) {
ensureOpen();
- kqueueWrapper.setInterest(ski.channel, ops);
+ synchronized (updateLock) {
+ updateOps.addLast(ops); // ops first in case adding the key fails
+ updateKeys.addLast(ski);
+ }
}
@Override
public Selector wakeup() {
synchronized (interruptLock) {
if (!interruptTriggered) {
- kqueueWrapper.interrupt();
+ try {
+ IOUtil.write1(fd1, (byte)0);
+ } catch (IOException ioe) {
+ throw new InternalError(ioe);
+ }
interruptTriggered = true;
}
}
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorProvider.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorProvider.java Fri Mar 23 18:44:47 2018 +0000
@@ -23,17 +23,10 @@
* questions.
*/
-/*
- * KQueueSelectorProvider.java
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- * Derived from Sun's DevPollSelectorProvider
- */
-
package sun.nio.ch;
import java.io.IOException;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
+import java.nio.channels.spi.AbstractSelector;
public class KQueueSelectorProvider
extends SelectorProviderImpl
--- a/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,7 +26,6 @@
package sun.nio.fs;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.spi.FileTypeDetector;
import sun.security.action.GetPropertyAction;
@@ -46,7 +45,7 @@
@Override
FileTypeDetector getFileTypeDetector() {
- Path userMimeTypes = Paths.get(GetPropertyAction
+ Path userMimeTypes = Path.of(GetPropertyAction
.privilegedGetProperty("user.home"), ".mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
--- a/src/java.base/macosx/native/libnio/ch/KQueue.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/macosx/native/libnio/ch/KQueue.c Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -23,76 +23,91 @@
* questions.
*/
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include "sun_nio_ch_KQueue.h"
-
#include <strings.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+
+#include "sun_nio_ch_KQueue.h"
+
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_keventSize(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_keventSize(JNIEnv* env, jclass clazz)
{
return sizeof(struct kevent);
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_identOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_identOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct kevent, ident);
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_filterOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_filterOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct kevent, filter);
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_flagsOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_flagsOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct kevent, flags);
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_kqueue(JNIEnv *env, jclass c) {
+Java_sun_nio_ch_KQueue_create(JNIEnv *env, jclass clazz) {
int kqfd = kqueue();
if (kqfd < 0) {
JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
+ return IOS_THROWN;
}
return kqfd;
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_keventRegister(JNIEnv *env, jclass c, jint kqfd,
- jint fd, jint filter, jint flags)
+Java_sun_nio_ch_KQueue_register(JNIEnv *env, jclass clazz, jint kqfd,
+ jint fd, jint filter, jint flags)
{
struct kevent changes[1];
- struct timespec timeout = {0, 0};
int res;
EV_SET(&changes[0], fd, filter, flags, 0, 0, 0);
- RESTARTABLE(kevent(kqfd, &changes[0], 1, NULL, 0, &timeout), res);
+ RESTARTABLE(kevent(kqfd, &changes[0], 1, NULL, 0, NULL), res);
return (res == -1) ? errno : 0;
}
JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_keventPoll(JNIEnv *env, jclass c,
- jint kqfd, jlong address, jint nevents)
+Java_sun_nio_ch_KQueue_poll(JNIEnv *env, jclass clazz, jint kqfd, jlong address,
+ jint nevents, jlong timeout)
{
struct kevent *events = jlong_to_ptr(address);
int res;
+ struct timespec ts;
+ struct timespec *tsp;
- RESTARTABLE(kevent(kqfd, NULL, 0, events, nevents, NULL), res);
+ if (timeout >= 0) {
+ ts.tv_sec = timeout / 1000;
+ ts.tv_nsec = (timeout % 1000) * 1000000;
+ tsp = &ts;
+ } else {
+ tsp = NULL;
+ }
+
+ res = kevent(kqfd, NULL, 0, events, nevents, tsp);
if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
+ if (errno == EINTR) {
+ return IOS_INTERRUPTED;
+ } else {
+ JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
+ return IOS_THROWN;
+ }
}
return res;
}
--- a/src/java.base/macosx/native/libnio/ch/KQueueArrayWrapper.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2011, 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
- * 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.
- */
-
-/*
- * KQueueArrayWrapper.c
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- * Derived from Sun's DevPollArrayWrapper
- */
-
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_initStructSizes(JNIEnv *env, jclass clazz)
-{
-#define CHECK_EXCEPTION() { \
- if ((*env)->ExceptionCheck(env)) { \
- goto exceptionOccurred; \
- } \
-}
-
-#define CHECK_ERROR_AND_EXCEPTION(_field) { \
- if (_field == NULL) { \
- goto badField; \
- } \
- CHECK_EXCEPTION(); \
-}
-
-
- jfieldID field;
-
- field = (*env)->GetStaticFieldID(env, clazz, "EVFILT_READ", "S");
- CHECK_ERROR_AND_EXCEPTION(field);
- (*env)->SetStaticShortField(env, clazz, field, EVFILT_READ);
- CHECK_EXCEPTION();
-
- field = (*env)->GetStaticFieldID(env, clazz, "EVFILT_WRITE", "S");
- CHECK_ERROR_AND_EXCEPTION(field);
- (*env)->SetStaticShortField(env, clazz, field, EVFILT_WRITE);
- CHECK_EXCEPTION();
-
- field = (*env)->GetStaticFieldID(env, clazz, "SIZEOF_KEVENT", "S");
- CHECK_ERROR_AND_EXCEPTION(field);
- (*env)->SetStaticShortField(env, clazz, field, (short) sizeof(struct kevent));
- CHECK_EXCEPTION();
-
- field = (*env)->GetStaticFieldID(env, clazz, "FD_OFFSET", "S");
- CHECK_ERROR_AND_EXCEPTION(field);
- (*env)->SetStaticShortField(env, clazz, field, (short) offsetof(struct kevent, ident));
- CHECK_EXCEPTION();
-
- field = (*env)->GetStaticFieldID(env, clazz, "FILTER_OFFSET", "S");
- CHECK_ERROR_AND_EXCEPTION(field);
- (*env)->SetStaticShortField(env, clazz, field, (short) offsetof(struct kevent, filter));
- CHECK_EXCEPTION();
- return;
-
-badField:
- return;
-
-exceptionOccurred:
- return;
-
-#undef CHECK_EXCEPTION
-#undef CHECK_ERROR_AND_EXCEPTION
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_init(JNIEnv *env, jobject this)
-{
- int kq = kqueue();
- if (kq < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "KQueueArrayWrapper: kqueue() failed");
- }
- return kq;
-}
-
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_register0(JNIEnv *env, jobject this,
- jint kq, jint fd, jint r, jint w)
-{
- struct kevent changes[2];
- struct kevent errors[2];
- struct timespec dontBlock = {0, 0};
-
- // if (r) then { register for read } else { unregister for read }
- // if (w) then { register for write } else { unregister for write }
- // Ignore errors - they're probably complaints about deleting non-
- // added filters - but provide an error array anyway because
- // kqueue behaves erratically if some of its registrations fail.
- EV_SET(&changes[0], fd, EVFILT_READ, r ? EV_ADD : EV_DELETE, 0, 0, 0);
- EV_SET(&changes[1], fd, EVFILT_WRITE, w ? EV_ADD : EV_DELETE, 0, 0, 0);
- kevent(kq, changes, 2, errors, 2, &dontBlock);
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_kevent0(JNIEnv *env, jobject this, jint kq,
- jlong kevAddr, jint kevCount,
- jlong timeout)
-{
- struct kevent *kevs = (struct kevent *)jlong_to_ptr(kevAddr);
- struct timespec ts;
- struct timespec *tsp;
- int result;
-
- // Java timeout is in milliseconds. Convert to struct timespec.
- // Java timeout == -1 : wait forever : timespec timeout of NULL
- // Java timeout == 0 : return immediately : timespec timeout of zero
- if (timeout >= 0) {
- // For some indeterminate reason kevent(2) has been found to fail with
- // an EINVAL error for timeout values greater than or equal to
- // 100000001000L. To avoid this problem, clamp the timeout arbitrarily
- // to the maximum value of a 32-bit signed integer which is
- // approximately 25 days in milliseconds.
- const jlong timeoutMax = 0x7fffffff; // java.lang.Integer.MAX_VALUE
- if (timeout > timeoutMax) {
- timeout = timeoutMax;
- }
- ts.tv_sec = timeout / 1000;
- ts.tv_nsec = (timeout % 1000) * 1000000; //nanosec = 1 million millisec
- tsp = &ts;
- } else {
- tsp = NULL;
- }
-
- RESTARTABLE(kevent(kq, NULL, 0, kevs, kevCount, tsp), result);
- if (result < 0) {
- JNU_ThrowIOExceptionWithLastError(env,
- "KQueueArrayWrapper: kevent poll failed");
- }
-
- return result;
-}
-
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_interrupt(JNIEnv *env, jclass cls, jint fd)
-{
- char c = 1;
- if (1 != write(fd, &c, 1)) {
- JNU_ThrowIOExceptionWithLastError(env, "KQueueArrayWrapper: interrupt failed");
- }
-}
-
--- a/src/java.base/macosx/native/libnio/ch/KQueuePort.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 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 "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include "sun_nio_ch_KQueuePort.h"
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
- int sp[2];
- if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
- JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
- } else {
- jint res[2];
- res[0] = (jint)sp[0];
- res[1] = (jint)sp[1];
- (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_interrupt(JNIEnv *env, jclass c, jint fd) {
- int res;
- int buf[1];
- buf[0] = 1;
- RESTARTABLE(write(fd, buf, 1), res);
- if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "write failed");
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_drain1(JNIEnv *env, jclass cl, jint fd) {
- int res;
- char buf[1];
- RESTARTABLE(read(fd, buf, 1), res);
- if (res < 0) {
- JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
- }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_close0(JNIEnv *env, jclass c, jint fd) {
- int res;
- RESTARTABLE(close(fd), res);
-}
--- a/src/java.base/share/classes/java/io/ByteArrayInputStream.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/io/ByteArrayInputStream.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -25,12 +25,15 @@
package java.io;
+import java.util.Arrays;
+import java.util.Objects;
+
/**
- * A <code>ByteArrayInputStream</code> contains
+ * A {@code ByteArrayInputStream} contains
* an internal buffer that contains bytes that
* may be read from the stream. An internal
* counter keeps track of the next byte to
- * be supplied by the <code>read</code> method.
+ * be supplied by the {@code read} method.
* <p>
* Closing a {@code ByteArrayInputStream} has no effect. The methods in
* this class can be called after the stream has been closed without
@@ -40,15 +43,14 @@
* @see java.io.StringBufferInputStream
* @since 1.0
*/
-public
-class ByteArrayInputStream extends InputStream {
+public class ByteArrayInputStream extends InputStream {
/**
* An array of bytes that was provided
- * by the creator of the stream. Elements <code>buf[0]</code>
- * through <code>buf[count-1]</code> are the
+ * by the creator of the stream. Elements {@code buf[0]}
+ * through {@code buf[count-1]} are the
* only bytes that can ever be read from the
- * stream; element <code>buf[pos]</code> is
+ * stream; element {@code buf[pos]} is
* the next byte to be read.
*/
protected byte buf[];
@@ -56,9 +58,9 @@
/**
* The index of the next character to read from the input stream buffer.
* This value should always be nonnegative
- * and not larger than the value of <code>count</code>.
+ * and not larger than the value of {@code count}.
* The next byte to be read from the input stream buffer
- * will be <code>buf[pos]</code>.
+ * will be {@code buf[pos]}.
*/
protected int pos;
@@ -66,9 +68,9 @@
* The currently marked position in the stream.
* ByteArrayInputStream objects are marked at position zero by
* default when constructed. They may be marked at another
- * position within the buffer by the <code>mark()</code> method.
+ * position within the buffer by the {@code mark()} method.
* The current buffer position is set to this point by the
- * <code>reset()</code> method.
+ * {@code reset()} method.
* <p>
* If no mark has been set, then the value of mark is the offset
* passed to the constructor (or 0 if the offset was not supplied).
@@ -81,22 +83,22 @@
* The index one greater than the last valid character in the input
* stream buffer.
* This value should always be nonnegative
- * and not larger than the length of <code>buf</code>.
+ * and not larger than the length of {@code buf}.
* It is one greater than the position of
- * the last byte within <code>buf</code> that
+ * the last byte within {@code buf} that
* can ever be read from the input stream buffer.
*/
protected int count;
/**
- * Creates a <code>ByteArrayInputStream</code>
- * so that it uses <code>buf</code> as its
+ * Creates a {@code ByteArrayInputStream}
+ * so that it uses {@code buf} as its
* buffer array.
* The buffer array is not copied.
- * The initial value of <code>pos</code>
- * is <code>0</code> and the initial value
- * of <code>count</code> is the length of
- * <code>buf</code>.
+ * The initial value of {@code pos}
+ * is {@code 0} and the initial value
+ * of {@code count} is the length of
+ * {@code buf}.
*
* @param buf the input buffer.
*/
@@ -107,12 +109,12 @@
}
/**
- * Creates <code>ByteArrayInputStream</code>
- * that uses <code>buf</code> as its
- * buffer array. The initial value of <code>pos</code>
- * is <code>offset</code> and the initial value
- * of <code>count</code> is the minimum of <code>offset+length</code>
- * and <code>buf.length</code>.
+ * Creates {@code ByteArrayInputStream}
+ * that uses {@code buf} as its
+ * buffer array. The initial value of {@code pos}
+ * is {@code offset} and the initial value
+ * of {@code count} is the minimum of {@code offset+length}
+ * and {@code buf.length}.
* The buffer array is not copied. The buffer's mark is
* set to the specified offset.
*
@@ -129,15 +131,15 @@
/**
* Reads the next byte of data from this input stream. The value
- * byte is returned as an <code>int</code> in the range
- * <code>0</code> to <code>255</code>. If no byte is available
+ * byte is returned as an {@code int} in the range
+ * {@code 0} to {@code 255}. If no byte is available
* because the end of the stream has been reached, the value
- * <code>-1</code> is returned.
+ * {@code -1} is returned.
* <p>
- * This <code>read</code> method
+ * This {@code read} method
* cannot block.
*
- * @return the next byte of data, or <code>-1</code> if the end of the
+ * @return the next byte of data, or {@code -1} if the end of the
* stream has been reached.
*/
public synchronized int read() {
@@ -145,40 +147,30 @@
}
/**
- * Reads up to <code>len</code> bytes of data into an array of bytes
- * from this input stream.
- * If <code>pos</code> equals <code>count</code>,
- * then <code>-1</code> is returned to indicate
- * end of file. Otherwise, the number <code>k</code>
- * of bytes read is equal to the smaller of
- * <code>len</code> and <code>count-pos</code>.
- * If <code>k</code> is positive, then bytes
- * <code>buf[pos]</code> through <code>buf[pos+k-1]</code>
- * are copied into <code>b[off]</code> through
- * <code>b[off+k-1]</code> in the manner performed
- * by <code>System.arraycopy</code>. The
- * value <code>k</code> is added into <code>pos</code>
- * and <code>k</code> is returned.
+ * Reads up to {@code len} bytes of data into an array of bytes from this
+ * input stream. If {@code pos} equals {@code count}, then {@code -1} is
+ * returned to indicate end of file. Otherwise, the number {@code k} of
+ * bytes read is equal to the smaller of {@code len} and {@code count-pos}.
+ * If {@code k} is positive, then bytes {@code buf[pos]} through
+ * {@code buf[pos+k-1]} are copied into {@code b[off]} through
+ * {@code b[off+k-1]} in the manner performed by {@code System.arraycopy}.
+ * The value {@code k} is added into {@code pos} and {@code k} is returned.
* <p>
- * This <code>read</code> method cannot block.
+ * This {@code read} method cannot block.
*
* @param b the buffer into which the data is read.
- * @param off the start offset in the destination array <code>b</code>
+ * @param off the start offset in the destination array {@code b}
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
- * <code>-1</code> if there is no more data because the end of
+ * {@code -1} if there is no more data because the end of
* the stream has been reached.
- * @exception NullPointerException If <code>b</code> is <code>null</code>.
- * @exception IndexOutOfBoundsException If <code>off</code> is negative,
- * <code>len</code> is negative, or <code>len</code> is greater than
- * <code>b.length - off</code>
+ * @throws NullPointerException If {@code b} is {@code null}.
+ * @throws IndexOutOfBoundsException If {@code off} is negative,
+ * {@code len} is negative, or {@code len} is greater than
+ * {@code b.length - off}
*/
public synchronized int read(byte b[], int off, int len) {
- if (b == null) {
- throw new NullPointerException();
- } else if (off < 0 || len < 0 || len > b.length - off) {
- throw new IndexOutOfBoundsException();
- }
+ Objects.checkFromIndexSize(off, len, b.length);
if (pos >= count) {
return -1;
@@ -196,14 +188,32 @@
return len;
}
+ public synchronized byte[] readAllBytes() {
+ byte[] result = Arrays.copyOfRange(buf, pos, count);
+ pos = count;
+ return result;
+ }
+
+ public int readNBytes(byte[] b, int off, int len) {
+ int n = read(b, off, len);
+ return n == -1 ? 0 : n;
+ }
+
+ public synchronized long transferTo(OutputStream out) throws IOException {
+ int len = count - pos;
+ out.write(buf, pos, len);
+ pos = count;
+ return len;
+ }
+
/**
- * Skips <code>n</code> bytes of input from this input stream. Fewer
+ * Skips {@code n} bytes of input from this input stream. Fewer
* bytes might be skipped if the end of the input stream is reached.
- * The actual number <code>k</code>
+ * The actual number {@code k}
* of bytes to be skipped is equal to the smaller
- * of <code>n</code> and <code>count-pos</code>.
- * The value <code>k</code> is added into <code>pos</code>
- * and <code>k</code> is returned.
+ * of {@code n} and {@code count-pos}.
+ * The value {@code k} is added into {@code pos}
+ * and {@code k} is returned.
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
@@ -222,7 +232,7 @@
* Returns the number of remaining bytes that can be read (or skipped over)
* from this input stream.
* <p>
- * The value returned is <code>count - pos</code>,
+ * The value returned is {@code count - pos},
* which is the number of bytes remaining to be read from the input buffer.
*
* @return the number of remaining bytes that can be read (or skipped
@@ -233,9 +243,9 @@
}
/**
- * Tests if this <code>InputStream</code> supports mark/reset. The
- * <code>markSupported</code> method of <code>ByteArrayInputStream</code>
- * always returns <code>true</code>.
+ * Tests if this {@code InputStream} supports mark/reset. The
+ * {@code markSupported} method of {@code ByteArrayInputStream}
+ * always returns {@code true}.
*
* @since 1.1
*/
@@ -253,7 +263,7 @@
* offset passed to the constructor (or 0 if the offset was not
* supplied).
*
- * <p> Note: The <code>readAheadLimit</code> for this class
+ * <p> Note: The {@code readAheadLimit} for this class
* has no meaning.
*
* @since 1.1
--- a/src/java.base/share/classes/java/lang/invoke/ProxyClassesDumper.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/ProxyClassesDumper.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -30,7 +30,6 @@
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Objects;
@@ -63,7 +62,7 @@
}
try {
path = path.trim();
- final Path dir = Paths.get(path.length() == 0 ? "." : path);
+ final Path dir = Path.of(path.length() == 0 ? "." : path);
AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public Void run() {
--- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, 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
@@ -34,7 +34,6 @@
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -346,11 +345,11 @@
int i = name.lastIndexOf('.');
Path path;
if (i > 0) {
- Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
+ Path dir = Path.of(name.substring(0, i).replace('.', File.separatorChar));
Files.createDirectories(dir);
path = dir.resolve(name.substring(i+1, name.length()) + ".class");
} else {
- path = Paths.get(name + ".class");
+ path = Path.of(name + ".class");
}
Files.write(path, classFile);
return null;
--- a/src/java.base/share/classes/java/nio/StringCharBuffer.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/nio/StringCharBuffer.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -149,7 +149,7 @@
that, that.position(),
Math.min(this.remaining(), that.remaining()));
if (i >= 0) {
- return Character.compare(this.get(this.position() + i), that.get(this.position() + i));
+ return Character.compare(this.get(this.position() + i), that.get(that.position() + i));
}
return this.remaining() - that.remaining();
}
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -1337,7 +1337,7 @@
that, that.position(),
Math.min(this.remaining(), that.remaining()));
if (i >= 0) {
- return compare(this.get(this.position() + i), that.get(this.position() + i));
+ return compare(this.get(this.position() + i), that.get(that.position() + i));
}
return this.remaining() - that.remaining();
}
--- a/src/java.base/share/classes/java/nio/channels/DatagramChannel.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/nio/channels/DatagramChannel.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -279,6 +279,9 @@
*
* @return This datagram channel
*
+ * @throws AlreadyConnectedException
+ * If this channel is already connected
+ *
* @throws ClosedChannelException
* If this channel is closed
*
@@ -292,6 +295,12 @@
* closing the channel and setting the current thread's
* interrupt status
*
+ * @throws UnresolvedAddressException
+ * If the given remote address is not fully resolved
+ *
+ * @throws UnsupportedAddressTypeException
+ * If the type of the given remote address is not supported
+ *
* @throws SecurityException
* If a security manager has been installed
* and it does not permit access to the given remote address
@@ -444,6 +453,10 @@
* zero if there was insufficient room for the datagram in the
* underlying output buffer
*
+ * @throws AlreadyConnectedException
+ * If this channel is connected to a different address
+ * from that specified by {@code target}
+ *
* @throws ClosedChannelException
* If this channel is closed
*
@@ -457,6 +470,12 @@
* closing the channel and setting the current thread's
* interrupt status
*
+ * @throws UnresolvedAddressException
+ * If the given remote address is not fully resolved
+ *
+ * @throws UnsupportedAddressTypeException
+ * If the type of the given remote address is not supported
+ *
* @throws SecurityException
* If a security manager has been installed
* and it does not permit datagrams to be sent
--- a/src/java.base/share/classes/java/nio/file/Path.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/nio/file/Path.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -28,6 +28,7 @@
import java.io.File;
import java.io.IOException;
import java.net.URI;
+import java.nio.file.spi.FileSystemProvider;
import java.util.Iterator;
import java.util.NoSuchElementException;
@@ -93,13 +94,125 @@
* multiple concurrent threads.
*
* @since 1.7
- * @see Paths
*/
public interface Path
extends Comparable<Path>, Iterable<Path>, Watchable
{
/**
+ * Returns a {@code Path} by converting a path string, or a sequence of
+ * strings that when joined form a path string. If {@code more} does not
+ * specify any elements then the value of the {@code first} parameter is
+ * the path string to convert. If {@code more} specifies one or more
+ * elements then each non-empty string, including {@code first}, is
+ * considered to be a sequence of name elements and is joined to form a
+ * path string. The details as to how the Strings are joined is provider
+ * specific but typically they will be joined using the
+ * {@link FileSystem#getSeparator name-separator} as the separator.
+ * For example, if the name separator is "{@code /}" and
+ * {@code getPath("/foo","bar","gus")} is invoked, then the path string
+ * {@code "/foo/bar/gus"} is converted to a {@code Path}. A {@code Path}
+ * representing an empty path is returned if {@code first} is the empty
+ * string and {@code more} does not contain any non-empty strings.
+ *
+ * <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
+ * getPath} method of the {@link FileSystems#getDefault default} {@link
+ * FileSystem}.
+ *
+ * <p> Note that while this method is very convenient, using it will imply
+ * an assumed reference to the default {@code FileSystem} and limit the
+ * utility of the calling code. Hence it should not be used in library code
+ * intended for flexible reuse. A more flexible alternative is to use an
+ * existing {@code Path} instance as an anchor, such as:
+ * <pre>{@code
+ * Path dir = ...
+ * Path path = dir.resolve("file");
+ * }</pre>
+ *
+ * @param first
+ * the path string or initial part of the path string
+ * @param more
+ * additional strings to be joined to form the path string
+ *
+ * @return the resulting {@code Path}
+ *
+ * @throws InvalidPathException
+ * if the path string cannot be converted to a {@code Path}
+ *
+ * @see FileSystem#getPath
+ *
+ * @since 11
+ */
+ public static Path of(String first, String... more) {
+ return FileSystems.getDefault().getPath(first, more);
+ }
+
+ /**
+ * Returns a {@code Path} by converting a URI.
+ *
+ * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+ * installed} providers to locate the provider that is identified by the
+ * URI {@link URI#getScheme scheme} of the given URI. URI schemes are
+ * compared without regard to case. If the provider is found then its {@link
+ * FileSystemProvider#getPath getPath} method is invoked to convert the
+ * URI.
+ *
+ * <p> In the case of the default provider, identified by the URI scheme
+ * "file", the given URI has a non-empty path component, and undefined query
+ * and fragment components. Whether the authority component may be present
+ * is platform specific. The returned {@code Path} is associated with the
+ * {@link FileSystems#getDefault default} file system.
+ *
+ * <p> The default provider provides a similar <em>round-trip</em> guarantee
+ * to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
+ * is guaranteed that
+ * <blockquote>{@code
+ * Path.of(}<i>p</i>{@code .}{@link Path#toUri() toUri}{@code ()).equals(}
+ * <i>p</i>{@code .}{@link Path#toAbsolutePath() toAbsolutePath}{@code ())}
+ * </blockquote>
+ * so long as the original {@code Path}, the {@code URI}, and the new {@code
+ * Path} are all created in (possibly different invocations of) the same
+ * Java virtual machine. Whether other providers make any guarantees is
+ * provider specific and therefore unspecified.
+ *
+ * @param uri
+ * the URI to convert
+ *
+ * @return the resulting {@code Path}
+ *
+ * @throws IllegalArgumentException
+ * if preconditions on the {@code uri} parameter do not hold. The
+ * format of the URI is provider specific.
+ * @throws FileSystemNotFoundException
+ * The file system, identified by the URI, does not exist and
+ * cannot be created automatically, or the provider identified by
+ * the URI's scheme component is not installed
+ * @throws SecurityException
+ * if a security manager is installed and it denies an unspecified
+ * permission to access the file system
+ *
+ * @since 11
+ */
+ public static Path of(URI uri) {
+ String scheme = uri.getScheme();
+ if (scheme == null)
+ throw new IllegalArgumentException("Missing scheme");
+
+ // check for default provider to avoid loading of installed providers
+ if (scheme.equalsIgnoreCase("file"))
+ return FileSystems.getDefault().provider().getPath(uri);
+
+ // try to find provider
+ for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+ if (provider.getScheme().equalsIgnoreCase(scheme)) {
+ return provider.getPath(uri);
+ }
+ }
+
+ throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");
+ }
+
+ /**
* Returns the file system that created this object.
*
* @return the file system that created this object
@@ -527,7 +640,7 @@
* to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
* is guaranteed that
* <blockquote>
- * {@link Paths#get(URI) Paths.get}{@code (}<i>p</i>{@code .toUri()).equals(}<i>p</i>
+ * {@link Path#of(URI) Path.of}{@code (}<i>p</i>{@code .toUri()).equals(}<i>p</i>
* {@code .}{@link #toAbsolutePath() toAbsolutePath}{@code ())}
* </blockquote>
* so long as the original {@code Path}, the {@code URI}, and the new {@code
--- a/src/java.base/share/classes/java/nio/file/Paths.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/nio/file/Paths.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -32,7 +32,13 @@
* This class consists exclusively of static methods that return a {@link Path}
* by converting a path string or {@link URI}.
*
+ * @apiNote
+ * It is recommended to obtain a {@code Path} via the {@code Path.of} methods
+ * instead of via the {@code get} methods defined in this class as this class
+ * may be deprecated in a future release.
+ *
* @since 1.7
+ * @see Path
*/
public final class Paths {
@@ -40,33 +46,11 @@
/**
* Converts a path string, or a sequence of strings that when joined form
- * a path string, to a {@code Path}. If {@code more} does not specify any
- * elements then the value of the {@code first} parameter is the path string
- * to convert. If {@code more} specifies one or more elements then each
- * non-empty string, including {@code first}, is considered to be a sequence
- * of name elements (see {@link Path}) and is joined to form a path string.
- * The details as to how the Strings are joined is provider specific but
- * typically they will be joined using the {@link FileSystem#getSeparator
- * name-separator} as the separator. For example, if the name separator is
- * "{@code /}" and {@code getPath("/foo","bar","gus")} is invoked, then the
- * path string {@code "/foo/bar/gus"} is converted to a {@code Path}.
- * A {@code Path} representing an empty path is returned if {@code first}
- * is the empty string and {@code more} does not contain any non-empty
- * strings.
+ * a path string, to a {@code Path}.
*
- * <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
- * getPath} method of the {@link FileSystems#getDefault default} {@link
- * FileSystem}.
- *
- * <p> Note that while this method is very convenient, using it will imply
- * an assumed reference to the default {@code FileSystem} and limit the
- * utility of the calling code. Hence it should not be used in library code
- * intended for flexible reuse. A more flexible alternative is to use an
- * existing {@code Path} instance as an anchor, such as:
- * <pre>
- * Path dir = ...
- * Path path = dir.resolve("file");
- * </pre>
+ * @implSpec
+ * This method simply invokes {@link Path#of(String,String...)
+ * Path.of(String, String...)} with the given parameters.
*
* @param first
* the path string or initial part of the path string
@@ -79,38 +63,17 @@
* if the path string cannot be converted to a {@code Path}
*
* @see FileSystem#getPath
+ * @see Path#of(String,String...)
*/
public static Path get(String first, String... more) {
- return FileSystems.getDefault().getPath(first, more);
+ return Path.of(first, more);
}
/**
* Converts the given URI to a {@link Path} object.
*
- * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
- * installed} providers to locate the provider that is identified by the
- * URI {@link URI#getScheme scheme} of the given URI. URI schemes are
- * compared without regard to case. If the provider is found then its {@link
- * FileSystemProvider#getPath getPath} method is invoked to convert the
- * URI.
- *
- * <p> In the case of the default provider, identified by the URI scheme
- * "file", the given URI has a non-empty path component, and undefined query
- * and fragment components. Whether the authority component may be present
- * is platform specific. The returned {@code Path} is associated with the
- * {@link FileSystems#getDefault default} file system.
- *
- * <p> The default provider provides a similar <em>round-trip</em> guarantee
- * to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
- * is guaranteed that
- * <blockquote>{@code
- * Paths.get(}<i>p</i>{@code .}{@link Path#toUri() toUri}{@code ()).equals(}
- * <i>p</i>{@code .}{@link Path#toAbsolutePath() toAbsolutePath}{@code ())}
- * </blockquote>
- * so long as the original {@code Path}, the {@code URI}, and the new {@code
- * Path} are all created in (possibly different invocations of) the same
- * Java virtual machine. Whether other providers make any guarantees is
- * provider specific and therefore unspecified.
+ * @implSpec
+ * This method simply invokes {@link Path#of(URI) * Path.of(URI)} with the given parameter.
*
* @param uri
* the URI to convert
@@ -127,23 +90,10 @@
* @throws SecurityException
* if a security manager is installed and it denies an unspecified
* permission to access the file system
+ *
+ * @see Path#of(URI)
*/
public static Path get(URI uri) {
- String scheme = uri.getScheme();
- if (scheme == null)
- throw new IllegalArgumentException("Missing scheme");
-
- // check for default provider to avoid loading of installed providers
- if (scheme.equalsIgnoreCase("file"))
- return FileSystems.getDefault().provider().getPath(uri);
-
- // try to find provider
- for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
- if (provider.getScheme().equalsIgnoreCase(scheme)) {
- return provider.getPath(uri);
- }
- }
-
- throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");
+ return Path.of(uri);
}
}
--- a/src/java.base/share/classes/java/nio/file/TempFileHelper.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/nio/file/TempFileHelper.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -46,7 +46,7 @@
// temporary directory location
private static final Path tmpdir =
- Paths.get(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
+ Path.of(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
private static final boolean isPosix =
FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
--- a/src/java.base/share/classes/java/util/AbstractSet.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/util/AbstractSet.java Fri Mar 23 18:44:47 2018 +0000
@@ -93,9 +93,7 @@
return false;
try {
return containsAll(c);
- } catch (ClassCastException unused) {
- return false;
- } catch (NullPointerException unused) {
+ } catch (ClassCastException | NullPointerException unused) {
return false;
}
}
--- a/src/java.base/share/classes/java/util/ImmutableCollections.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/util/ImmutableCollections.java Fri Mar 23 18:44:47 2018 +0000
@@ -70,46 +70,297 @@
static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
- // ---------- List Implementations ----------
-
- abstract static class AbstractImmutableList<E> extends AbstractList<E>
- implements RandomAccess, Serializable {
+ static abstract class AbstractImmutableCollection<E> extends AbstractCollection<E> {
+ // all mutating methods throw UnsupportedOperationException
@Override public boolean add(E e) { throw uoe(); }
@Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
- @Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
@Override public void clear() { throw uoe(); }
@Override public boolean remove(Object o) { throw uoe(); }
@Override public boolean removeAll(Collection<?> c) { throw uoe(); }
@Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }
+ @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
+ }
+
+ // ---------- List Implementations ----------
+
+ @SuppressWarnings("unchecked")
+ static <E> List<E> emptyList() {
+ return (List<E>) ListN.EMPTY_LIST;
+ }
+
+ static abstract class AbstractImmutableList<E> extends AbstractImmutableCollection<E>
+ implements List<E>, RandomAccess {
+
+ // all mutating methods throw UnsupportedOperationException
+ @Override public void add(int index, E element) { throw uoe(); }
+ @Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
+ @Override public E remove(int index) { throw uoe(); }
@Override public void replaceAll(UnaryOperator<E> operator) { throw uoe(); }
- @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
+ @Override public E set(int index, E element) { throw uoe(); }
@Override public void sort(Comparator<? super E> c) { throw uoe(); }
+
+ @Override
+ public List<E> subList(int fromIndex, int toIndex) {
+ int size = size();
+ subListRangeCheck(fromIndex, toIndex, size);
+ return SubList.fromList(this, fromIndex, toIndex);
+ }
+
+ static void subListRangeCheck(int fromIndex, int toIndex, int size) {
+ if (fromIndex < 0)
+ throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+ if (toIndex > size)
+ throw new IndexOutOfBoundsException("toIndex = " + toIndex);
+ if (fromIndex > toIndex)
+ throw new IllegalArgumentException("fromIndex(" + fromIndex +
+ ") > toIndex(" + toIndex + ")");
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new ListItr<E>(this, size());
+ }
+
+ @Override
+ public ListIterator<E> listIterator() {
+ return listIterator(0);
+ }
+
+ @Override
+ public ListIterator<E> listIterator(final int index) {
+ int size = size();
+ if (index < 0 || index > size) {
+ throw outOfBounds(index);
+ }
+ return new ListItr<E>(this, size, index);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+
+ if (!(o instanceof List)) {
+ return false;
+ }
+
+ Iterator<?> oit = ((List<?>) o).iterator();
+ for (int i = 0, s = size(); i < s; i++) {
+ if (!oit.hasNext() || !get(i).equals(oit.next())) {
+ return false;
+ }
+ }
+ return !oit.hasNext();
+ }
+
+ @Override
+ public int indexOf(Object o) {
+ Objects.requireNonNull(o);
+ for (int i = 0, s = size(); i < s; i++) {
+ if (o.equals(get(i))) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int lastIndexOf(Object o) {
+ Objects.requireNonNull(o);
+ for (int i = size() - 1; i >= 0; i--) {
+ if (o.equals(get(i))) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 1;
+ for (int i = 0, s = size(); i < s; i++) {
+ hash = 31 * hash + get(i).hashCode();
+ }
+ return hash;
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return indexOf(o) >= 0;
+ }
+
+ IndexOutOfBoundsException outOfBounds(int index) {
+ return new IndexOutOfBoundsException("Index: " + index + " Size: " + size());
+ }
}
- static final class List0<E> extends AbstractImmutableList<E> {
- private static final List0<?> INSTANCE = new List0<>();
+ static final class ListItr<E> implements ListIterator<E> {
+
+ @Stable
+ private final List<E> list;
+
+ @Stable
+ private final int size;
+
+ private int cursor;
+
+ ListItr(List<E> list, int size) {
+ this(list, size, 0);
+ }
+
+ ListItr(List<E> list, int size, int index) {
+ this.list = list;
+ this.size = size;
+ this.cursor = index;
+ }
+
+ public boolean hasNext() {
+ return cursor != size;
+ }
- @SuppressWarnings("unchecked")
- static <T> List0<T> instance() {
- return (List0<T>) INSTANCE;
+ public E next() {
+ try {
+ int i = cursor;
+ E next = list.get(i);
+ cursor = i + 1;
+ return next;
+ } catch (IndexOutOfBoundsException e) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public void remove() {
+ throw uoe();
+ }
+
+ public boolean hasPrevious() {
+ return cursor != 0;
+ }
+
+ public E previous() {
+ try {
+ int i = cursor - 1;
+ E previous = list.get(i);
+ cursor = i;
+ return previous;
+ } catch (IndexOutOfBoundsException e) {
+ throw new NoSuchElementException();
+ }
+ }
+
+ public int nextIndex() {
+ return cursor;
+ }
+
+ public int previousIndex() {
+ return cursor - 1;
+ }
+
+ public void set(E e) {
+ throw uoe();
}
- private List0() { }
+ public void add(E e) {
+ throw uoe();
+ }
+ }
+
+ static final class SubList<E> extends AbstractImmutableList<E>
+ implements RandomAccess {
+
+ @Stable
+ private final List<E> root;
+
+ @Stable
+ private final int offset;
+
+ @Stable
+ private final int size;
+
+ private SubList(List<E> root, int offset, int size) {
+ this.root = root;
+ this.offset = offset;
+ this.size = size;
+ }
+
+ /**
+ * Constructs a sublist of another SubList.
+ */
+ static <E> SubList<E> fromSubList(SubList<E> parent, int fromIndex, int toIndex) {
+ return new SubList<E>(parent.root, parent.offset + fromIndex, toIndex - fromIndex);
+ }
+
+ /**
+ * Constructs a sublist of an arbitrary AbstractImmutableList, which is
+ * not a SubList itself.
+ */
+ static <E> SubList<E> fromList(List<E> list, int fromIndex, int toIndex) {
+ return new SubList<E>(list, fromIndex, toIndex - fromIndex);
+ }
+
+ public E get(int index) {
+ Objects.checkIndex(index, size);
+ return root.get(offset + index);
+ }
+
+ public int size() {
+ return size;
+ }
+
+ public Iterator<E> iterator() {
+ return new ListItr<E>(this, size());
+ }
+
+ public ListIterator<E> listIterator(int index) {
+ rangeCheck(index);
+ return new ListItr<E>(this, size(), index);
+ }
+
+ public List<E> subList(int fromIndex, int toIndex) {
+ subListRangeCheck(fromIndex, toIndex, size);
+ return SubList.fromSubList(this, fromIndex, toIndex);
+ }
+
+ private void rangeCheck(int index) {
+ if (index < 0 || index > size) {
+ throw outOfBounds(index);
+ }
+ }
+ }
+
+ static final class List12<E> extends AbstractImmutableList<E>
+ implements Serializable {
+
+ @Stable
+ private final E e0;
+
+ @Stable
+ private final E e1;
+
+ List12(E e0) {
+ this.e0 = Objects.requireNonNull(e0);
+ this.e1 = null;
+ }
+
+ List12(E e0, E e1) {
+ this.e0 = Objects.requireNonNull(e0);
+ this.e1 = Objects.requireNonNull(e1);
+ }
@Override
public int size() {
- return 0;
+ return e1 != null ? 2 : 1;
}
@Override
public E get(int index) {
- Objects.checkIndex(index, 0); // always throws IndexOutOfBoundsException
- return null; // but the compiler doesn't know this
- }
-
- @Override
- public Iterator<E> iterator() {
- return Collections.emptyIterator();
+ if (index == 0) {
+ return e0;
+ } else if (index == 1 && e1 != null) {
+ return e1;
+ }
+ throw outOfBounds(index);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@@ -117,111 +368,20 @@
}
private Object writeReplace() {
- return new CollSer(CollSer.IMM_LIST);
- }
-
- @Override
- public boolean contains(Object o) {
- Objects.requireNonNull(o);
- return false;
- }
-
- @Override
- public boolean containsAll(Collection<?> o) {
- return o.isEmpty(); // implicit nullcheck of o
- }
-
- @Override
- public int hashCode() {
- return 1;
- }
- }
-
- static final class List1<E> extends AbstractImmutableList<E> {
- @Stable
- private final E e0;
-
- List1(E e0) {
- this.e0 = Objects.requireNonNull(e0);
- }
-
- @Override
- public int size() {
- return 1;
- }
-
- @Override
- public E get(int index) {
- Objects.checkIndex(index, 1);
- return e0;
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- throw new InvalidObjectException("not serial proxy");
- }
-
- private Object writeReplace() {
- return new CollSer(CollSer.IMM_LIST, e0);
- }
-
- @Override
- public boolean contains(Object o) {
- return o.equals(e0); // implicit nullcheck of o
- }
-
- @Override
- public int hashCode() {
- return 31 + e0.hashCode();
- }
- }
-
- static final class List2<E> extends AbstractImmutableList<E> {
- @Stable
- private final E e0;
- @Stable
- private final E e1;
-
- List2(E e0, E e1) {
- this.e0 = Objects.requireNonNull(e0);
- this.e1 = Objects.requireNonNull(e1);
- }
-
- @Override
- public int size() {
- return 2;
- }
-
- @Override
- public E get(int index) {
- Objects.checkIndex(index, 2);
- if (index == 0) {
- return e0;
- } else { // index == 1
- return e1;
+ if (e1 == null) {
+ return new CollSer(CollSer.IMM_LIST, e0);
+ } else {
+ return new CollSer(CollSer.IMM_LIST, e0, e1);
}
}
- @Override
- public boolean contains(Object o) {
- return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
- }
-
- @Override
- public int hashCode() {
- int hash = 31 + e0.hashCode();
- return 31 * hash + e1.hashCode();
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- throw new InvalidObjectException("not serial proxy");
- }
-
- private Object writeReplace() {
- return new CollSer(CollSer.IMM_LIST, e0, e1);
- }
}
- static final class ListN<E> extends AbstractImmutableList<E> {
+ static final class ListN<E> extends AbstractImmutableList<E>
+ implements Serializable {
+
+ static final List<?> EMPTY_LIST = new ListN<>();
+
@Stable
private final E[] elements;
@@ -233,7 +393,12 @@
for (int i = 0; i < input.length; i++) {
tmp[i] = Objects.requireNonNull(input[i]);
}
- this.elements = tmp;
+ elements = tmp;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size() == 0;
}
@Override
@@ -243,29 +408,9 @@
@Override
public E get(int index) {
- Objects.checkIndex(index, elements.length);
return elements[index];
}
- @Override
- public boolean contains(Object o) {
- for (E e : elements) {
- if (o.equals(e)) { // implicit nullcheck of o
- return true;
- }
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- int hash = 1;
- for (E e : elements) {
- hash = 31 * hash + e.hashCode();
- }
- return hash;
- }
-
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
@@ -277,105 +422,52 @@
// ---------- Set Implementations ----------
- abstract static class AbstractImmutableSet<E> extends AbstractSet<E> implements Serializable {
- @Override public boolean add(E e) { throw uoe(); }
- @Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
- @Override public void clear() { throw uoe(); }
- @Override public boolean remove(Object o) { throw uoe(); }
- @Override public boolean removeAll(Collection<?> c) { throw uoe(); }
- @Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }
- @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
- }
-
- static final class Set0<E> extends AbstractImmutableSet<E> {
- private static final Set0<?> INSTANCE = new Set0<>();
-
- @SuppressWarnings("unchecked")
- static <T> Set0<T> instance() {
- return (Set0<T>) INSTANCE;
- }
-
- private Set0() { }
+ static abstract class AbstractImmutableSet<E> extends AbstractImmutableCollection<E>
+ implements Set<E> {
@Override
- public int size() {
- return 0;
- }
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ } else if (!(o instanceof Set)) {
+ return false;
+ }
- @Override
- public boolean contains(Object o) {
- Objects.requireNonNull(o);
- return false;
- }
-
- @Override
- public boolean containsAll(Collection<?> o) {
- return o.isEmpty(); // implicit nullcheck of o
+ Collection<?> c = (Collection<?>) o;
+ if (c.size() != size()) {
+ return false;
+ }
+ for (Object e : c) {
+ if (e == null || !contains(e)) {
+ return false;
+ }
+ }
+ return true;
}
@Override
- public Iterator<E> iterator() {
- return Collections.emptyIterator();
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- throw new InvalidObjectException("not serial proxy");
- }
-
- private Object writeReplace() {
- return new CollSer(CollSer.IMM_SET);
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
+ public abstract int hashCode();
}
- static final class Set1<E> extends AbstractImmutableSet<E> {
- @Stable
- private final E e0;
-
- Set1(E e0) {
- this.e0 = Objects.requireNonNull(e0);
- }
-
- @Override
- public int size() {
- return 1;
- }
-
- @Override
- public boolean contains(Object o) {
- return o.equals(e0); // implicit nullcheck of o
- }
-
- @Override
- public Iterator<E> iterator() {
- return Collections.singletonIterator(e0);
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- throw new InvalidObjectException("not serial proxy");
- }
-
- private Object writeReplace() {
- return new CollSer(CollSer.IMM_SET, e0);
- }
-
- @Override
- public int hashCode() {
- return e0.hashCode();
- }
+ @SuppressWarnings("unchecked")
+ static <E> Set<E> emptySet() {
+ return (Set<E>) SetN.EMPTY_SET;
}
- static final class Set2<E> extends AbstractImmutableSet<E> {
+ static final class Set12<E> extends AbstractImmutableSet<E>
+ implements Serializable {
+
@Stable
final E e0;
@Stable
final E e1;
- Set2(E e0, E e1) {
+ Set12(E e0) {
+ this.e0 = Objects.requireNonNull(e0);
+ this.e1 = null;
+ }
+
+ Set12(E e0, E e1) {
if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0
throw new IllegalArgumentException("duplicate element: " + e0);
}
@@ -391,7 +483,7 @@
@Override
public int size() {
- return 2;
+ return (e1 == null) ? 1 : 2;
}
@Override
@@ -401,26 +493,26 @@
@Override
public int hashCode() {
- return e0.hashCode() + e1.hashCode();
+ return e0.hashCode() + (e1 == null ? 0 : e1.hashCode());
}
@Override
public Iterator<E> iterator() {
- return new Iterator<E>() {
- private int idx = 0;
+ return new Iterator<>() {
+ private int idx = size();
@Override
public boolean hasNext() {
- return idx < 2;
+ return idx > 0;
}
@Override
public E next() {
- if (idx == 0) {
- idx = 1;
+ if (idx == 1) {
+ idx = 0;
return e0;
- } else if (idx == 1) {
- idx = 2;
+ } else if (idx == 2) {
+ idx = 1;
return e1;
} else {
throw new NoSuchElementException();
@@ -434,7 +526,11 @@
}
private Object writeReplace() {
- return new CollSer(CollSer.IMM_SET, e0, e1);
+ if (e1 == null) {
+ return new CollSer(CollSer.IMM_SET, e0);
+ } else {
+ return new CollSer(CollSer.IMM_SET, e0, e1);
+ }
}
}
@@ -444,7 +540,11 @@
* least one null is always present.
* @param <E> the element type
*/
- static final class SetN<E> extends AbstractImmutableSet<E> {
+ static final class SetN<E> extends AbstractImmutableSet<E>
+ implements Serializable {
+
+ static final Set<?> EMPTY_SET = new SetN<>();
+
@Stable
final E[] elements;
@Stable
@@ -474,12 +574,13 @@
@Override
public boolean contains(Object o) {
- return probe(o) >= 0; // implicit nullcheck of o
+ Objects.requireNonNull(o);
+ return size > 0 && probe(o) >= 0;
}
@Override
public Iterator<E> iterator() {
- return new Iterator<E>() {
+ return new Iterator<>() {
private int idx = 0;
@Override
@@ -549,6 +650,11 @@
// ---------- Map Implementations ----------
+ @SuppressWarnings("unchecked")
+ static <K,V> Map<K,V> emptyMap() {
+ return (Map<K,V>) MapN.EMPTY_MAP;
+ }
+
abstract static class AbstractImmutableMap<K,V> extends AbstractMap<K,V> implements Serializable {
@Override public void clear() { throw uoe(); }
@Override public V compute(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); }
@@ -565,47 +671,6 @@
@Override public void replaceAll(BiFunction<? super K,? super V,? extends V> f) { throw uoe(); }
}
- static final class Map0<K,V> extends AbstractImmutableMap<K,V> {
- private static final Map0<?,?> INSTANCE = new Map0<>();
-
- @SuppressWarnings("unchecked")
- static <K,V> Map0<K,V> instance() {
- return (Map0<K,V>) INSTANCE;
- }
-
- private Map0() { }
-
- @Override
- public Set<Map.Entry<K,V>> entrySet() {
- return Set.of();
- }
-
- @Override
- public boolean containsKey(Object o) {
- Objects.requireNonNull(o);
- return false;
- }
-
- @Override
- public boolean containsValue(Object o) {
- Objects.requireNonNull(o);
- return false;
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- throw new InvalidObjectException("not serial proxy");
- }
-
- private Object writeReplace() {
- return new CollSer(CollSer.IMM_MAP);
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
- }
-
static final class Map1<K,V> extends AbstractImmutableMap<K,V> {
@Stable
private final K k0;
@@ -656,8 +721,12 @@
* @param <V> the value type
*/
static final class MapN<K,V> extends AbstractImmutableMap<K,V> {
+
+ static final Map<?,?> EMPTY_MAP = new MapN<>();
+
@Stable
final Object[] table; // pairs of key, value
+
@Stable
final int size; // number of pairs
@@ -689,14 +758,16 @@
@Override
public boolean containsKey(Object o) {
- return probe(o) >= 0; // implicit nullcheck of o
+ Objects.requireNonNull(o);
+ return size > 0 && probe(o) >= 0;
}
@Override
public boolean containsValue(Object o) {
+ Objects.requireNonNull(o);
for (int i = 1; i < table.length; i += 2) {
Object v = table[i];
- if (v != null && o.equals(v)) { // implicit nullcheck of o
+ if (v != null && o.equals(v)) {
return true;
}
}
@@ -718,6 +789,10 @@
@Override
@SuppressWarnings("unchecked")
public V get(Object o) {
+ if (size == 0) {
+ Objects.requireNonNull(o);
+ return null;
+ }
int i = probe(o);
if (i >= 0) {
return (V)table[i+1];
@@ -733,7 +808,7 @@
@Override
public Set<Map.Entry<K,V>> entrySet() {
- return new AbstractSet<Map.Entry<K,V>>() {
+ return new AbstractSet<>() {
@Override
public int size() {
return MapN.this.size;
@@ -741,7 +816,7 @@
@Override
public Iterator<Map.Entry<K,V>> iterator() {
- return new Iterator<Map.Entry<K,V>>() {
+ return new Iterator<>() {
int idx = 0;
@Override
@@ -948,7 +1023,7 @@
return Set.of(array);
case IMM_MAP:
if (array.length == 0) {
- return ImmutableCollections.Map0.instance();
+ return ImmutableCollections.emptyMap();
} else if (array.length == 2) {
return new ImmutableCollections.Map1<>(array[0], array[1]);
} else {
--- a/src/java.base/share/classes/java/util/List.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/util/List.java Fri Mar 23 18:44:47 2018 +0000
@@ -788,7 +788,7 @@
* @since 9
*/
static <E> List<E> of() {
- return ImmutableCollections.List0.instance();
+ return ImmutableCollections.emptyList();
}
/**
@@ -804,7 +804,7 @@
* @since 9
*/
static <E> List<E> of(E e1) {
- return new ImmutableCollections.List1<>(e1);
+ return new ImmutableCollections.List12<>(e1);
}
/**
@@ -821,7 +821,7 @@
* @since 9
*/
static <E> List<E> of(E e1, E e2) {
- return new ImmutableCollections.List2<>(e1, e2);
+ return new ImmutableCollections.List12<>(e1, e2);
}
/**
@@ -1031,11 +1031,11 @@
static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
- return ImmutableCollections.List0.instance();
+ return ImmutableCollections.emptyList();
case 1:
- return new ImmutableCollections.List1<>(elements[0]);
+ return new ImmutableCollections.List12<>(elements[0]);
case 2:
- return new ImmutableCollections.List2<>(elements[0], elements[1]);
+ return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}
--- a/src/java.base/share/classes/java/util/Map.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/util/Map.java Fri Mar 23 18:44:47 2018 +0000
@@ -1287,7 +1287,7 @@
* @since 9
*/
static <K, V> Map<K, V> of() {
- return ImmutableCollections.Map0.instance();
+ return ImmutableCollections.emptyMap();
}
/**
@@ -1604,11 +1604,11 @@
@SuppressWarnings("varargs")
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
if (entries.length == 0) { // implicit null check of entries array
- return ImmutableCollections.Map0.instance();
+ return ImmutableCollections.emptyMap();
} else if (entries.length == 1) {
// implicit null check of the array slot
return new ImmutableCollections.Map1<>(entries[0].getKey(),
- entries[0].getValue());
+ entries[0].getValue());
} else {
Object[] kva = new Object[entries.length << 1];
int a = 0;
--- a/src/java.base/share/classes/java/util/Scanner.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/util/Scanner.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -2897,7 +2897,7 @@
* letters:
*
* <pre>{@code
- * try (Scanner sc = new Scanner(Paths.get("input.txt"))) {
+ * try (Scanner sc = new Scanner(Path.of("input.txt"))) {
* Pattern pat = Pattern.compile("[A-Z]{7,}");
* List<String> capWords = sc.findAll(pat)
* .map(MatchResult::group)
--- a/src/java.base/share/classes/java/util/Set.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/java/util/Set.java Fri Mar 23 18:44:47 2018 +0000
@@ -449,7 +449,7 @@
* @since 9
*/
static <E> Set<E> of() {
- return ImmutableCollections.Set0.instance();
+ return ImmutableCollections.emptySet();
}
/**
@@ -464,7 +464,7 @@
* @since 9
*/
static <E> Set<E> of(E e1) {
- return new ImmutableCollections.Set1<>(e1);
+ return new ImmutableCollections.Set12<>(e1);
}
/**
@@ -481,7 +481,7 @@
* @since 9
*/
static <E> Set<E> of(E e1, E e2) {
- return new ImmutableCollections.Set2<>(e1, e2);
+ return new ImmutableCollections.Set12<>(e1, e2);
}
/**
@@ -692,11 +692,11 @@
static <E> Set<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
- return ImmutableCollections.Set0.instance();
+ return ImmutableCollections.emptySet();
case 1:
- return new ImmutableCollections.Set1<>(elements[0]);
+ return new ImmutableCollections.Set12<>(elements[0]);
case 2:
- return new ImmutableCollections.Set2<>(elements[0], elements[1]);
+ return new ImmutableCollections.Set12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.SetN<>(elements);
}
--- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -32,7 +32,6 @@
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
@@ -243,8 +242,8 @@
mn = location.substring(5, location.length());
} else if (location.startsWith("file:/")) {
// named module in exploded image
- Path path = Paths.get(URI.create(location));
- Path modulesDir = Paths.get(JAVA_HOME, "modules");
+ Path path = Path.of(URI.create(location));
+ Path modulesDir = Path.of(JAVA_HOME, "modules");
if (path.startsWith(modulesDir)) {
mn = path.getFileName().toString();
}
@@ -267,7 +266,7 @@
private static URL toFileURL(String location) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
public URL run() {
- Path path = Paths.get(location);
+ Path path = Path.of(location);
if (Files.isRegularFile(path)) {
try {
return path.toUri().toURL();
@@ -285,7 +284,7 @@
private static Manifest getManifest(String location) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
public Manifest run() {
- Path jar = Paths.get(location);
+ Path jar = Path.of(location);
try (InputStream in = Files.newInputStream(jar);
JarInputStream jis = new JarInputStream(in, false)) {
return jis.getManifest();
--- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,7 +28,7 @@
import java.io.IOException;
import java.net.URL;
import java.nio.file.InvalidPathException;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.util.jar.Manifest;
@@ -223,7 +223,7 @@
// Use an intermediate File object to construct a URI/URL without
// authority component as URLClassPath can't handle URLs with a UNC
// server name in the authority component.
- return Paths.get(s).toRealPath().toFile().toURI().toURL();
+ return Path.of(s).toRealPath().toFile().toURI().toURL();
} catch (InvalidPathException | IOException ignore) {
// malformed path string or class path element does not exist
return null;
--- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -34,7 +34,6 @@
import java.lang.module.ResolvedModule;
import java.net.URI;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -539,7 +538,7 @@
Path[] paths = new Path[dirs.length];
int i = 0;
for (String dir: dirs) {
- paths[i++] = Paths.get(dir);
+ paths[i++] = Path.of(dir);
}
return ModulePath.of(patcher, paths);
}
--- a/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -30,7 +30,6 @@
import java.lang.module.ResolvedModule;
import java.net.URI;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
@@ -129,7 +128,7 @@
() -> new InternalError("Selected module " + name + " not on module path"));
URI uri = rm.reference().location().get();
- Path path = Paths.get(uri);
+ Path path = Path.of(uri);
String fn = path.getFileName().toString();
if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
--- a/src/java.base/share/classes/jdk/internal/module/ModulePath.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -43,7 +43,6 @@
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
@@ -360,7 +359,7 @@
URI uri = mref.location().orElse(null);
if (uri != null) {
if (uri.getScheme().equalsIgnoreCase("file")) {
- Path file = Paths.get(uri);
+ Path file = Path.of(uri);
return file.getFileName().toString();
} else {
return uri.toString();
--- a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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,7 +38,6 @@
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayDeque;
@@ -185,7 +184,7 @@
// probe to see if this is an images build
String home = System.getProperty("java.home");
- Path modules = Paths.get(home, "lib", "modules");
+ Path modules = Path.of(home, "lib", "modules");
if (Files.isRegularFile(modules)) {
if (USE_FAST_PATH) {
SystemModules systemModules = allSystemModules();
@@ -205,7 +204,7 @@
}
// exploded build (do not cache module finder)
- Path dir = Paths.get(home, "modules");
+ Path dir = Path.of(home, "modules");
if (!Files.isDirectory(dir))
throw new InternalError("Unable to detect the run-time image");
ModuleFinder f = ModulePath.of(ModuleBootstrap.patcher(), dir);
--- a/src/java.base/share/classes/jdk/internal/perf/PerfCounter.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/jdk/internal/perf/PerfCounter.java Fri Mar 23 18:44:47 2018 +0000
@@ -133,10 +133,6 @@
static final PerfCounter zfot = newPerfCounter("sun.zip.zipFile.openTime");
}
- static class WindowsClientCounters {
- static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available");
- }
-
/**
* Number of findClass calls
*/
@@ -182,10 +178,4 @@
return CoreCounters.zfot;
}
- /**
- * D3D graphic pipeline available
- */
- public static PerfCounter getD3DAvailable() {
- return WindowsClientCounters.d3dAvailable;
- }
}
--- a/src/java.base/share/classes/module-info.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/module-info.java Fri Mar 23 18:44:47 2018 +0000
@@ -159,8 +159,6 @@
jdk.scripting.nashorn;
exports jdk.internal.org.objectweb.asm.signature to
jdk.scripting.nashorn;
- exports jdk.internal.math to
- java.desktop;
exports jdk.internal.misc to
java.desktop,
java.logging,
@@ -188,7 +186,6 @@
jdk.jartool,
jdk.jlink;
exports jdk.internal.perf to
- java.desktop,
java.management,
jdk.management.agent,
jdk.internal.jvmstat;
@@ -235,7 +232,6 @@
jdk.sctp,
jdk.unsupported;
exports sun.nio.cs to
- java.desktop,
jdk.charsets;
exports sun.nio.fs to
jdk.unsupported;
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -508,8 +508,7 @@
if (remote != null) {
// connected
if (!target.equals(remote)) {
- throw new IllegalArgumentException(
- "Connected address not equal to target address");
+ throw new AlreadyConnectedException();
}
do {
n = IOUtil.write(fd, src, -1, nd);
--- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java Fri Mar 23 18:44:47 2018 +0000
@@ -397,7 +397,9 @@
* The read end of the pipe is returned in the high 32 bits,
* while the write end is returned in the low 32 bits.
*/
- static native long makePipe(boolean blocking);
+ static native long makePipe(boolean blocking) throws IOException;
+
+ static native int write1(int fd, byte b) throws IOException;
static native boolean drain(int fd) throws IOException;
--- a/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -33,10 +33,10 @@
/**
- * An implementation of SelectionKey for Solaris.
+ * An implementation of SelectionKey.
*/
-public class SelectionKeyImpl
+public final class SelectionKeyImpl
extends AbstractSelectionKey
{
@@ -54,12 +54,14 @@
selector = sel;
}
+ @Override
public SelectableChannel channel() {
return (SelectableChannel)channel;
}
+ @Override
public Selector selector() {
- return selector;
+ return (Selector)selector;
}
int getIndex() { // package-private
@@ -75,16 +77,19 @@
throw new CancelledKeyException();
}
+ @Override
public int interestOps() {
ensureValid();
return interestOps;
}
+ @Override
public SelectionKey interestOps(int ops) {
ensureValid();
return nioInterestOps(ops);
}
+ @Override
public int readyOps() {
ensureValid();
return readyOps;
@@ -131,4 +136,6 @@
return sb.toString();
}
+ // used by Selector implementations to record when the key was selected
+ int lastPolled;
}
--- a/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -78,6 +78,16 @@
return publicSelectedKeys;
}
+ /**
+ * Returns the public view of the key sets
+ */
+ protected final Set<SelectionKey> nioKeys() {
+ return publicKeys;
+ }
+ protected final Set<SelectionKey> nioSelectedKeys() {
+ return publicSelectedKeys;
+ }
+
protected abstract int doSelect(long timeout) throws IOException;
private int lockAndDoSelect(long timeout) throws IOException {
@@ -125,8 +135,6 @@
protected abstract void implClose() throws IOException;
- public abstract void putEventOps(SelectionKeyImpl sk, int ops);
-
@Override
protected final SelectionKey register(AbstractSelectableChannel ch,
int ops,
@@ -166,4 +174,9 @@
}
}
}
+
+ /**
+ * Invoked to change the key's interest set
+ */
+ public abstract void putEventOps(SelectionKeyImpl ski, int ops);
}
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -210,25 +210,20 @@
@Override
public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
- acceptLock.lock();
- try {
- synchronized (stateLock) {
- ensureOpen();
- if (localAddress != null)
- throw new AlreadyBoundException();
- InetSocketAddress isa = (local == null)
- ? new InetSocketAddress(0)
- : Net.checkAddress(local);
- SecurityManager sm = System.getSecurityManager();
- if (sm != null)
- sm.checkListen(isa.getPort());
- NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
- Net.bind(fd, isa.getAddress(), isa.getPort());
- Net.listen(fd, backlog < 1 ? 50 : backlog);
- localAddress = Net.localAddress(fd);
- }
- } finally {
- acceptLock.unlock();
+ synchronized (stateLock) {
+ ensureOpen();
+ if (localAddress != null)
+ throw new AlreadyBoundException();
+ InetSocketAddress isa = (local == null)
+ ? new InetSocketAddress(0)
+ : Net.checkAddress(local);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkListen(isa.getPort());
+ NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
+ Net.bind(fd, isa.getAddress(), isa.getPort());
+ Net.listen(fd, backlog < 1 ? 50 : backlog);
+ localAddress = Net.localAddress(fd);
}
return this;
}
--- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java Fri Mar 23 18:44:47 2018 +0000
@@ -30,7 +30,7 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URI;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.util.*;
import java.security.*;
import java.security.cert.Certificate;
@@ -278,7 +278,7 @@
public URL run() {
String sep = File.separator;
try {
- return Paths.get(System.getProperty("java.home"),
+ return Path.of(System.getProperty("java.home"),
"lib", "security",
"default.policy").toUri().toURL();
} catch (MalformedURLException mue) {
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Fri Mar 23 18:44:47 2018 +0000
@@ -27,7 +27,7 @@
import java.io.*;
import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
import java.security.CodeSigner;
import java.security.CryptoPrimitive;
import java.security.KeyStore;
@@ -2189,7 +2189,7 @@
inplaceBackupName = srcksfname + ".old" + (n == 1 ? "" : n);
File bkFile = new File(inplaceBackupName);
if (!bkFile.exists()) {
- Files.copy(Paths.get(srcksfname), bkFile.toPath());
+ Files.copy(Path.of(srcksfname), bkFile.toPath());
break;
}
}
--- a/src/java.base/share/native/libjava/System.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/share/native/libjava/System.c Fri Mar 23 18:44:47 2018 +0000
@@ -244,21 +244,8 @@
PUTPROP(props, "line.separator", sprops->line_separator);
/*
- * user.language
- * user.script, user.country, user.variant (if user's environment specifies them)
- * file.encoding
+ * file encoding for stdout and stderr
*/
- PUTPROP(props, "user.language", sprops->language);
- if (sprops->script) {
- PUTPROP(props, "user.script", sprops->script);
- }
- if (sprops->country) {
- PUTPROP(props, "user.country", sprops->country);
- }
- if (sprops->variant) {
- PUTPROP(props, "user.variant", sprops->variant);
- }
- PUTPROP(props, "file.encoding", sprops->encoding);
if (sprops->sun_stdout_encoding != NULL) {
PUTPROP(props, "sun.stdout.encoding", sprops->sun_stdout_encoding);
}
@@ -314,7 +301,7 @@
#endif
/* !!! DO NOT call PUTPROP_ForPlatformNString before this line !!!
- * !!! I18n properties have not been set up yet !!!
+ * !!! The platform native encoding for strings has not been set up yet !!!
*/
InitializeEncoding(env, sprops->sun_jnu_encoding);
@@ -379,17 +366,6 @@
PUTPROP(props, "sun.desktop", sprops->desktop);
}
- /*
- * unset "user.language", "user.script", "user.country", and "user.variant"
- * in order to tell whether the command line option "-DXXXX=YYYY" is
- * specified or not. They will be reset in fillI18nProps() below.
- */
- REMOVEPROP(props, "user.language");
- REMOVEPROP(props, "user.script");
- REMOVEPROP(props, "user.country");
- REMOVEPROP(props, "user.variant");
- REMOVEPROP(props, "file.encoding");
-
ret = JVM_InitProperties(env, props);
/* reconstruct i18n related properties */
--- a/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Fri Mar 23 18:44:47 2018 +0000
@@ -127,7 +127,7 @@
// descriptor is registered with /dev/poll.
private final BitSet registered = new BitSet();
- DevPollArrayWrapper() {
+ DevPollArrayWrapper() throws IOException {
int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
pollArray = new AllocatedNativeObject(allocationSize, true);
pollArrayAddress = pollArray.address();
@@ -136,7 +136,7 @@
eventsHigh = new HashMap<>();
}
- void initInterrupt(int fd0, int fd1) {
+ void initInterrupt(int fd0, int fd1) throws IOException {
outgoingInterruptFD = fd1;
incomingInterruptFD = fd0;
register(wfd, fd0, POLLIN);
@@ -200,7 +200,7 @@
}
}
- void release(int fd) {
+ void release(int fd) throws IOException {
synchronized (updateLock) {
// ignore any pending update for this file descriptor
setUpdateEvents(fd, IGNORE);
@@ -297,7 +297,11 @@
boolean interrupted = false;
public void interrupt() {
- interrupt(outgoingInterruptFD);
+ try {
+ IOUtil.write1(outgoingInterruptFD, (byte)0);
+ } catch (IOException ioe) {
+ throw new InternalError(ioe);
+ }
}
public int interruptedIndex() {
@@ -312,13 +316,12 @@
interrupted = false;
}
- private native int init();
- private native void register(int wfd, int fd, int mask);
+ private native int init() throws IOException;
+ private native void register(int wfd, int fd, int mask) throws IOException;
private native void registerMultiple(int wfd, long address, int len)
throws IOException;
- private native int poll0(long pollAddress, int numfds, long timeout,
- int wfd);
- private static native void interrupt(int fd);
+ private native int poll0(long pollAddress, int numfds, long timeout, int wfd)
+ throws IOException;
static {
IOUtil.load();
--- a/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -61,7 +61,7 @@
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
- DevPollSelectorImpl(SelectorProvider sp) {
+ DevPollSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);
--- a/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -181,12 +181,26 @@
}
// poll for events
- int updated = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout);
+ int numEntries;
+ long to = timeout;
+ boolean timedPoll = (to > 0);
+ do {
+ long startTime = timedPoll ? System.currentTimeMillis() : 0;
+ numEntries = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout);
+ if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
+ // timed poll interrupted so need to adjust timeout
+ to -= System.currentTimeMillis() - startTime;
+ if (to <= 0) {
+ // timeout also expired so no retry
+ numEntries = 0;
+ }
+ }
+ } while (numEntries == IOStatus.INTERRUPTED);
// after polling we need to queue all polled file descriptors as they
// are candidates to register for the next poll.
synchronized (updateLock) {
- for (int i=0; i<updated; i++) {
+ for (int i=0; i<numEntries; i++) {
if (getSource(i) == PORT_SOURCE_USER) {
interrupted = true;
setDescriptor(i, -1);
@@ -199,7 +213,7 @@
}
}
- return updated;
+ return numEntries;
}
private void setInterest(int fd) {
--- a/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -164,7 +164,10 @@
// A error here is fatal (thread will not be replaced)
replaceMe = false;
try {
- port_get(port, address);
+ int n;
+ do {
+ n = port_get(port, address);
+ } while (n == IOStatus.INTERRUPTED);
} catch (IOException x) {
x.printStackTrace();
return;
@@ -240,7 +243,7 @@
/**
* Retrieves a single event from a port
*/
- static native void port_get(int port, long pe) throws IOException;
+ static native int port_get(int port, long address) throws IOException;
/**
* Retrieves at most {@code max} events from a port.
--- a/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -84,9 +84,9 @@
@Override
FileTypeDetector getFileTypeDetector() {
- Path userMimeTypes = Paths.get(
+ Path userMimeTypes = Path.of(
GetPropertyAction.privilegedGetProperty("user.home"), ".mime.types");
- Path etcMimeTypes = Paths.get("/etc/mime.types");
+ Path etcMimeTypes = Path.of("/etc/mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
new MimeTypesFileTypeDetector(etcMimeTypes));
--- a/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -176,14 +176,3 @@
}
return result;
}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_DevPollArrayWrapper_interrupt(JNIEnv *env, jclass this, jint fd)
-{
- int fakebuf[1];
- fakebuf[0] = 1;
- if (write(fd, fakebuf, 1) < 0) {
- JNU_ThrowIOExceptionWithLastError(env,
- "Write to interrupt fd failed");
- }
-}
--- a/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -23,17 +23,18 @@
* questions.
*/
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <port.h>
+
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
+#include "nio.h"
#include "nio_util.h"
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <sys/types.h>
-#include <port.h>
-
#include "sun_nio_ch_SolarisEventPort.h"
JNIEXPORT jint JNICALL
@@ -51,8 +52,10 @@
Java_sun_nio_ch_SolarisEventPort_port_1close
(JNIEnv* env, jclass clazz, jint port)
{
- int res;
- RESTARTABLE(close(port), res);
+ int res = close(port);
+ if (res < 0 && res != EINTR) {
+ JNU_ThrowIOExceptionWithLastError(env, "close failed");
+ }
}
JNIEXPORT jboolean JNICALL
@@ -93,17 +96,23 @@
}
}
-JNIEXPORT void JNICALL
+JNIEXPORT jint JNICALL
Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz,
jint port, jlong eventAddress)
{
int res;
port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress);
- RESTARTABLE(port_get((int)port, ev, NULL), res);
+ res = port_get((int)port, ev, NULL);
if (res == -1) {
- JNU_ThrowIOExceptionWithLastError(env, "port_get");
+ if (errno == EINTR) {
+ return IOS_INTERRUPTED;
+ } else {
+ JNU_ThrowIOExceptionWithLastError(env, "port_get failed");
+ return IOS_THROWN;
+ }
}
+ return res;
}
JNIEXPORT jint JNICALL
@@ -125,9 +134,13 @@
}
res = port_getn((int)port, list, (uint_t)max, &n, tsp);
- if (res == -1) {
- if (errno != ETIME && errno != EINTR)
- JNU_ThrowIOExceptionWithLastError(env, "port_getn");
+ if (res == -1 && errno != ETIME) {
+ if (errno == EINTR) {
+ return IOS_INTERRUPTED;
+ } else {
+ JNU_ThrowIOExceptionWithLastError(env, "port_getn failed");
+ return IOS_THROWN;
+ }
}
return (jint)n;
--- a/src/java.base/unix/classes/module-info.java.extra Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/unix/classes/module-info.java.extra Fri Mar 23 18:44:47 2018 +0000
@@ -23,3 +23,4 @@
* questions.
*/
+exports sun.nio.cs to java.desktop;
--- a/src/java.base/unix/classes/sun/nio/ch/PipeImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/unix/classes/sun/nio/ch/PipeImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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,7 +38,7 @@
private final SourceChannel source;
private final SinkChannel sink;
- PipeImpl(SelectorProvider sp) {
+ PipeImpl(SelectorProvider sp) throws IOException {
long pipeFds = IOUtil.makePipe(true);
int readFd = (int) (pipeFds >>> 32);
int writeFd = (int) pipeFds;
--- a/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -51,7 +51,7 @@
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
- PollSelectorImpl(SelectorProvider sp) {
+ PollSelectorImpl(SelectorProvider sp) throws IOException {
super(sp, 1, 1);
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);
--- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -25,15 +25,15 @@
package sun.nio.ch;
-import java.io.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
/**
* Allows different platforms to call different native methods
* for read and write operations.
*/
-class SocketDispatcher extends NativeDispatcher
-{
+class SocketDispatcher extends NativeDispatcher {
int read(FileDescriptor fd, long address, int len) throws IOException {
return FileDispatcherImpl.read0(fd, address, len);
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -260,7 +260,7 @@
private static Properties loadProperties() {
Properties result = new Properties();
String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
- Path file = Paths.get(fstypes);
+ Path file = Path.of(fstypes);
try {
try (ReadableByteChannel rbc = Files.newByteChannel(file)) {
result.load(Channels.newReader(rbc, "UTF-8"));
--- a/src/java.base/unix/native/libnio/ch/IOUtil.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.base/unix/native/libnio/ch/IOUtil.c Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -104,10 +104,19 @@
return ((jlong) fd[0] << 32) | (jlong) fd[1];
}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_IOUtil_write1(JNIEnv *env, jclass cl, jint fd, jbyte b)
+{
+ char c = (char)b;
+ return convertReturnVal(env, write(fd, &c, 1), JNI_FALSE);
+}
+
+
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd)
{
- char buf[128];
+ char buf[16];
int tn = 0;
for (;;) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2003, 2015, 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_LinuxOS_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
+
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.h Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003, 2007, 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_LINUXOS_ALSA_COMMONUTILS_H_INCLUDED
+#define PLATFORM_API_LINUXOS_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_LINUXOS_ALSA_COMMONUTILS_H_INCLUDED
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2003, 2010, 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_LinuxOS_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 linux
+ * 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 jre32onlinux64 = -1;
+ if (jre32onlinux64 < 0) {
+ jre32onlinux64 = 0;
+ /* The workaround may be disabled setting "JAVASOUND_ENABLE_MIDIIN"
+ * environment variable.
+ */
+ if (getenv("JAVASOUND_ENABLE_MIDIIN") == NULL) {
+ struct utsname u;
+ jre32onlinux64 = 0;
+ if (uname(&u) == 0) {
+ if (strstr(u.machine, "64") != NULL) {
+ TRACE0("jre32 on linux64 detected - report no midiIn devices\n");
+ jre32onlinux64 = 1;
+ }
+ }
+ }
+ }
+ if (jre32onlinux64) {
+ 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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2003, 2007, 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_LinuxOS_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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,481 @@
+/*
+ * 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_LinuxOS_ALSA_MidiUtils.h"
+#include "PLATFORM_API_LinuxOS_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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.h Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003, 2007, 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_LINUXOS_ALSA_MIDIUTILS_H_INCLUDED
+#define PLATFORM_API_LINUXOS_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_LINUXOS_ALSA_MIDIUTILS_H_INCLUDED
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,941 @@
+/*
+ * Copyright (c) 2002, 2011, 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_LinuxOS_ALSA_PCMUtils.h"
+#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
+#include "DirectAudio.h"
+
+#if USE_DAUDIO == TRUE
+
+// GetPosition method 1: based on how many bytes are passed to the kernel driver
+// + does not need much processor resources
+// - not very exact, "jumps"
+// GetPosition method 2: ask kernel about actual position of playback.
+// - very exact
+// - switch to kernel layer for each call
+// GetPosition method 3: use snd_pcm_avail() call - not yet in official ALSA
+// quick tests on a Pentium 200MMX showed max. 1.5% processor usage
+// for playing back a CD-quality file and printing 20x per second a line
+// on the console with the current time. So I guess performance is not such a
+// factor here.
+//#define GET_POSITION_METHOD1
+#define GET_POSITION_METHOD2
+
+
+// The default time for a period in microseconds.
+// For very small buffers, only 2 periods are used.
+#define DEFAULT_PERIOD_TIME 20000 /* 20ms */
+
+///// implemented functions of DirectAudio.h
+
+INT32 DAUDIO_GetDirectAudioDeviceCount() {
+ return (INT32) getAudioDeviceCount();
+}
+
+
+INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* description) {
+ ALSA_AudioDeviceDescription adesc;
+
+ adesc.index = (int) mixerIndex;
+ adesc.strLen = DAUDIO_STRING_LENGTH;
+
+ adesc.maxSimultaneousLines = (int*) (&(description->maxSimulLines));
+ adesc.deviceID = &(description->deviceID);
+ adesc.name = description->name;
+ adesc.vendor = description->vendor;
+ adesc.description = description->description;
+ adesc.version = description->version;
+
+ return getAudioDeviceDescriptionByIndex(&adesc);
+}
+
+#define MAX_BIT_INDEX 6
+// returns
+// 6: for anything above 24-bit
+// 5: for 4 bytes sample size, 24-bit
+// 4: for 3 bytes sample size, 24-bit
+// 3: for 3 bytes sample size, 20-bit
+// 2: for 2 bytes sample size, 16-bit
+// 1: for 1 byte sample size, 8-bit
+// 0: for anything else
+int getBitIndex(int sampleSizeInBytes, int significantBits) {
+ if (significantBits > 24) return 6;
+ if (sampleSizeInBytes == 4 && significantBits == 24) return 5;
+ if (sampleSizeInBytes == 3) {
+ if (significantBits == 24) return 4;
+ if (significantBits == 20) return 3;
+ }
+ if (sampleSizeInBytes == 2 && significantBits == 16) return 2;
+ if (sampleSizeInBytes == 1 && significantBits == 8) return 1;
+ return 0;
+}
+
+int getSampleSizeInBytes(int bitIndex, int sampleSizeInBytes) {
+ switch(bitIndex) {
+ case 1: return 1;
+ case 2: return 2;
+ case 3: /* fall through */
+ case 4: return 3;
+ case 5: return 4;
+ }
+ return sampleSizeInBytes;
+}
+
+int getSignificantBits(int bitIndex, int significantBits) {
+ switch(bitIndex) {
+ case 1: return 8;
+ case 2: return 16;
+ case 3: return 20;
+ case 4: /* fall through */
+ case 5: return 24;
+ }
+ return significantBits;
+}
+
+void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
+ snd_pcm_t* handle;
+ snd_pcm_format_mask_t* formatMask;
+ snd_pcm_format_t format;
+ snd_pcm_hw_params_t* hwParams;
+ int handledBits[MAX_BIT_INDEX+1];
+
+ int ret;
+ int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc;
+ int origSampleSizeInBytes, origSignificantBits;
+ unsigned int channels, minChannels, maxChannels;
+ int rate, bitIndex;
+
+ for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE;
+ if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) {
+ return;
+ }
+ ret = snd_pcm_format_mask_malloc(&formatMask);
+ if (ret != 0) {
+ ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret);
+ } else {
+ ret = snd_pcm_hw_params_malloc(&hwParams);
+ if (ret != 0) {
+ ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
+ } else {
+ ret = snd_pcm_hw_params_any(handle, hwParams);
+ /* snd_pcm_hw_params_any can return a positive value on success too */
+ if (ret < 0) {
+ ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
+ } else {
+ /* for the logic following this code, set ret to 0 to indicate success */
+ ret = 0;
+ }
+ }
+ snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
+ if (ret == 0) {
+ ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels);
+ if (ret != 0) {
+ ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret);
+ }
+ }
+ if (ret == 0) {
+ ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels);
+ if (ret != 0) {
+ ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret);
+ }
+ }
+
+ // since we queried the hw: device, for many soundcards, it will only
+ // report the maximum number of channels (which is the only way to talk
+ // to the hw: device). Since we will, however, open the plughw: device
+ // when opening the Source/TargetDataLine, we can safely assume that
+ // also the channels 1..maxChannels are available.
+#ifdef ALSA_PCM_USE_PLUGHW
+ minChannels = 1;
+#endif
+ if (ret == 0) {
+ // plughw: supports any sample rate
+ rate = -1;
+ for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
+ if (snd_pcm_format_mask_test(formatMask, format)) {
+ // format exists
+ if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes,
+ &origSignificantBits,
+ &isSigned, &isBigEndian, &enc)) {
+ // now if we use plughw:, we can use any bit size below the
+ // natively supported ones. Some ALSA drivers only support the maximum
+ // bit size, so we add any sample rates below the reported one.
+ // E.g. this iteration reports support for 16-bit.
+ // getBitIndex will return 2, so it will add entries for
+ // 16-bit (bitIndex=2) and in the next do-while loop iteration,
+ // it will decrease bitIndex and will therefore add 8-bit support.
+ bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits);
+ do {
+ if (bitIndex == 0
+ || bitIndex == MAX_BIT_INDEX
+ || !handledBits[bitIndex]) {
+ handledBits[bitIndex] = TRUE;
+ sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes);
+ significantBits = getSignificantBits(bitIndex, origSignificantBits);
+ if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) {
+ // avoid too many channels explicitly listed
+ // just add -1, min, and max
+ DAUDIO_AddAudioFormat(creator, significantBits,
+ -1, -1, rate,
+ enc, isSigned, isBigEndian);
+ DAUDIO_AddAudioFormat(creator, significantBits,
+ sampleSizeInBytes * minChannels,
+ minChannels, rate,
+ enc, isSigned, isBigEndian);
+ DAUDIO_AddAudioFormat(creator, significantBits,
+ sampleSizeInBytes * maxChannels,
+ maxChannels, rate,
+ enc, isSigned, isBigEndian);
+ } else {
+ for (channels = minChannels; channels <= maxChannels; channels++) {
+ DAUDIO_AddAudioFormat(creator, significantBits,
+ sampleSizeInBytes * channels,
+ channels, rate,
+ enc, isSigned, isBigEndian);
+ }
+ }
+ }
+#ifndef ALSA_PCM_USE_PLUGHW
+ // without plugin, do not add fake formats
+ break;
+#endif
+ } while (--bitIndex > 0);
+ } else {
+ TRACE1("could not get format from alsa for format %d\n", format);
+ }
+ } else {
+ //TRACE1("Format %d not supported\n", format);
+ }
+ } // for loop
+ snd_pcm_hw_params_free(hwParams);
+ }
+ snd_pcm_format_mask_free(formatMask);
+ }
+ snd_pcm_close(handle);
+}
+
+/** Workaround for cr 7033899, 7030629:
+ * dmix plugin doesn't like flush (snd_pcm_drop) when the buffer is empty
+ * (just opened, underruned or already flushed).
+ * Sometimes it causes PCM falls to -EBADFD error,
+ * sometimes causes bufferSize change.
+ * To prevent unnecessary flushes AlsaPcmInfo::isRunning & isFlushed are used.
+ */
+/* ******* ALSA PCM INFO ******************** */
+typedef struct tag_AlsaPcmInfo {
+ snd_pcm_t* handle;
+ snd_pcm_hw_params_t* hwParams;
+ snd_pcm_sw_params_t* swParams;
+ int bufferSizeInBytes;
+ int frameSize; // storage size in Bytes
+ unsigned int periods;
+ snd_pcm_uframes_t periodSize;
+ short int isRunning; // see comment above
+ short int isFlushed; // see comment above
+#ifdef GET_POSITION_METHOD2
+ // to be used exclusively by getBytePosition!
+ snd_pcm_status_t* positionStatus;
+#endif
+} AlsaPcmInfo;
+
+
+int setStartThresholdNoCommit(AlsaPcmInfo* info, int useThreshold) {
+ int ret;
+ int threshold;
+
+ if (useThreshold) {
+ // start device whenever anything is written to the buffer
+ threshold = 1;
+ } else {
+ // never start the device automatically
+ threshold = 2000000000; /* near UINT_MAX */
+ }
+ ret = snd_pcm_sw_params_set_start_threshold(info->handle, info->swParams, threshold);
+ if (ret < 0) {
+ ERROR1("Unable to set start threshold mode: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int setStartThreshold(AlsaPcmInfo* info, int useThreshold) {
+ int ret = 0;
+
+ if (!setStartThresholdNoCommit(info, useThreshold)) {
+ ret = -1;
+ }
+ if (ret == 0) {
+ // commit it
+ ret = snd_pcm_sw_params(info->handle, info->swParams);
+ if (ret < 0) {
+ ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
+ }
+ }
+ return (ret == 0)?TRUE:FALSE;
+}
+
+
+// returns TRUE if successful
+int setHWParams(AlsaPcmInfo* info,
+ float sampleRate,
+ int channels,
+ int bufferSizeInFrames,
+ snd_pcm_format_t format) {
+ unsigned int rrate, periodTime, periods;
+ int ret, dir;
+ snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames;
+
+ /* choose all parameters */
+ ret = snd_pcm_hw_params_any(info->handle, info->hwParams);
+ if (ret < 0) {
+ ERROR1("Broken configuration: no configurations available: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ /* set the interleaved read/write format */
+ ret = snd_pcm_hw_params_set_access(info->handle, info->hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
+ if (ret < 0) {
+ ERROR1("SND_PCM_ACCESS_RW_INTERLEAVED access type not available: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ /* set the sample format */
+ ret = snd_pcm_hw_params_set_format(info->handle, info->hwParams, format);
+ if (ret < 0) {
+ ERROR1("Sample format not available: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ /* set the count of channels */
+ ret = snd_pcm_hw_params_set_channels(info->handle, info->hwParams, channels);
+ if (ret < 0) {
+ ERROR2("Channels count (%d) not available: %s\n", channels, snd_strerror(ret));
+ return FALSE;
+ }
+ /* set the stream rate */
+ rrate = (int) (sampleRate + 0.5f);
+ dir = 0;
+ ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir);
+ if (ret < 0) {
+ ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret));
+ return FALSE;
+ }
+ if ((rrate-sampleRate > 2) || (rrate-sampleRate < - 2)) {
+ ERROR2("Rate doesn't match (requested %2.2fHz, got %dHz)\n", sampleRate, rrate);
+ return FALSE;
+ }
+ /* set the buffer time */
+ ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames);
+ if (ret < 0) {
+ ERROR2("Unable to set buffer size to %d frames: %s\n",
+ (int) alsaBufferSizeInFrames, snd_strerror(ret));
+ return FALSE;
+ }
+ bufferSizeInFrames = (int) alsaBufferSizeInFrames;
+ /* set the period time */
+ if (bufferSizeInFrames > 1024) {
+ dir = 0;
+ periodTime = DEFAULT_PERIOD_TIME;
+ ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir);
+ if (ret < 0) {
+ ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret));
+ return FALSE;
+ }
+ } else {
+ /* set the period count for very small buffer sizes to 2 */
+ dir = 0;
+ periods = 2;
+ ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir);
+ if (ret < 0) {
+ ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret));
+ return FALSE;
+ }
+ }
+ /* write the parameters to device */
+ ret = snd_pcm_hw_params(info->handle, info->hwParams);
+ if (ret < 0) {
+ ERROR1("Unable to set hw params: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// returns 1 if successful
+int setSWParams(AlsaPcmInfo* info) {
+ int ret;
+
+ /* get the current swparams */
+ ret = snd_pcm_sw_params_current(info->handle, info->swParams);
+ if (ret < 0) {
+ ERROR1("Unable to determine current swparams: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ /* never start the transfer automatically */
+ if (!setStartThresholdNoCommit(info, FALSE /* don't use threshold */)) {
+ return FALSE;
+ }
+
+ /* allow the transfer when at least period_size samples can be processed */
+ ret = snd_pcm_sw_params_set_avail_min(info->handle, info->swParams, info->periodSize);
+ if (ret < 0) {
+ ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ /* write the parameters to the playback device */
+ ret = snd_pcm_sw_params(info->handle, info->swParams);
+ if (ret < 0) {
+ ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static snd_output_t* ALSA_OUTPUT = NULL;
+
+void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
+ int encoding, float sampleRate, int sampleSizeInBits,
+ int frameSize, int channels,
+ int isSigned, int isBigEndian, int bufferSizeInBytes) {
+ snd_pcm_format_mask_t* formatMask;
+ snd_pcm_format_t format;
+ int dir;
+ int ret = 0;
+ AlsaPcmInfo* info = NULL;
+ /* snd_pcm_uframes_t is 64 bit on 64-bit systems */
+ snd_pcm_uframes_t alsaBufferSizeInFrames = 0;
+
+
+ TRACE0("> DAUDIO_Open\n");
+#ifdef USE_TRACE
+ // for using ALSA debug dump methods
+ if (ALSA_OUTPUT == NULL) {
+ snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
+ }
+#endif
+ if (channels <= 0) {
+ ERROR1("ERROR: Invalid number of channels=%d!\n", channels);
+ return NULL;
+ }
+ info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
+ if (!info) {
+ ERROR0("Out of memory\n");
+ return NULL;
+ }
+ memset(info, 0, sizeof(AlsaPcmInfo));
+ // initial values are: stopped, flushed
+ info->isRunning = 0;
+ info->isFlushed = 1;
+
+ ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
+ if (ret == 0) {
+ // set to blocking mode
+ snd_pcm_nonblock(info->handle, 0);
+ ret = snd_pcm_hw_params_malloc(&(info->hwParams));
+ if (ret != 0) {
+ ERROR1(" snd_pcm_hw_params_malloc returned error %d\n", ret);
+ } else {
+ ret = -1;
+ if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
+ isSigned, isBigEndian, encoding)) {
+ if (setHWParams(info,
+ sampleRate,
+ channels,
+ bufferSizeInBytes / frameSize,
+ format)) {
+ info->frameSize = frameSize;
+ ret = snd_pcm_hw_params_get_period_size(info->hwParams, &info->periodSize, &dir);
+ if (ret < 0) {
+ ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
+ }
+ snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
+ snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
+ info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
+ TRACE3(" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
+ (int) info->periodSize, info->periods, info->bufferSizeInBytes);
+ }
+ }
+ }
+ if (ret == 0) {
+ // set software parameters
+ ret = snd_pcm_sw_params_malloc(&(info->swParams));
+ if (ret != 0) {
+ ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
+ } else {
+ if (!setSWParams(info)) {
+ ret = -1;
+ }
+ }
+ }
+ if (ret == 0) {
+ // prepare device
+ ret = snd_pcm_prepare(info->handle);
+ if (ret < 0) {
+ ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
+ }
+ }
+
+#ifdef GET_POSITION_METHOD2
+ if (ret == 0) {
+ ret = snd_pcm_status_malloc(&(info->positionStatus));
+ if (ret != 0) {
+ ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
+ }
+ }
+#endif
+ }
+ if (ret != 0) {
+ DAUDIO_Close((void*) info, isSource);
+ info = NULL;
+ } else {
+ // set to non-blocking mode
+ snd_pcm_nonblock(info->handle, 1);
+ TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
+ (void*) info->handle);
+ }
+ return (void*) info;
+}
+
+#ifdef USE_TRACE
+void printState(snd_pcm_state_t state) {
+ if (state == SND_PCM_STATE_OPEN) {
+ TRACE0("State: SND_PCM_STATE_OPEN\n");
+ }
+ else if (state == SND_PCM_STATE_SETUP) {
+ TRACE0("State: SND_PCM_STATE_SETUP\n");
+ }
+ else if (state == SND_PCM_STATE_PREPARED) {
+ TRACE0("State: SND_PCM_STATE_PREPARED\n");
+ }
+ else if (state == SND_PCM_STATE_RUNNING) {
+ TRACE0("State: SND_PCM_STATE_RUNNING\n");
+ }
+ else if (state == SND_PCM_STATE_XRUN) {
+ TRACE0("State: SND_PCM_STATE_XRUN\n");
+ }
+ else if (state == SND_PCM_STATE_DRAINING) {
+ TRACE0("State: SND_PCM_STATE_DRAINING\n");
+ }
+ else if (state == SND_PCM_STATE_PAUSED) {
+ TRACE0("State: SND_PCM_STATE_PAUSED\n");
+ }
+ else if (state == SND_PCM_STATE_SUSPENDED) {
+ TRACE0("State: SND_PCM_STATE_SUSPENDED\n");
+ }
+}
+#endif
+
+int DAUDIO_Start(void* id, int isSource) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ int ret;
+ snd_pcm_state_t state;
+
+ TRACE0("> DAUDIO_Start\n");
+ // set to blocking mode
+ snd_pcm_nonblock(info->handle, 0);
+ // set start mode so that it always starts as soon as data is there
+ setStartThreshold(info, TRUE /* use threshold */);
+ state = snd_pcm_state(info->handle);
+ if (state == SND_PCM_STATE_PAUSED) {
+ // in case it was stopped previously
+ TRACE0(" Un-pausing...\n");
+ ret = snd_pcm_pause(info->handle, FALSE);
+ if (ret != 0) {
+ ERROR2(" NOTE: error in snd_pcm_pause:%d: %s\n", ret, snd_strerror(ret));
+ }
+ }
+ if (state == SND_PCM_STATE_SUSPENDED) {
+ TRACE0(" Resuming...\n");
+ ret = snd_pcm_resume(info->handle);
+ if (ret < 0) {
+ if ((ret != -EAGAIN) && (ret != -ENOSYS)) {
+ ERROR2(" ERROR: error in snd_pcm_resume:%d: %s\n", ret, snd_strerror(ret));
+ }
+ }
+ }
+ if (state == SND_PCM_STATE_SETUP) {
+ TRACE0("need to call prepare again...\n");
+ // prepare device
+ ret = snd_pcm_prepare(info->handle);
+ if (ret < 0) {
+ ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
+ }
+ }
+ // in case there is still data in the buffers
+ ret = snd_pcm_start(info->handle);
+ if (ret != 0) {
+ if (ret != -EPIPE) {
+ ERROR2(" NOTE: error in snd_pcm_start: %d: %s\n", ret, snd_strerror(ret));
+ }
+ }
+ // set to non-blocking mode
+ ret = snd_pcm_nonblock(info->handle, 1);
+ if (ret != 0) {
+ ERROR1(" ERROR in snd_pcm_nonblock: %s\n", snd_strerror(ret));
+ }
+ state = snd_pcm_state(info->handle);
+#ifdef USE_TRACE
+ printState(state);
+#endif
+ ret = (state == SND_PCM_STATE_PREPARED)
+ || (state == SND_PCM_STATE_RUNNING)
+ || (state == SND_PCM_STATE_XRUN)
+ || (state == SND_PCM_STATE_SUSPENDED);
+ if (ret) {
+ info->isRunning = 1;
+ // source line should keep isFlushed value until Write() is called;
+ // for target data line reset it right now.
+ if (!isSource) {
+ info->isFlushed = 0;
+ }
+ }
+ TRACE1("< DAUDIO_Start %s\n", ret?"success":"error");
+ return ret?TRUE:FALSE;
+}
+
+int DAUDIO_Stop(void* id, int isSource) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ int ret;
+
+ TRACE0("> DAUDIO_Stop\n");
+ // set to blocking mode
+ snd_pcm_nonblock(info->handle, 0);
+ setStartThreshold(info, FALSE /* don't use threshold */); // device will not start after buffer xrun
+ ret = snd_pcm_pause(info->handle, 1);
+ // set to non-blocking mode
+ snd_pcm_nonblock(info->handle, 1);
+ if (ret != 0) {
+ ERROR1("ERROR in snd_pcm_pause: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+ info->isRunning = 0;
+ TRACE0("< DAUDIO_Stop success\n");
+ return TRUE;
+}
+
+void DAUDIO_Close(void* id, int isSource) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+
+ TRACE0("DAUDIO_Close\n");
+ if (info != NULL) {
+ if (info->handle != NULL) {
+ snd_pcm_close(info->handle);
+ }
+ if (info->hwParams) {
+ snd_pcm_hw_params_free(info->hwParams);
+ }
+ if (info->swParams) {
+ snd_pcm_sw_params_free(info->swParams);
+ }
+#ifdef GET_POSITION_METHOD2
+ if (info->positionStatus) {
+ snd_pcm_status_free(info->positionStatus);
+ }
+#endif
+ free(info);
+ }
+}
+
+/*
+ * Underrun and suspend recovery
+ * returns
+ * 0: exit native and return 0
+ * 1: try again to write/read
+ * -1: error - exit native with return value -1
+ */
+int xrun_recovery(AlsaPcmInfo* info, int err) {
+ int ret;
+
+ if (err == -EPIPE) { /* underrun / overflow */
+ TRACE0("xrun_recovery: underrun/overflow.\n");
+ ret = snd_pcm_prepare(info->handle);
+ if (ret < 0) {
+ ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
+ return -1;
+ }
+ return 1;
+ } else if (err == -ESTRPIPE) {
+ TRACE0("xrun_recovery: suspended.\n");
+ ret = snd_pcm_resume(info->handle);
+ if (ret < 0) {
+ if (ret == -EAGAIN) {
+ return 0; /* wait until the suspend flag is released */
+ }
+ return -1;
+ }
+ ret = snd_pcm_prepare(info->handle);
+ if (ret < 0) {
+ ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
+ return -1;
+ }
+ return 1;
+ } else if (err == -EAGAIN) {
+ TRACE0("xrun_recovery: EAGAIN try again flag.\n");
+ return 0;
+ }
+
+ TRACE2("xrun_recovery: unexpected error %d: %s\n", err, snd_strerror(err));
+ return -1;
+}
+
+// returns -1 on error
+int DAUDIO_Write(void* id, char* data, int byteSize) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ int ret, count;
+ snd_pcm_sframes_t frameSize, writtenFrames;
+
+ TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
+
+ /* sanity */
+ if (byteSize <= 0 || info->frameSize <= 0) {
+ ERROR2(" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
+ (int) byteSize, (int) info->frameSize);
+ TRACE0("< DAUDIO_Write returning -1\n");
+ return -1;
+ }
+
+ count = 2; // maximum number of trials to recover from underrun
+ //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
+ frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
+ do {
+ writtenFrames = snd_pcm_writei(info->handle, (const void*) data, (snd_pcm_uframes_t) frameSize);
+
+ if (writtenFrames < 0) {
+ ret = xrun_recovery(info, (int) writtenFrames);
+ if (ret <= 0) {
+ TRACE1("DAUDIO_Write: xrun recovery returned %d -> return.\n", ret);
+ return ret;
+ }
+ if (count-- <= 0) {
+ ERROR0("DAUDIO_Write: too many attempts to recover from xrun/suspend\n");
+ return -1;
+ }
+ } else {
+ break;
+ }
+ } while (TRUE);
+ //ret = snd_pcm_frames_to_bytes(info->handle, writtenFrames);
+
+ if (writtenFrames > 0) {
+ // reset "flushed" flag
+ info->isFlushed = 0;
+ }
+
+ ret = (int) (writtenFrames * info->frameSize);
+ TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
+ return ret;
+}
+
+// returns -1 on error
+int DAUDIO_Read(void* id, char* data, int byteSize) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ int ret, count;
+ snd_pcm_sframes_t frameSize, readFrames;
+
+ TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
+ /*TRACE3(" info=%p, data=%p, byteSize=%d\n",
+ (void*) info, (void*) data, (int) byteSize);
+ TRACE2(" info->frameSize=%d, info->handle=%p\n",
+ (int) info->frameSize, (void*) info->handle);
+ */
+ /* sanity */
+ if (byteSize <= 0 || info->frameSize <= 0) {
+ ERROR2(" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
+ (int) byteSize, (int) info->frameSize);
+ TRACE0("< DAUDIO_Read returning -1\n");
+ return -1;
+ }
+ if (!info->isRunning && info->isFlushed) {
+ // PCM has nothing to read
+ return 0;
+ }
+
+ count = 2; // maximum number of trials to recover from error
+ //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
+ frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
+ do {
+ readFrames = snd_pcm_readi(info->handle, (void*) data, (snd_pcm_uframes_t) frameSize);
+ if (readFrames < 0) {
+ ret = xrun_recovery(info, (int) readFrames);
+ if (ret <= 0) {
+ TRACE1("DAUDIO_Read: xrun recovery returned %d -> return.\n", ret);
+ return ret;
+ }
+ if (count-- <= 0) {
+ ERROR0("DAUDIO_Read: too many attempts to recover from xrun/suspend\n");
+ return -1;
+ }
+ } else {
+ break;
+ }
+ } while (TRUE);
+ //ret = snd_pcm_frames_to_bytes(info->handle, readFrames);
+ ret = (int) (readFrames * info->frameSize);
+ TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
+ return ret;
+}
+
+
+int DAUDIO_GetBufferSize(void* id, int isSource) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+
+ return info->bufferSizeInBytes;
+}
+
+int DAUDIO_StillDraining(void* id, int isSource) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ snd_pcm_state_t state;
+
+ state = snd_pcm_state(info->handle);
+ //printState(state);
+ //TRACE1("Still draining: %s\n", (state != SND_PCM_STATE_XRUN)?"TRUE":"FALSE");
+ return (state == SND_PCM_STATE_RUNNING)?TRUE:FALSE;
+}
+
+
+int DAUDIO_Flush(void* id, int isSource) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ int ret;
+
+ TRACE0("DAUDIO_Flush\n");
+
+ if (info->isFlushed) {
+ // nothing to drop
+ return 1;
+ }
+
+ ret = snd_pcm_drop(info->handle);
+ if (ret != 0) {
+ ERROR1("ERROR in snd_pcm_drop: %s\n", snd_strerror(ret));
+ return FALSE;
+ }
+
+ info->isFlushed = 1;
+ if (info->isRunning) {
+ ret = DAUDIO_Start(id, isSource);
+ }
+ return ret;
+}
+
+int DAUDIO_GetAvailable(void* id, int isSource) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ snd_pcm_sframes_t availableInFrames;
+ snd_pcm_state_t state;
+ int ret;
+
+ state = snd_pcm_state(info->handle);
+ if (info->isFlushed || state == SND_PCM_STATE_XRUN) {
+ // if in xrun state then we have the entire buffer available,
+ // not 0 as alsa reports
+ ret = info->bufferSizeInBytes;
+ } else {
+ availableInFrames = snd_pcm_avail_update(info->handle);
+ if (availableInFrames < 0) {
+ ret = 0;
+ } else {
+ //ret = snd_pcm_frames_to_bytes(info->handle, availableInFrames);
+ ret = (int) (availableInFrames * info->frameSize);
+ }
+ }
+ TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
+ return ret;
+}
+
+INT64 estimatePositionFromAvail(AlsaPcmInfo* info, int isSource, INT64 javaBytePos, int availInBytes) {
+ // estimate the current position with the buffer size and
+ // the available bytes to read or write in the buffer.
+ // not an elegant solution - bytePos will stop on xruns,
+ // and in race conditions it may jump backwards
+ // Advantage is that it is indeed based on the samples that go through
+ // the system (rather than time-based methods)
+ if (isSource) {
+ // javaBytePos is the position that is reached when the current
+ // buffer is played completely
+ return (INT64) (javaBytePos - info->bufferSizeInBytes + availInBytes);
+ } else {
+ // javaBytePos is the position that was when the current buffer was empty
+ return (INT64) (javaBytePos + availInBytes);
+ }
+}
+
+INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
+ AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+ int ret;
+ INT64 result = javaBytePos;
+ snd_pcm_state_t state;
+ state = snd_pcm_state(info->handle);
+
+ if (!info->isFlushed && state != SND_PCM_STATE_XRUN) {
+#ifdef GET_POSITION_METHOD2
+ snd_timestamp_t* ts;
+ snd_pcm_uframes_t framesAvail;
+
+ // note: slight race condition if this is called simultaneously from 2 threads
+ ret = snd_pcm_status(info->handle, info->positionStatus);
+ if (ret != 0) {
+ ERROR1("ERROR in snd_pcm_status: %s\n", snd_strerror(ret));
+ result = javaBytePos;
+ } else {
+ // calculate from time value, or from available bytes
+ framesAvail = snd_pcm_status_get_avail(info->positionStatus);
+ result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
+ }
+#endif
+#ifdef GET_POSITION_METHOD3
+ snd_pcm_uframes_t framesAvail;
+ ret = snd_pcm_avail(info->handle, &framesAvail);
+ if (ret != 0) {
+ ERROR1("ERROR in snd_pcm_avail: %s\n", snd_strerror(ret));
+ result = javaBytePos;
+ } else {
+ result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
+ }
+#endif
+#ifdef GET_POSITION_METHOD1
+ result = estimatePositionFromAvail(info, isSource, javaBytePos, DAUDIO_GetAvailable(id, isSource));
+#endif
+ }
+ //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
+ return result;
+}
+
+
+
+void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
+ /* save to ignore, since GetBytePosition
+ * takes the javaBytePos param into account
+ */
+}
+
+int DAUDIO_RequiresServicing(void* id, int isSource) {
+ // never need servicing on Linux
+ return FALSE;
+}
+
+void DAUDIO_Service(void* id, int isSource) {
+ // never need servicing on Linux
+}
+
+
+#endif // USE_DAUDIO
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,292 @@
+/*
+ * 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_LinuxOS_ALSA_PCMUtils.h"
+#include "PLATFORM_API_LinuxOS_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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2003, 2010, 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_LINUXOS_ALSA_PCMUTILS_H_INCLUDED
+#define PLATFORM_API_LINUXOS_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_LINUXOS_ALSA_PCMUTILS_H_INCLUDED
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 2003, 2016, 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 "Ports.h"
+#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
+#include <alsa/asoundlib.h>
+
+#if USE_PORTS == TRUE
+
+#define MAX_ELEMS (300)
+#define MAX_CONTROLS (MAX_ELEMS * 4)
+
+#define CHANNELS_MONO (SND_MIXER_SCHN_LAST + 1)
+#define CHANNELS_STEREO (SND_MIXER_SCHN_LAST + 2)
+
+typedef struct {
+ snd_mixer_elem_t* elem;
+ INT32 portType; /* one of PORT_XXX_xx */
+ char* controlType; /* one of CONTROL_TYPE_xx */
+ /* Values: either SND_MIXER_SCHN_FRONT_xx, CHANNELS_MONO or CHANNELS_STEREO.
+ For SND_MIXER_SCHN_FRONT_xx, exactly this channel is set/retrieved directly.
+ For CHANNELS_MONO, ALSA channel SND_MIXER_SCHN_MONO is set/retrieved directly.
+ For CHANNELS_STEREO, ALSA channels SND_MIXER_SCHN_FRONT_LEFT and SND_MIXER_SCHN_FRONT_RIGHT
+ are set after a calculation that takes balance into account. Retrieved? Average of both
+ channels? (Using a cached value is not a good idea since the value in the HW may have been
+ altered.) */
+ INT32 channel;
+} PortControl;
+
+
+typedef struct tag_PortMixer {
+ snd_mixer_t* mixer_handle;
+ /* Number of array elements used in elems and types. */
+ int numElems;
+ snd_mixer_elem_t** elems;
+ /* Array of port types (PORT_SRC_UNKNOWN etc.). Indices are the same as in elems. */
+ INT32* types;
+ /* Number of array elements used in controls. */
+ int numControls;
+ PortControl* controls;
+} PortMixer;
+
+
+///// implemented functions of Ports.h
+
+INT32 PORT_GetPortMixerCount() {
+ INT32 mixerCount;
+ int card;
+ char devname[16];
+ int err;
+ snd_ctl_t *handle;
+ snd_ctl_card_info_t* info;
+
+ TRACE0("> PORT_GetPortMixerCount\n");
+
+ initAlsaSupport();
+
+ snd_ctl_card_info_malloc(&info);
+ card = -1;
+ mixerCount = 0;
+ if (snd_card_next(&card) >= 0) {
+ while (card >= 0) {
+ sprintf(devname, ALSA_HARDWARE_CARD, card);
+ TRACE1("PORT_GetPortMixerCount: Opening alsa device \"%s\"...\n", devname);
+ err = snd_ctl_open(&handle, devname, 0);
+ if (err < 0) {
+ ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
+ } else {
+ mixerCount++;
+ snd_ctl_close(handle);
+ }
+ if (snd_card_next(&card) < 0) {
+ break;
+ }
+ }
+ }
+ snd_ctl_card_info_free(info);
+ TRACE0("< PORT_GetPortMixerCount\n");
+ return mixerCount;
+}
+
+
+INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
+ snd_ctl_t* handle;
+ snd_ctl_card_info_t* card_info;
+ char devname[16];
+ int err;
+ char buffer[100];
+
+ TRACE0("> PORT_GetPortMixerDescription\n");
+ snd_ctl_card_info_malloc(&card_info);
+
+ sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
+ TRACE1("Opening alsa device \"%s\"...\n", devname);
+ err = snd_ctl_open(&handle, devname, 0);
+ if (err < 0) {
+ ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
+ return FALSE;
+ }
+ err = snd_ctl_card_info(handle, card_info);
+ if (err < 0) {
+ ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
+ }
+ strncpy(description->name, snd_ctl_card_info_get_id(card_info), PORT_STRING_LENGTH - 1);
+ sprintf(buffer, " [%s]", devname);
+ strncat(description->name, buffer, PORT_STRING_LENGTH - 1 - strlen(description->name));
+ strncpy(description->vendor, "ALSA (http://www.alsa-project.org)", PORT_STRING_LENGTH - 1);
+ strncpy(description->description, snd_ctl_card_info_get_name(card_info), PORT_STRING_LENGTH - 1);
+ strncat(description->description, ", ", PORT_STRING_LENGTH - 1 - strlen(description->description));
+ strncat(description->description, snd_ctl_card_info_get_mixername(card_info), PORT_STRING_LENGTH - 1 - strlen(description->description));
+ getALSAVersion(description->version, PORT_STRING_LENGTH - 1);
+
+ snd_ctl_close(handle);
+ snd_ctl_card_info_free(card_info);
+ TRACE0("< PORT_GetPortMixerDescription\n");
+ return TRUE;
+}
+
+
+void* PORT_Open(INT32 mixerIndex) {
+ char devname[16];
+ snd_mixer_t* mixer_handle;
+ int err;
+ PortMixer* handle;
+
+ TRACE0("> PORT_Open\n");
+ sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
+ if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
+ ERROR2("Mixer %s open error: %s", devname, snd_strerror(err));
+ return NULL;
+ }
+ if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) {
+ ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err));
+ snd_mixer_close(mixer_handle);
+ return NULL;
+ }
+ if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) {
+ ERROR1("Mixer register error: %s", snd_strerror(err));
+ snd_mixer_close(mixer_handle);
+ return NULL;
+ }
+ err = snd_mixer_load(mixer_handle);
+ if (err < 0) {
+ ERROR2("Mixer %s load error: %s", devname, snd_strerror(err));
+ snd_mixer_close(mixer_handle);
+ return NULL;
+ }
+ handle = (PortMixer*) calloc(1, sizeof(PortMixer));
+ if (handle == NULL) {
+ ERROR0("malloc() failed.");
+ snd_mixer_close(mixer_handle);
+ return NULL;
+ }
+ handle->numElems = 0;
+ handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*));
+ if (handle->elems == NULL) {
+ ERROR0("malloc() failed.");
+ snd_mixer_close(mixer_handle);
+ free(handle);
+ return NULL;
+ }
+ handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32));
+ if (handle->types == NULL) {
+ ERROR0("malloc() failed.");
+ snd_mixer_close(mixer_handle);
+ free(handle->elems);
+ free(handle);
+ return NULL;
+ }
+ handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl));
+ if (handle->controls == NULL) {
+ ERROR0("malloc() failed.");
+ snd_mixer_close(mixer_handle);
+ free(handle->elems);
+ free(handle->types);
+ free(handle);
+ return NULL;
+ }
+ handle->mixer_handle = mixer_handle;
+ // necessary to initialize data structures
+ PORT_GetPortCount(handle);
+ TRACE0("< PORT_Open\n");
+ return handle;
+}
+
+
+void PORT_Close(void* id) {
+ TRACE0("> PORT_Close\n");
+ if (id != NULL) {
+ PortMixer* handle = (PortMixer*) id;
+ if (handle->mixer_handle != NULL) {
+ snd_mixer_close(handle->mixer_handle);
+ }
+ if (handle->elems != NULL) {
+ free(handle->elems);
+ }
+ if (handle->types != NULL) {
+ free(handle->types);
+ }
+ if (handle->controls != NULL) {
+ free(handle->controls);
+ }
+ free(handle);
+ }
+ TRACE0("< PORT_Close\n");
+}
+
+
+
+INT32 PORT_GetPortCount(void* id) {
+ PortMixer* portMixer;
+ snd_mixer_elem_t *elem;
+
+ TRACE0("> PORT_GetPortCount\n");
+ if (id == NULL) {
+ // $$mp: Should become a descriptive error code (invalid handle).
+ return -1;
+ }
+ portMixer = (PortMixer*) id;
+ if (portMixer->numElems == 0) {
+ for (elem = snd_mixer_first_elem(portMixer->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
+ if (!snd_mixer_selem_is_active(elem))
+ continue;
+ TRACE2("Simple mixer control '%s',%i\n",
+ snd_mixer_selem_get_name(elem),
+ snd_mixer_selem_get_index(elem));
+ if (snd_mixer_selem_has_playback_volume(elem)) {
+ portMixer->elems[portMixer->numElems] = elem;
+ portMixer->types[portMixer->numElems] = PORT_DST_UNKNOWN;
+ portMixer->numElems++;
+ }
+ // to prevent buffer overflow
+ if (portMixer->numElems >= MAX_ELEMS) {
+ break;
+ }
+ /* If an element has both playback an capture volume, it is put into the arrays
+ twice. */
+ if (snd_mixer_selem_has_capture_volume(elem)) {
+ portMixer->elems[portMixer->numElems] = elem;
+ portMixer->types[portMixer->numElems] = PORT_SRC_UNKNOWN;
+ portMixer->numElems++;
+ }
+ // to prevent buffer overflow
+ if (portMixer->numElems >= MAX_ELEMS) {
+ break;
+ }
+ }
+ }
+ TRACE0("< PORT_GetPortCount\n");
+ return portMixer->numElems;
+}
+
+
+INT32 PORT_GetPortType(void* id, INT32 portIndex) {
+ PortMixer* portMixer;
+ INT32 type;
+ TRACE0("> PORT_GetPortType\n");
+ if (id == NULL) {
+ // $$mp: Should become a descriptive error code (invalid handle).
+ return -1;
+ }
+ portMixer = (PortMixer*) id;
+ if (portIndex < 0 || portIndex >= portMixer->numElems) {
+ // $$mp: Should become a descriptive error code (index out of bounds).
+ return -1;
+ }
+ type = portMixer->types[portIndex];
+ TRACE0("< PORT_GetPortType\n");
+ return type;
+}
+
+
+INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
+ PortMixer* portMixer;
+ const char* nam;
+
+ TRACE0("> PORT_GetPortName\n");
+ if (id == NULL) {
+ // $$mp: Should become a descriptive error code (invalid handle).
+ return -1;
+ }
+ portMixer = (PortMixer*) id;
+ if (portIndex < 0 || portIndex >= portMixer->numElems) {
+ // $$mp: Should become a descriptive error code (index out of bounds).
+ return -1;
+ }
+ nam = snd_mixer_selem_get_name(portMixer->elems[portIndex]);
+ strncpy(name, nam, len - 1);
+ name[len - 1] = 0;
+ TRACE0("< PORT_GetPortName\n");
+ return TRUE;
+}
+
+
+static int isPlaybackFunction(INT32 portType) {
+ return (portType & PORT_DST_MASK);
+}
+
+
+/* Sets portControl to a pointer to the next free array element in the PortControl (pointer)
+ array of the passed portMixer. Returns TRUE if successful. May return FALSE if there is no
+ free slot. In this case, portControl is not altered */
+static int getControlSlot(PortMixer* portMixer, PortControl** portControl) {
+ if (portMixer->numControls >= MAX_CONTROLS) {
+ return FALSE;
+ } else {
+ *portControl = &(portMixer->controls[portMixer->numControls]);
+ portMixer->numControls++;
+ return TRUE;
+ }
+}
+
+
+/* Protect against illegal min-max values, preventing divisions by zero.
+ */
+inline static long getRange(long min, long max) {
+ if (max > min) {
+ return max - min;
+ } else {
+ return 1;
+ }
+}
+
+
+/* Idea: we may specify that if unit is an empty string, the values are linear and if unit is "dB",
+ the values are logarithmic.
+*/
+static void* createVolumeControl(PortControlCreator* creator,
+ PortControl* portControl,
+ snd_mixer_elem_t* elem, int isPlayback) {
+ void* control;
+ float precision;
+ long min, max;
+
+ if (isPlayback) {
+ snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
+ } else {
+ snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
+ }
+ /* $$mp: The volume values retrieved with the ALSA API are strongly supposed to be logarithmic.
+ So the following calculation is wrong. However, there is no correct calculation, since
+ for equal-distant logarithmic steps, the precision expressed in linear varies over the
+ scale. */
+ precision = 1.0F / getRange(min, max);
+ control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_VOLUME, 0.0F, +1.0F, precision, "");
+ return control;
+}
+
+
+void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
+ PortMixer* portMixer;
+ snd_mixer_elem_t* elem;
+ void* control;
+ PortControl* portControl;
+ void* controls[10];
+ int numControls;
+ char* portName;
+ int isPlayback = 0;
+ int isMono;
+ int isStereo;
+ char* type;
+ snd_mixer_selem_channel_id_t channel;
+ memset(controls, 0, sizeof(controls));
+
+ TRACE0("> PORT_GetControls\n");
+ if (id == NULL) {
+ ERROR0("Invalid handle!");
+ // $$mp: an error code should be returned.
+ return;
+ }
+ portMixer = (PortMixer*) id;
+ if (portIndex < 0 || portIndex >= portMixer->numElems) {
+ ERROR0("Port index out of range!");
+ // $$mp: an error code should be returned.
+ return;
+ }
+ numControls = 0;
+ elem = portMixer->elems[portIndex];
+ if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) {
+ /* Since we've split/duplicated elements with both playback and capture on the recovery
+ of elements, we now can assume that we handle only to deal with either playback or
+ capture. */
+ isPlayback = isPlaybackFunction(portMixer->types[portIndex]);
+ isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) ||
+ (!isPlayback && snd_mixer_selem_is_capture_mono(elem));
+ isStereo = (isPlayback &&
+ snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
+ snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) ||
+ (!isPlayback &&
+ snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
+ snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT));
+ // single volume control
+ if (isMono || isStereo) {
+ if (getControlSlot(portMixer, &portControl)) {
+ portControl->elem = elem;
+ portControl->portType = portMixer->types[portIndex];
+ portControl->controlType = CONTROL_TYPE_VOLUME;
+ if (isMono) {
+ portControl->channel = CHANNELS_MONO;
+ } else {
+ portControl->channel = CHANNELS_STEREO;
+ }
+ control = createVolumeControl(creator, portControl, elem, isPlayback);
+ if (control != NULL) {
+ controls[numControls++] = control;
+ }
+ }
+ } else { // more than two channels, each channels has its own control.
+ for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) {
+ if ((isPlayback && snd_mixer_selem_has_playback_channel(elem, channel)) ||
+ (!isPlayback && snd_mixer_selem_has_capture_channel(elem, channel))) {
+ if (getControlSlot(portMixer, &portControl)) {
+ portControl->elem = elem;
+ portControl->portType = portMixer->types[portIndex];
+ portControl->controlType = CONTROL_TYPE_VOLUME;
+ portControl->channel = channel;
+ control = createVolumeControl(creator, portControl, elem, isPlayback);
+ // We wrap in a compound control to provide the channel name.
+ if (control != NULL) {
+ /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
+ declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
+ to take a const char* parameter. */
+ control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1);
+ }
+ if (control != NULL) {
+ controls[numControls++] = control;
+ }
+ }
+ }
+ }
+ }
+ // BALANCE control
+ if (isStereo) {
+ if (getControlSlot(portMixer, &portControl)) {
+ portControl->elem = elem;
+ portControl->portType = portMixer->types[portIndex];
+ portControl->controlType = CONTROL_TYPE_BALANCE;
+ portControl->channel = CHANNELS_STEREO;
+ /* $$mp: The value for precision is chosen more or less arbitrarily. */
+ control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, "");
+ if (control != NULL) {
+ controls[numControls++] = control;
+ }
+ }
+ }
+ }
+ if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) {
+ if (getControlSlot(portMixer, &portControl)) {
+ type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT;
+ portControl->elem = elem;
+ portControl->portType = portMixer->types[portIndex];
+ portControl->controlType = type;
+ control = (creator->newBooleanControl)(creator, portControl, type);
+ if (control != NULL) {
+ controls[numControls++] = control;
+ }
+ }
+ }
+ /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
+ declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
+ to take a const char* parameter. */
+ portName = (char*) snd_mixer_selem_get_name(elem);
+ control = (creator->newCompoundControl)(creator, portName, controls, numControls);
+ if (control != NULL) {
+ (creator->addControl)(creator, control);
+ }
+ TRACE0("< PORT_GetControls\n");
+}
+
+
+INT32 PORT_GetIntValue(void* controlIDV) {
+ PortControl* portControl = (PortControl*) controlIDV;
+ int value = 0;
+ snd_mixer_selem_channel_id_t channel;
+
+ if (portControl != NULL) {
+ switch (portControl->channel) {
+ case CHANNELS_MONO:
+ channel = SND_MIXER_SCHN_MONO;
+ break;
+
+ case CHANNELS_STEREO:
+ channel = SND_MIXER_SCHN_FRONT_LEFT;
+ break;
+
+ default:
+ channel = portControl->channel;
+ }
+ if (portControl->controlType == CONTROL_TYPE_MUTE ||
+ portControl->controlType == CONTROL_TYPE_SELECT) {
+ if (isPlaybackFunction(portControl->portType)) {
+ snd_mixer_selem_get_playback_switch(portControl->elem, channel, &value);
+ } else {
+ snd_mixer_selem_get_capture_switch(portControl->elem, channel, &value);
+ }
+ if (portControl->controlType == CONTROL_TYPE_MUTE) {
+ value = ! value;
+ }
+ } else {
+ ERROR1("PORT_GetIntValue(): inappropriate control type: %s\n",
+ portControl->controlType);
+ }
+ }
+ return (INT32) value;
+}
+
+
+void PORT_SetIntValue(void* controlIDV, INT32 value) {
+ PortControl* portControl = (PortControl*) controlIDV;
+ snd_mixer_selem_channel_id_t channel;
+
+ if (portControl != NULL) {
+ if (portControl->controlType == CONTROL_TYPE_MUTE) {
+ value = ! value;
+ }
+ if (portControl->controlType == CONTROL_TYPE_MUTE ||
+ portControl->controlType == CONTROL_TYPE_SELECT) {
+ if (isPlaybackFunction(portControl->portType)) {
+ snd_mixer_selem_set_playback_switch_all(portControl->elem, value);
+ } else {
+ snd_mixer_selem_set_capture_switch_all(portControl->elem, value);
+ }
+ } else {
+ ERROR1("PORT_SetIntValue(): inappropriate control type: %s\n",
+ portControl->controlType);
+ }
+ }
+}
+
+
+static float scaleVolumeValueToNormalized(long value, long min, long max) {
+ return (float) (value - min) / getRange(min, max);
+}
+
+
+static long scaleVolumeValueToHardware(float value, long min, long max) {
+ return (long)(value * getRange(min, max) + min);
+}
+
+
+float getRealVolume(PortControl* portControl,
+ snd_mixer_selem_channel_id_t channel) {
+ float fValue;
+ long lValue = 0;
+ long min = 0;
+ long max = 0;
+
+ if (isPlaybackFunction(portControl->portType)) {
+ snd_mixer_selem_get_playback_volume_range(portControl->elem,
+ &min, &max);
+ snd_mixer_selem_get_playback_volume(portControl->elem,
+ channel, &lValue);
+ } else {
+ snd_mixer_selem_get_capture_volume_range(portControl->elem,
+ &min, &max);
+ snd_mixer_selem_get_capture_volume(portControl->elem,
+ channel, &lValue);
+ }
+ fValue = scaleVolumeValueToNormalized(lValue, min, max);
+ return fValue;
+}
+
+
+void setRealVolume(PortControl* portControl,
+ snd_mixer_selem_channel_id_t channel, float value) {
+ long lValue = 0;
+ long min = 0;
+ long max = 0;
+
+ if (isPlaybackFunction(portControl->portType)) {
+ snd_mixer_selem_get_playback_volume_range(portControl->elem,
+ &min, &max);
+ lValue = scaleVolumeValueToHardware(value, min, max);
+ snd_mixer_selem_set_playback_volume(portControl->elem,
+ channel, lValue);
+ } else {
+ snd_mixer_selem_get_capture_volume_range(portControl->elem,
+ &min, &max);
+ lValue = scaleVolumeValueToHardware(value, min, max);
+ snd_mixer_selem_set_capture_volume(portControl->elem,
+ channel, lValue);
+ }
+}
+
+
+static float getFakeBalance(PortControl* portControl) {
+ float volL, volR;
+
+ // pan is the ratio of left and right
+ volL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
+ volR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
+ if (volL > volR) {
+ return -1.0f + (volR / volL);
+ }
+ else if (volR > volL) {
+ return 1.0f - (volL / volR);
+ }
+ return 0.0f;
+}
+
+
+static float getFakeVolume(PortControl* portControl) {
+ float valueL;
+ float valueR;
+ float value;
+
+ valueL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
+ valueR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
+ // volume is the greater value of both
+ value = valueL > valueR ? valueL : valueR ;
+ return value;
+}
+
+
+/*
+ * sets the unsigned values for left and right volume according to
+ * the given volume (0...1) and balance (-1..0..+1)
+ */
+static void setFakeVolume(PortControl* portControl, float vol, float bal) {
+ float volumeLeft;
+ float volumeRight;
+
+ if (bal < 0.0f) {
+ volumeLeft = vol;
+ volumeRight = vol * (bal + 1.0f);
+ } else {
+ volumeLeft = vol * (1.0f - bal);
+ volumeRight = vol;
+ }
+ setRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT, volumeLeft);
+ setRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT, volumeRight);
+}
+
+
+float PORT_GetFloatValue(void* controlIDV) {
+ PortControl* portControl = (PortControl*) controlIDV;
+ float value = 0.0F;
+
+ if (portControl != NULL) {
+ if (portControl->controlType == CONTROL_TYPE_VOLUME) {
+ switch (portControl->channel) {
+ case CHANNELS_MONO:
+ value = getRealVolume(portControl, SND_MIXER_SCHN_MONO);
+ break;
+
+ case CHANNELS_STEREO:
+ value = getFakeVolume(portControl);
+ break;
+
+ default:
+ value = getRealVolume(portControl, portControl->channel);
+ }
+ } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
+ if (portControl->channel == CHANNELS_STEREO) {
+ value = getFakeBalance(portControl);
+ } else {
+ ERROR0("PORT_GetFloatValue(): Balance only allowed for stereo channels!\n");
+ }
+ } else {
+ ERROR1("PORT_GetFloatValue(): inappropriate control type: %s!\n",
+ portControl->controlType);
+ }
+ }
+ return value;
+}
+
+
+void PORT_SetFloatValue(void* controlIDV, float value) {
+ PortControl* portControl = (PortControl*) controlIDV;
+
+ if (portControl != NULL) {
+ if (portControl->controlType == CONTROL_TYPE_VOLUME) {
+ switch (portControl->channel) {
+ case CHANNELS_MONO:
+ setRealVolume(portControl, SND_MIXER_SCHN_MONO, value);
+ break;
+
+ case CHANNELS_STEREO:
+ setFakeVolume(portControl, value, getFakeBalance(portControl));
+ break;
+
+ default:
+ setRealVolume(portControl, portControl->channel, value);
+ }
+ } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
+ if (portControl->channel == CHANNELS_STEREO) {
+ setFakeVolume(portControl, getFakeVolume(portControl), value);
+ } else {
+ ERROR0("PORT_SetFloatValue(): Balance only allowed for stereo channels!\n");
+ }
+ } else {
+ ERROR1("PORT_SetFloatValue(): inappropriate control type: %s!\n",
+ portControl->controlType);
+ }
+ }
+}
+
+
+#endif // USE_PORTS
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri Mar 23 18:44:47 2018 +0000
@@ -859,7 +859,7 @@
@Override
public void updateFocusableWindowState() {
final boolean isFocusable = isNativelyFocusableWindow();
- setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once
+ setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN | RESIZABLE, isFocusable); // set bits at once
}
@Override
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPConstants.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPConstants.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -30,6 +30,7 @@
static final String VERSION_2 = "BMP v. 2.x";
static final String VERSION_3 = "BMP v. 3.x";
static final String VERSION_3_NT = "BMP v. 3.x NT";
+ static final String VERSION_3_EXT = "BMP V2/V3 INFO";
static final String VERSION_4 = "BMP v. 4.x";
static final String VERSION_5 = "BMP v. 5.x";
@@ -48,3 +49,4 @@
static final int BI_JPEG = 4;
static final int BI_PNG = 5;
}
+
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -78,6 +78,8 @@
*
* This class supports Microsoft Windows Bitmap Version 3-5,
* as well as OS/2 Bitmap Version 2.x (for single-image BMP file).
+ * It also supports undocumented DIB header of type BITMAPV2INFOHEADER
+ * & BITMAPV3INFOHEADER.
*/
public class BMPImageReader extends ImageReader implements BMPConstants {
// BMP Image types
@@ -94,16 +96,25 @@
private static final int VERSION_3_NT_16_BIT = 8;
private static final int VERSION_3_NT_32_BIT = 9;
- private static final int VERSION_4_1_BIT = 10;
- private static final int VERSION_4_4_BIT = 11;
- private static final int VERSION_4_8_BIT = 12;
- private static final int VERSION_4_16_BIT = 13;
- private static final int VERSION_4_24_BIT = 14;
- private static final int VERSION_4_32_BIT = 15;
+ // All VERSION_3_EXT_* are for BITMAPV2INFOHEADER & BITMAPV3INFOHEADER
+ private static final int VERSION_3_EXT_1_BIT = 10;
+ private static final int VERSION_3_EXT_4_BIT = 11;
+ private static final int VERSION_3_EXT_8_BIT = 12;
+ private static final int VERSION_3_EXT_16_BIT = 13;
+ private static final int VERSION_3_EXT_24_BIT = 14;
+ private static final int VERSION_3_EXT_32_BIT = 15;
- private static final int VERSION_3_XP_EMBEDDED = 16;
- private static final int VERSION_4_XP_EMBEDDED = 17;
- private static final int VERSION_5_XP_EMBEDDED = 18;
+ private static final int VERSION_4_1_BIT = 16;
+ private static final int VERSION_4_4_BIT = 17;
+ private static final int VERSION_4_8_BIT = 18;
+ private static final int VERSION_4_16_BIT = 19;
+ private static final int VERSION_4_24_BIT = 20;
+ private static final int VERSION_4_32_BIT = 21;
+
+ private static final int VERSION_3_XP_EMBEDDED = 22;
+ private static final int VERSION_3_EXT_EMBEDDED = 23;
+ private static final int VERSION_4_XP_EMBEDDED = 24;
+ private static final int VERSION_5_XP_EMBEDDED = 25;
// BMP variables
private long bitmapFileSize;
@@ -409,6 +420,63 @@
throw new
IIOException(I18N.getString("BMPImageReader2"));
}
+ } else if (size == 52 || size == 56) {
+ // BITMAPV2INFOHEADER or BITMAPV3INFOHEADER
+ redMask = (int)iis.readUnsignedInt();
+ greenMask = (int)iis.readUnsignedInt();
+ blueMask = (int)iis.readUnsignedInt();
+ if (size == 56) {
+ alphaMask = (int)iis.readUnsignedInt();
+ }
+
+ metadata.bmpVersion = VERSION_3_EXT;
+ // Read in the palette
+ int numberOfEntries = (int)((bitmapOffset-14-size) / 4);
+ int sizeOfPalette = numberOfEntries*4;
+ palette = new byte[sizeOfPalette];
+ iis.readFully(palette, 0, sizeOfPalette);
+ metadata.palette = palette;
+ metadata.paletteSize = numberOfEntries;
+
+ switch((int)compression) {
+
+ case BI_JPEG:
+ case BI_PNG:
+ imageType = VERSION_3_EXT_EMBEDDED;
+ break;
+ default:
+ if (bitsPerPixel == 1) {
+ imageType = VERSION_3_EXT_1_BIT;
+ } else if (bitsPerPixel == 4) {
+ imageType = VERSION_3_EXT_4_BIT;
+ } else if (bitsPerPixel == 8) {
+ imageType = VERSION_3_EXT_8_BIT;
+ } else if (bitsPerPixel == 16) {
+ imageType = VERSION_3_EXT_16_BIT;
+ if ((int)compression == BI_RGB) {
+ redMask = 0x7C00;
+ greenMask = 0x3E0;
+ blueMask = 0x1F;
+ }
+ } else if (bitsPerPixel == 24) {
+ imageType = VERSION_3_EXT_24_BIT;
+ } else if (bitsPerPixel == 32) {
+ imageType = VERSION_3_EXT_32_BIT;
+ if ((int)compression == BI_RGB) {
+ redMask = 0x00FF0000;
+ greenMask = 0x0000FF00;
+ blueMask = 0x000000FF;
+ }
+ } else {
+ throw new
+ IIOException(I18N.getString("BMPImageReader8"));
+ }
+
+ metadata.redMask = redMask;
+ metadata.greenMask = greenMask;
+ metadata.blueMask = blueMask;
+ metadata.alphaMask = alphaMask;
+ }
} else if (size == 108 || size == 124) {
// Windows 4.x BMP
if (size == 108)
@@ -908,15 +976,18 @@
break;
case VERSION_3_XP_EMBEDDED:
+ case VERSION_3_EXT_EMBEDDED:
case VERSION_4_XP_EMBEDDED:
case VERSION_5_XP_EMBEDDED:
bi = readEmbedded((int)compression, bi, param);
break;
+ case VERSION_3_EXT_1_BIT:
case VERSION_4_1_BIT:
read1Bit(bdata);
break;
+ case VERSION_3_EXT_4_BIT:
case VERSION_4_4_BIT:
switch((int)compression) {
@@ -934,6 +1005,7 @@
}
break;
+ case VERSION_3_EXT_8_BIT:
case VERSION_4_8_BIT:
switch((int)compression) {
@@ -951,14 +1023,17 @@
}
break;
+ case VERSION_3_EXT_16_BIT:
case VERSION_4_16_BIT:
read16Bit(sdata);
break;
+ case VERSION_3_EXT_24_BIT:
case VERSION_4_24_BIT:
read24Bit(bdata);
break;
+ case VERSION_3_EXT_32_BIT:
case VERSION_4_32_BIT:
read32Bit(idata);
break;
@@ -2000,3 +2075,4 @@
}
}
}
+
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormat.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageMetadataFormat.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -119,10 +119,10 @@
"1", "65535", true, true);
addAttribute("PlainTextExtension", "characterCellWidth",
DATATYPE_INTEGER, true, null,
- "1", "65535", true, true);
+ "1", "255", true, true);
addAttribute("PlainTextExtension", "characterCellHeight",
DATATYPE_INTEGER, true, null,
- "1", "65535", true, true);
+ "1", "255", true, true);
addAttribute("PlainTextExtension", "textForegroundColor",
DATATYPE_INTEGER, true, null,
"0", "255", true, true);
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -203,15 +203,18 @@
-1, true,
true, 1, 65535);
+ // As per the specification (89a), character cell width
+ // and character cell height occupy one byte each
+ // in the Plain Text Extension block.
characterCellWidth = getIntAttribute(node,
"characterCellWidth",
-1, true,
- true, 1, 65535);
+ true, 1, 255);
characterCellHeight = getIntAttribute(node,
"characterCellHeight",
-1, true,
- true, 1, 65535);
+ true, 1, 255);
textForegroundColor = getIntAttribute(node,
"textForegroundColor",
--- a/src/java.desktop/share/classes/com/sun/media/sound/Platform.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/com/sun/media/sound/Platform.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * 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 @@
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";
-
- // 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;
+ private static final String libName = "jsound";
- // 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 @@
if(Printer.trace)Printer.trace(">> Platform.java: static");
loadLibraries();
- readProperties();
}
/**
@@ -95,72 +80,37 @@
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();
- }
}
--- a/src/java.desktop/share/classes/java/awt/SequencedEvent.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/java/awt/SequencedEvent.java Fri Mar 23 18:44:47 2018 +0000
@@ -135,11 +135,7 @@
if (Thread.currentThread() instanceof EventDispatchThread) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
- edt.pumpEvents(SentEvent.ID, new Conditional() {
- public boolean evaluate() {
- return !SequencedEvent.this.isFirstOrDisposed();
- }
- });
+ edt.pumpEvents(ID, () -> !SequencedEvent.this.isFirstOrDisposed());
} else {
if (fxAppThreadIsDispatchThread) {
fxCheckSequenceThread.start();
--- a/src/java.desktop/share/classes/javax/imageio/metadata/doc-files/gif_metadata.html Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/javax/imageio/metadata/doc-files/gif_metadata.html Fri Mar 23 18:44:47 2018 +0000
@@ -5,7 +5,7 @@
<title>GIF Metadata Format Specification</title>
</head>
<!--
-Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2000, 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
@@ -291,13 +291,13 @@
<!-- The width of a character cell -->
<!-- Data type: Integer -->
<!-- Min value: 1 (inclusive) -->
- <!-- Max value: 65535 (inclusive) -->
+ <!-- Max value: 255 (inclusive) -->
<!ATTLIST "PlainTextExtension" "characterCellHeight" #CDATA
#REQUIRED>
<!-- The height of a character cell -->
<!-- Data type: Integer -->
<!-- Min value: 1 (inclusive) -->
- <!-- Max value: 65535 (inclusive) -->
+ <!-- Max value: 255 (inclusive) -->
<!ATTLIST "PlainTextExtension" "textForegroundColor" #CDATA
#REQUIRED>
<!-- The text foreground color index -->
--- a/src/java.desktop/share/classes/javax/sound/midi/package-info.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/javax/sound/midi/package-info.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, 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
@@ -33,6 +33,12 @@
* <li><a href="https://docs.oracle.com/javase/tutorial/sound/">
* The Java Sound Tutorial</a>
* </ul>
+ * Please note: In the {@code javax.sound.midi} APIs, a {@code null} reference
+ * parameter to methods is incorrect unless explicitly documented on the method
+ * as having a meaningful interpretation. Usage to the contrary is incorrect
+ * coding and may result in a run time exception either immediately or at some
+ * later time. {@code NullPointerException} is an example of typical and
+ * acceptable run time exception for such cases.
*
* @since 1.3
*/
--- a/src/java.desktop/share/classes/javax/sound/midi/spi/package-info.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/javax/sound/midi/spi/package-info.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, 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
@@ -33,6 +33,12 @@
* <li><a href="https://docs.oracle.com/javase/tutorial/sound/">
* The Java Sound Tutorial</a>
* </ul>
+ * Please note: In the {@code javax.sound.midi.spi} APIs, a {@code null}
+ * reference parameter to methods is incorrect unless explicitly documented on
+ * the method as having a meaningful interpretation. Usage to the contrary is
+ * incorrect coding and may result in a run time exception either immediately or
+ * at some later time. {@code NullPointerException} is an example of typical and
+ * acceptable run time exception for such cases.
*
* @since 1.3
*/
--- a/src/java.desktop/share/classes/javax/sound/sampled/package-info.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/javax/sound/sampled/package-info.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, 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
@@ -33,6 +33,12 @@
* <li><a href="https://docs.oracle.com/javase/tutorial/sound/">
* The Java Sound Tutorial</a>
* </ul>
+ * Please note: In the {@code javax.sound.sampled} APIs, a {@code null}
+ * reference parameter to methods is incorrect unless explicitly documented on
+ * the method as having a meaningful interpretation. Usage to the contrary is
+ * incorrect coding and may result in a run time exception either immediately or
+ * at some later time. {@code NullPointerException} is an example of typical and
+ * acceptable run time exception for such cases.
*
* @since 1.3
*/
--- a/src/java.desktop/share/classes/javax/sound/sampled/spi/package-info.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/javax/sound/sampled/spi/package-info.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, 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
@@ -33,6 +33,12 @@
* <li><a href="https://docs.oracle.com/javase/tutorial/sound/">
* The Java Sound Tutorial</a>
* </ul>
+ * Please note: In the {@code javax.sound.sampled.spi} APIs, a {@code null}
+ * reference parameter to methods is incorrect unless explicitly documented on
+ * the method as having a meaningful interpretation. Usage to the contrary is
+ * incorrect coding and may result in a run time exception either immediately or
+ * at some later time. {@code NullPointerException} is an example of typical and
+ * acceptable run time exception for such cases.
*
* @since 1.3
*/
--- a/src/java.desktop/share/classes/javax/swing/JList.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/javax/swing/JList.java Fri Mar 23 18:44:47 2018 +0000
@@ -2269,10 +2269,12 @@
int iMin = sm.getMinSelectionIndex();
int iMax = sm.getMaxSelectionIndex();
-
- if ((iMin < 0) || (iMax < 0)) {
+ int size = dm.getSize();
+
+ if ((iMin < 0) || (iMax < 0) || (iMin >= size)) {
return new Object[0];
}
+ iMax = iMax < size ? iMax : size - 1;
Object[] rvTmp = new Object[1+ (iMax - iMin)];
int n = 0;
@@ -2304,10 +2306,12 @@
int iMin = sm.getMinSelectionIndex();
int iMax = sm.getMaxSelectionIndex();
-
- if ((iMin < 0) || (iMax < 0)) {
+ int size = dm.getSize();
+
+ if ((iMin < 0) || (iMax < 0) || (iMin >= size)) {
return Collections.emptyList();
}
+ iMax = iMax < size ? iMax : size - 1;
List<E> selectedItems = new ArrayList<E>();
for(int i = iMin; i <= iMax; i++) {
@@ -2353,7 +2357,8 @@
@BeanProperty(bound = false)
public E getSelectedValue() {
int i = getMinSelectionIndex();
- return (i == -1) ? null : getModel().getElementAt(i);
+ return ((i == -1) || (i >= getModel().getSize())) ? null :
+ getModel().getElementAt(i);
}
--- a/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java Fri Mar 23 18:44:47 2018 +0000
@@ -928,11 +928,11 @@
}
synchronized(ImageView.this) {
- if ((changed & 1) == 1 && (state & WIDTH_FLAG) == 0) {
- width = newWidth;
+ if ((changed & 1) == 1 && (state & HEIGHT_FLAG) == 0) {
+ height = newHeight;
}
- if ((changed & 2) == 2 && (state & HEIGHT_FLAG) == 0) {
- height = newHeight;
+ if ((changed & 2) == 2 && (state & WIDTH_FLAG) == 0) {
+ width = newWidth;
}
if ((state & LOADING_FLAG) == LOADING_FLAG) {
// No need to resize or repaint, still in the process of
--- a/src/java.desktop/share/classes/sun/font/FontScaler.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/sun/font/FontScaler.java Fri Mar 23 18:44:47 2018 +0000
@@ -96,12 +96,23 @@
try {
@SuppressWarnings("unchecked")
Class<? extends FontScaler> tmp = (Class<? extends FontScaler>)
- (!FontUtilities.useT2K ?
+ ((!FontUtilities.useT2K && !FontUtilities.useLegacy) ?
Class.forName("sun.font.FreetypeFontScaler") :
Class.forName("sun.font.T2KFontScaler"));
scalerClass = tmp;
} catch (ClassNotFoundException e) {
+ try {
+ @SuppressWarnings("unchecked")
+ Class<? extends FontScaler> tmp = (Class<? extends FontScaler>)
+ Class.forName("sun.font.FreetypeFontScaler");
+ scalerClass = tmp;
+ } catch (ClassNotFoundException e1) {
scalerClass = NullFontScaler.class;
+ }
+ } finally {
+ if (FontUtilities.debugFonts()) {
+ System.out.println("Scaler class="+scalerClass);
+ }
}
//NB: rewrite using factory? constructor is ugly way
--- a/src/java.desktop/share/classes/sun/font/FontUtilities.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/classes/sun/font/FontUtilities.java Fri Mar 23 18:44:47 2018 +0000
@@ -53,6 +53,8 @@
public static boolean useJDKScaler;
public static boolean useT2K;
+ // useLegacy is a short-term debugging transition aid.
+ public static boolean useLegacy;
public static boolean isWindows;
@@ -94,9 +96,17 @@
String scalerStr = System.getProperty("sun.java2d.font.scaler");
if (scalerStr != null) {
useT2K = "t2k".equals(scalerStr);
+ if (useT2K) {
+ System.out.println("WARNING: t2k will be removed in JDK 11.");
+ }
+ useLegacy = "legacy".equals(scalerStr);
+ if (useLegacy) {
+ System.out.println("WARNING: legacy behavior will be removed in JDK 11.");
+ }
useJDKScaler = useT2K || "jdk".equals(scalerStr);
} else {
useT2K = false;
+ useLegacy = false;
useJDKScaler = false;
}
isWindows = osName.startsWith("Windows");
--- a/src/java.desktop/share/legal/colorimaging.md Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/legal/colorimaging.md Fri Mar 23 18:44:47 2018 +0000
@@ -1,4 +1,4 @@
-## Eastman Kodak Company: Kodak Color Management System (kcms) and portions of color management and imaging software
+## Eastman Kodak Company: Portions of color management and imaging software
### Eastman Kodak Notice
<pre>
--- a/src/java.desktop/share/native/libfontmanager/sunFont.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/native/libfontmanager/sunFont.c Fri Mar 23 18:44:47 2018 +0000
@@ -219,7 +219,7 @@
* accelerated glyph cache cells as we do in freeInt/LongMemory().
*/
if (ptr != 0) {
- free((void*)ptr);
+ free((void*)((intptr_t)ptr));
}
}
@@ -257,13 +257,13 @@
if (ptrs) {
for (i=0; i< len; i++) {
if (ptrs[i] != 0) {
- GlyphInfo *ginfo = (GlyphInfo *)ptrs[i];
+ GlyphInfo *ginfo = (GlyphInfo *)((intptr_t)ptrs[i]);
if (ginfo->cellInfo != NULL &&
ginfo->managed == MANAGED_GLYPH) {
// invalidate this glyph's accelerated cache cell
AccelGlyphCache_RemoveAllCellInfos(ginfo);
}
- free((void*)ginfo);
+ free(ginfo);
}
}
(*env)->ReleasePrimitiveArrayCritical(env, jmemArray, ptrs, JNI_ABORT);
--- a/src/java.desktop/share/native/libjsound/Platform.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/share/native/libjsound/Platform.c Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * 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 @@
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;
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,626 @@
+/*
+ * Copyright (c) 2003, 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 USE_ERROR
+#define USE_TRACE
+
+#include "PLATFORM_API_SolarisOS_Utils.h"
+#include "DirectAudio.h"
+
+#if USE_DAUDIO == TRUE
+
+
+// The default buffer time
+#define DEFAULT_PERIOD_TIME_MILLIS 50
+
+///// implemented functions of DirectAudio.h
+
+INT32 DAUDIO_GetDirectAudioDeviceCount() {
+ return (INT32) getAudioDeviceCount();
+}
+
+
+INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex,
+ DirectAudioDeviceDescription* description) {
+ AudioDeviceDescription desc;
+
+ if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
+ description->maxSimulLines = desc.maxSimulLines;
+ strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1);
+ description->name[DAUDIO_STRING_LENGTH-1] = 0;
+ strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1);
+ description->vendor[DAUDIO_STRING_LENGTH-1] = 0;
+ strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1);
+ description->version[DAUDIO_STRING_LENGTH-1] = 0;
+ /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/
+ strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1);
+ description->description[DAUDIO_STRING_LENGTH-1] = 0;
+ return TRUE;
+ }
+ return FALSE;
+
+}
+
+#define MAX_SAMPLE_RATES 20
+
+void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
+ int fd = -1;
+ AudioDeviceDescription desc;
+ am_sample_rates_t *sr;
+ /* hardcoded bits and channels */
+ int bits[] = {8, 16};
+ int bitsCount = 2;
+ int channels[] = {1, 2};
+ int channelsCount = 2;
+ /* for querying sample rates */
+ int err;
+ int ch, b, s;
+
+ TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource);
+ if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
+ fd = open(desc.pathctl, O_RDONLY);
+ }
+ if (fd < 0) {
+ ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
+ return;
+ }
+
+ /* get sample rates */
+ sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES));
+ if (sr == NULL) {
+ ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex);
+ close(fd);
+ return;
+ }
+
+ sr->num_samp_rates = MAX_SAMPLE_RATES;
+ sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD;
+ sr->samp_rates[0] = -2;
+ err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
+ if (err < 0) {
+ ERROR1(" DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n",
+ (int)mixerIndex);
+ ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n",
+ (int) sr->num_samp_rates,
+ (int) sr->samp_rates[0]);
+ /* Some Solaris 8 drivers fail for get sample rates!
+ * Do as if we support all sample rates
+ */
+ sr->flags = MIXER_SR_LIMITS;
+ }
+ if ((sr->flags & MIXER_SR_LIMITS)
+ || (sr->num_samp_rates > MAX_SAMPLE_RATES)) {
+#ifdef USE_TRACE
+ if ((sr->flags & MIXER_SR_LIMITS)) {
+ TRACE1(" DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n",
+ (int)mixerIndex);
+ }
+ if (sr->num_samp_rates > MAX_SAMPLE_RATES) {
+ TRACE2(" DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n",
+ MAX_SAMPLE_RATES, (int)mixerIndex);
+ }
+#endif
+ /*
+ * Fake it to have only one sample rate: -1
+ */
+ sr->num_samp_rates = 1;
+ sr->samp_rates[0] = -1;
+ }
+ close(fd);
+
+ for (ch = 0; ch < channelsCount; ch++) {
+ for (b = 0; b < bitsCount; b++) {
+ for (s = 0; s < sr->num_samp_rates; s++) {
+ DAUDIO_AddAudioFormat(creator,
+ bits[b], /* significant bits */
+ 0, /* frameSize: let it be calculated */
+ channels[ch],
+ (float) ((int) sr->samp_rates[s]),
+ DAUDIO_PCM, /* encoding - let's only do PCM */
+ (bits[b] > 8)?TRUE:TRUE, /* isSigned */
+#ifdef _LITTLE_ENDIAN
+ FALSE /* little endian */
+#else
+ (bits[b] > 8)?TRUE:FALSE /* big endian */
+#endif
+ );
+ }
+ }
+ }
+ free(sr);
+}
+
+
+typedef struct {
+ int fd;
+ audio_info_t info;
+ int bufferSizeInBytes;
+ int frameSize; /* storage size in Bytes */
+ /* how many bytes were written or read */
+ INT32 transferedBytes;
+ /* if transferedBytes exceed 32-bit boundary,
+ * it will be reset and positionOffset will receive
+ * the offset
+ */
+ INT64 positionOffset;
+} SolPcmInfo;
+
+
+void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
+ int encoding, float sampleRate, int sampleSizeInBits,
+ int frameSize, int channels,
+ int isSigned, int isBigEndian, int bufferSizeInBytes) {
+ int err = 0;
+ int openMode;
+ AudioDeviceDescription desc;
+ SolPcmInfo* info;
+
+ TRACE0("> DAUDIO_Open\n");
+ if (encoding != DAUDIO_PCM) {
+ ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding);
+ return NULL;
+ }
+ if (channels <= 0) {
+ ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels);
+ return NULL;
+ }
+
+ info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo));
+ if (!info) {
+ ERROR0("Out of memory\n");
+ return NULL;
+ }
+ memset(info, 0, sizeof(SolPcmInfo));
+ info->frameSize = frameSize;
+ info->fd = -1;
+
+ if (isSource) {
+ openMode = O_WRONLY;
+ } else {
+ openMode = O_RDONLY;
+ }
+
+#ifndef __linux__
+ /* blackdown does not use NONBLOCK */
+ openMode |= O_NONBLOCK;
+#endif
+
+ if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
+ info->fd = open(desc.path, openMode);
+ }
+ if (info->fd < 0) {
+ ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex);
+ free(info);
+ return NULL;
+ }
+ /* set to multiple open */
+ if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) {
+ TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path);
+ } else {
+ ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path);
+ }
+
+ AUDIO_INITINFO(&(info->info));
+ /* need AUDIO_GETINFO ioctl to get this to work on solaris x86 */
+ err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
+
+ /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */
+ AUDIO_INITINFO(&(info->info));
+
+ if (isSource) {
+ info->info.play.sample_rate = sampleRate;
+ info->info.play.precision = sampleSizeInBits;
+ info->info.play.channels = channels;
+ info->info.play.encoding = AUDIO_ENCODING_LINEAR;
+ info->info.play.buffer_size = bufferSizeInBytes;
+ info->info.play.pause = 1;
+ } else {
+ info->info.record.sample_rate = sampleRate;
+ info->info.record.precision = sampleSizeInBits;
+ info->info.record.channels = channels;
+ info->info.record.encoding = AUDIO_ENCODING_LINEAR;
+ info->info.record.buffer_size = bufferSizeInBytes;
+ info->info.record.pause = 1;
+ }
+ err = ioctl(info->fd, AUDIO_SETINFO, &(info->info));
+ if (err < 0) {
+ ERROR0("DAUDIO_Open: could not set info!\n");
+ DAUDIO_Close((void*) info, isSource);
+ return NULL;
+ }
+ DAUDIO_Flush((void*) info, isSource);
+
+ err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
+ if (err >= 0) {
+ if (isSource) {
+ info->bufferSizeInBytes = info->info.play.buffer_size;
+ } else {
+ info->bufferSizeInBytes = info->info.record.buffer_size;
+ }
+ TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n",
+ (int) bufferSizeInBytes,
+ (int) info->bufferSizeInBytes);
+ } else {
+ ERROR0("DAUDIO_Open: cannot get info!\n");
+ DAUDIO_Close((void*) info, isSource);
+ return NULL;
+ }
+ TRACE0("< DAUDIO_Open: Opened device successfully.\n");
+ return (void*) info;
+}
+
+
+int DAUDIO_Start(void* id, int isSource) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int err, modified;
+ audio_info_t audioInfo;
+
+ TRACE0("> DAUDIO_Start\n");
+
+ AUDIO_INITINFO(&audioInfo);
+ err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
+ if (err >= 0) {
+ // unpause
+ modified = FALSE;
+ if (isSource && audioInfo.play.pause) {
+ audioInfo.play.pause = 0;
+ modified = TRUE;
+ }
+ if (!isSource && audioInfo.record.pause) {
+ audioInfo.record.pause = 0;
+ modified = TRUE;
+ }
+ if (modified) {
+ err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
+ }
+ }
+
+ TRACE1("< DAUDIO_Start %s\n", (err>=0)?"success":"error");
+ return (err >= 0)?TRUE:FALSE;
+}
+
+int DAUDIO_Stop(void* id, int isSource) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int err, modified;
+ audio_info_t audioInfo;
+
+ TRACE0("> DAUDIO_Stop\n");
+
+ AUDIO_INITINFO(&audioInfo);
+ err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
+ if (err >= 0) {
+ // pause
+ modified = FALSE;
+ if (isSource && !audioInfo.play.pause) {
+ audioInfo.play.pause = 1;
+ modified = TRUE;
+ }
+ if (!isSource && !audioInfo.record.pause) {
+ audioInfo.record.pause = 1;
+ modified = TRUE;
+ }
+ if (modified) {
+ err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
+ }
+ }
+
+ TRACE1("< DAUDIO_Stop %s\n", (err>=0)?"success":"error");
+ return (err >= 0)?TRUE:FALSE;
+}
+
+void DAUDIO_Close(void* id, int isSource) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+
+ TRACE0("DAUDIO_Close\n");
+ if (info != NULL) {
+ if (info->fd >= 0) {
+ DAUDIO_Flush(id, isSource);
+ close(info->fd);
+ }
+ free(info);
+ }
+}
+
+#ifndef USE_TRACE
+/* close to 2^31 */
+#define POSITION_MAX 2000000000
+#else
+/* for testing */
+#define POSITION_MAX 1000000
+#endif
+
+void resetErrorFlagAndAdjustPosition(SolPcmInfo* info, int isSource, int count) {
+ audio_info_t audioInfo;
+ audio_prinfo_t* prinfo;
+ int err;
+ int offset = -1;
+ int underrun = FALSE;
+ int devBytes = 0;
+
+ if (count > 0) {
+ info->transferedBytes += count;
+
+ if (isSource) {
+ prinfo = &(audioInfo.play);
+ } else {
+ prinfo = &(audioInfo.record);
+ }
+ AUDIO_INITINFO(&audioInfo);
+ err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
+ if (err >= 0) {
+ underrun = prinfo->error;
+ devBytes = prinfo->samples * info->frameSize;
+ }
+ AUDIO_INITINFO(&audioInfo);
+ if (underrun) {
+ /* if an underrun occurred, reset */
+ ERROR1("DAUDIO_Write/Read: Underrun/overflow: adjusting positionOffset by %d:\n",
+ (devBytes - info->transferedBytes));
+ ERROR1(" devBytes from %d to 0, ", devBytes);
+ ERROR2(" positionOffset from %d to %d ",
+ (int) info->positionOffset,
+ (int) (info->positionOffset + info->transferedBytes));
+ ERROR1(" transferedBytes from %d to 0\n",
+ (int) info->transferedBytes);
+ prinfo->samples = 0;
+ info->positionOffset += info->transferedBytes;
+ info->transferedBytes = 0;
+ }
+ else if (info->transferedBytes > POSITION_MAX) {
+ /* we will reset transferedBytes and
+ * the samples field in prinfo
+ */
+ offset = devBytes;
+ prinfo->samples = 0;
+ }
+ /* reset error flag */
+ prinfo->error = 0;
+
+ err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
+ if (err >= 0) {
+ if (offset > 0) {
+ /* upon exit of AUDIO_SETINFO, the samples parameter
+ * was set to the previous value. This is our
+ * offset.
+ */
+ TRACE1("Adjust samplePos: offset=%d, ", (int) offset);
+ TRACE2("transferedBytes=%d -> %d, ",
+ (int) info->transferedBytes,
+ (int) (info->transferedBytes - offset));
+ TRACE2("positionOffset=%d -> %d\n",
+ (int) (info->positionOffset),
+ (int) (((int) info->positionOffset) + offset));
+ info->transferedBytes -= offset;
+ info->positionOffset += offset;
+ }
+ } else {
+ ERROR0("DAUDIO: resetErrorFlagAndAdjustPosition ioctl failed!\n");
+ }
+ }
+}
+
+// returns -1 on error
+int DAUDIO_Write(void* id, char* data, int byteSize) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int ret = -1;
+
+ TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
+ if (info!=NULL) {
+ ret = write(info->fd, data, byteSize);
+ resetErrorFlagAndAdjustPosition(info, TRUE, ret);
+ /* sets ret to -1 if buffer full, no error! */
+ if (ret < 0) {
+ ret = 0;
+ }
+ }
+ TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
+ return ret;
+}
+
+// returns -1 on error
+int DAUDIO_Read(void* id, char* data, int byteSize) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int ret = -1;
+
+ TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
+ if (info != NULL) {
+ ret = read(info->fd, data, byteSize);
+ resetErrorFlagAndAdjustPosition(info, TRUE, ret);
+ /* sets ret to -1 if buffer full, no error! */
+ if (ret < 0) {
+ ret = 0;
+ }
+ }
+ TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
+ return ret;
+}
+
+
+int DAUDIO_GetBufferSize(void* id, int isSource) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ if (info) {
+ return info->bufferSizeInBytes;
+ }
+ return 0;
+}
+
+int DAUDIO_StillDraining(void* id, int isSource) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ audio_info_t audioInfo;
+ audio_prinfo_t* prinfo;
+ int ret = FALSE;
+
+ if (info!=NULL) {
+ if (isSource) {
+ prinfo = &(audioInfo.play);
+ } else {
+ prinfo = &(audioInfo.record);
+ }
+ /* check error flag */
+ AUDIO_INITINFO(&audioInfo);
+ ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
+ ret = (prinfo->error != 0)?FALSE:TRUE;
+ }
+ return ret;
+}
+
+
+int getDevicePosition(SolPcmInfo* info, int isSource) {
+ audio_info_t audioInfo;
+ audio_prinfo_t* prinfo;
+ int err;
+
+ if (isSource) {
+ prinfo = &(audioInfo.play);
+ } else {
+ prinfo = &(audioInfo.record);
+ }
+ AUDIO_INITINFO(&audioInfo);
+ err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
+ if (err >= 0) {
+ /*TRACE2("---> device paused: %d eof=%d\n",
+ prinfo->pause, prinfo->eof);
+ */
+ return (int) (prinfo->samples * info->frameSize);
+ }
+ ERROR0("DAUDIO: getDevicePosition: ioctl failed!\n");
+ return -1;
+}
+
+int DAUDIO_Flush(void* id, int isSource) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int err = -1;
+ int pos;
+
+ TRACE0("DAUDIO_Flush\n");
+ if (info) {
+ if (isSource) {
+ err = ioctl(info->fd, I_FLUSH, FLUSHW);
+ } else {
+ err = ioctl(info->fd, I_FLUSH, FLUSHR);
+ }
+ if (err >= 0) {
+ /* resets the transferedBytes parameter to
+ * the current samples count of the device
+ */
+ pos = getDevicePosition(info, isSource);
+ if (pos >= 0) {
+ info->transferedBytes = pos;
+ }
+ }
+ }
+ if (err < 0) {
+ ERROR0("ERROR in DAUDIO_Flush\n");
+ }
+ return (err < 0)?FALSE:TRUE;
+}
+
+int DAUDIO_GetAvailable(void* id, int isSource) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int ret = 0;
+ int pos;
+
+ if (info) {
+ /* unfortunately, the STREAMS architecture
+ * seems to not have a method for querying
+ * the available bytes to read/write!
+ * estimate it...
+ */
+ pos = getDevicePosition(info, isSource);
+ if (pos >= 0) {
+ if (isSource) {
+ /* we usually have written more bytes
+ * to the queue than the device position should be
+ */
+ ret = (info->bufferSizeInBytes) - (info->transferedBytes - pos);
+ } else {
+ /* for record, the device stream should
+ * be usually ahead of our read actions
+ */
+ ret = pos - info->transferedBytes;
+ }
+ if (ret > info->bufferSizeInBytes) {
+ ERROR2("DAUDIO_GetAvailable: available=%d, too big at bufferSize=%d!\n",
+ (int) ret, (int) info->bufferSizeInBytes);
+ ERROR2(" devicePos=%d, transferedBytes=%d\n",
+ (int) pos, (int) info->transferedBytes);
+ ret = info->bufferSizeInBytes;
+ }
+ else if (ret < 0) {
+ ERROR1("DAUDIO_GetAvailable: available=%d, in theory not possible!\n",
+ (int) ret);
+ ERROR2(" devicePos=%d, transferedBytes=%d\n",
+ (int) pos, (int) info->transferedBytes);
+ ret = 0;
+ }
+ }
+ }
+
+ TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
+ return ret;
+}
+
+INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int ret;
+ int pos;
+ INT64 result = javaBytePos;
+
+ if (info) {
+ pos = getDevicePosition(info, isSource);
+ if (pos >= 0) {
+ result = info->positionOffset + pos;
+ }
+ }
+
+ //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
+ return result;
+}
+
+
+void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
+ SolPcmInfo* info = (SolPcmInfo*) id;
+ int ret;
+ int pos;
+
+ if (info) {
+ pos = getDevicePosition(info, isSource);
+ if (pos >= 0) {
+ info->positionOffset = javaBytePos - pos;
+ }
+ }
+}
+
+int DAUDIO_RequiresServicing(void* id, int isSource) {
+ // never need servicing on Solaris
+ return FALSE;
+}
+
+void DAUDIO_Service(void* id, int isSource) {
+ // never need servicing on Solaris
+}
+
+
+#endif // USE_DAUDIO
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Ports.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2002, 2016, 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 "Ports.h"
+#include "PLATFORM_API_SolarisOS_Utils.h"
+
+#if USE_PORTS == TRUE
+
+#define MONITOR_GAIN_STRING "Monitor Gain"
+
+#define ALL_TARGET_PORT_COUNT 6
+
+// define the following to not use audio_prinfo_t.mod_ports
+#define SOLARIS7_COMPATIBLE
+
+// Solaris audio defines
+static int targetPorts[ALL_TARGET_PORT_COUNT] = {
+ AUDIO_SPEAKER,
+ AUDIO_HEADPHONE,
+ AUDIO_LINE_OUT,
+ AUDIO_AUX1_OUT,
+ AUDIO_AUX2_OUT,
+ AUDIO_SPDIF_OUT
+};
+
+static char* targetPortNames[ALL_TARGET_PORT_COUNT] = {
+ "Speaker",
+ "Headphone",
+ "Line Out",
+ "AUX1 Out",
+ "AUX2 Out",
+ "SPDIF Out"
+};
+
+// defined in Ports.h
+static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = {
+ PORT_DST_SPEAKER,
+ PORT_DST_HEADPHONE,
+ PORT_DST_LINE_OUT,
+ PORT_DST_UNKNOWN,
+ PORT_DST_UNKNOWN,
+ PORT_DST_UNKNOWN,
+};
+
+#define ALL_SOURCE_PORT_COUNT 7
+
+// Solaris audio defines
+static int sourcePorts[ALL_SOURCE_PORT_COUNT] = {
+ AUDIO_MICROPHONE,
+ AUDIO_LINE_IN,
+ AUDIO_CD,
+ AUDIO_AUX1_IN,
+ AUDIO_AUX2_IN,
+ AUDIO_SPDIF_IN,
+ AUDIO_CODEC_LOOPB_IN
+};
+
+static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = {
+ "Microphone In",
+ "Line In",
+ "Compact Disc In",
+ "AUX1 In",
+ "AUX2 In",
+ "SPDIF In",
+ "Internal Loopback"
+};
+
+// Ports.h defines
+static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = {
+ PORT_SRC_MICROPHONE,
+ PORT_SRC_LINE_IN,
+ PORT_SRC_COMPACT_DISC,
+ PORT_SRC_UNKNOWN,
+ PORT_SRC_UNKNOWN,
+ PORT_SRC_UNKNOWN,
+ PORT_SRC_UNKNOWN
+};
+
+struct tag_PortControlID;
+
+typedef struct tag_PortInfo {
+ int fd; // file descriptor of the pseudo device
+ audio_info_t audioInfo;
+ // ports
+ int targetPortCount;
+ int sourcePortCount;
+ // indexes to sourcePorts/targetPorts
+ // contains first target ports, then source ports
+ int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT];
+ // controls
+ int maxControlCount; // upper bound of number of controls
+ int usedControlIDs; // number of items already filled in controlIDs
+ struct tag_PortControlID* controlIDs; // the control IDs themselves
+} PortInfo;
+
+#define PORT_CONTROL_TYPE_PLAY 0x4000000
+#define PORT_CONTROL_TYPE_RECORD 0x8000000
+#define PORT_CONTROL_TYPE_SELECT_PORT 1
+#define PORT_CONTROL_TYPE_GAIN 2
+#define PORT_CONTROL_TYPE_BALANCE 3
+#define PORT_CONTROL_TYPE_MONITOR_GAIN 10
+#define PORT_CONTROL_TYPE_OUTPUT_MUTED 11
+#define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD
+#define PORT_CONTROL_TYPE_MASK 0xFFFFFF
+
+
+typedef struct tag_PortControlID {
+ PortInfo* portInfo;
+ INT32 controlType; // PORT_CONTROL_TYPE_XX
+ uint_t port;
+} PortControlID;
+
+
+///// implemented functions of Ports.h
+
+INT32 PORT_GetPortMixerCount() {
+ return (INT32) getAudioDeviceCount();
+}
+
+
+INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
+ AudioDeviceDescription desc;
+
+ if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
+ strncpy(description->name, desc.name, PORT_STRING_LENGTH-1);
+ description->name[PORT_STRING_LENGTH-1] = 0;
+ strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1);
+ description->vendor[PORT_STRING_LENGTH-1] = 0;
+ strncpy(description->version, desc.version, PORT_STRING_LENGTH-1);
+ description->version[PORT_STRING_LENGTH-1] = 0;
+ /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/
+ strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1);
+ description->description[PORT_STRING_LENGTH-1] = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+void* PORT_Open(INT32 mixerIndex) {
+ PortInfo* info = NULL;
+ int fd = -1;
+ AudioDeviceDescription desc;
+ int success = FALSE;
+
+ TRACE0("PORT_Open\n");
+ if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
+ fd = open(desc.pathctl, O_RDWR);
+ }
+ if (fd < 0) {
+ ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
+ return NULL;
+ }
+
+ info = (PortInfo*) malloc(sizeof(PortInfo));
+ if (info != NULL) {
+ memset(info, 0, sizeof(PortInfo));
+ info->fd = fd;
+ success = TRUE;
+ }
+ if (!success) {
+ if (fd >= 0) {
+ close(fd);
+ }
+ PORT_Close((void*) info);
+ info = NULL;
+ }
+ return info;
+}
+
+void PORT_Close(void* id) {
+ TRACE0("PORT_Close\n");
+ if (id != NULL) {
+ PortInfo* info = (PortInfo*) id;
+ if (info->fd >= 0) {
+ close(info->fd);
+ info->fd = -1;
+ }
+ if (info->controlIDs) {
+ free(info->controlIDs);
+ info->controlIDs = NULL;
+ }
+ free(info);
+ }
+}
+
+
+
+INT32 PORT_GetPortCount(void* id) {
+ int ret = 0;
+ PortInfo* info = (PortInfo*) id;
+ if (info != NULL) {
+ if (!info->targetPortCount && !info->sourcePortCount) {
+ int i;
+ AUDIO_INITINFO(&info->audioInfo);
+ if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) {
+ for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) {
+ if (info->audioInfo.play.avail_ports & targetPorts[i]) {
+ info->ports[info->targetPortCount] = i;
+ info->targetPortCount++;
+ }
+#ifdef SOLARIS7_COMPATIBLE
+ TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i],
+ info->audioInfo.play.avail_ports & targetPorts[i]);
+#else
+ TRACE4("Target %d %s: avail=%d mod=%d\n", i, targetPortNames[i],
+ info->audioInfo.play.avail_ports & targetPorts[i],
+ info->audioInfo.play.mod_ports & targetPorts[i]);
+#endif
+ }
+ for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) {
+ if (info->audioInfo.record.avail_ports & sourcePorts[i]) {
+ info->ports[info->targetPortCount + info->sourcePortCount] = i;
+ info->sourcePortCount++;
+ }
+#ifdef SOLARIS7_COMPATIBLE
+ TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i],
+ info->audioInfo.record.avail_ports & sourcePorts[i]);
+#else
+ TRACE4("Source %d %s: avail=%d mod=%d\n", i, sourcePortNames[i],
+ info->audioInfo.record.avail_ports & sourcePorts[i],
+ info->audioInfo.record.mod_ports & sourcePorts[i]);
+#endif
+ }
+ }
+ }
+ ret = info->targetPortCount + info->sourcePortCount;
+ }
+ return ret;
+}
+
+int isSourcePort(PortInfo* info, INT32 portIndex) {
+ return (portIndex >= info->targetPortCount);
+}
+
+INT32 PORT_GetPortType(void* id, INT32 portIndex) {
+ PortInfo* info = (PortInfo*) id;
+ if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
+ if (isSourcePort(info, portIndex)) {
+ return sourcePortJavaSoundMapping[info->ports[portIndex]];
+ } else {
+ return targetPortJavaSoundMapping[info->ports[portIndex]];
+ }
+ }
+ return 0;
+}
+
+// pre-condition: portIndex must have been verified!
+char* getPortName(PortInfo* info, INT32 portIndex) {
+ char* ret = NULL;
+
+ if (isSourcePort(info, portIndex)) {
+ ret = sourcePortNames[info->ports[portIndex]];
+ } else {
+ ret = targetPortNames[info->ports[portIndex]];
+ }
+ return ret;
+}
+
+INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
+ PortInfo* info = (PortInfo*) id;
+ char* n;
+
+ if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
+ n = getPortName(info, portIndex);
+ if (n) {
+ strncpy(name, n, len-1);
+ name[len-1] = 0;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex,
+ INT32 type, void** controlObjects, int* controlCount) {
+ PortControlID* controlID;
+ void* newControl = NULL;
+ int controlIndex;
+ char* jsType = NULL;
+ int isBoolean = FALSE;
+
+ TRACE0(">createPortControl\n");
+
+ // fill the ControlID structure and add this control
+ if (info->usedControlIDs >= info->maxControlCount) {
+ ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount);
+ return;
+ }
+ controlID = &(info->controlIDs[info->usedControlIDs]);
+ controlID->portInfo = info;
+ controlID->controlType = type;
+ controlIndex = info->ports[portIndex];
+ if (isSourcePort(info, portIndex)) {
+ controlID->port = sourcePorts[controlIndex];
+ } else {
+ controlID->port = targetPorts[controlIndex];
+ }
+ switch (type & PORT_CONTROL_TYPE_MASK) {
+ case PORT_CONTROL_TYPE_SELECT_PORT:
+ jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break;
+ case PORT_CONTROL_TYPE_GAIN:
+ jsType = CONTROL_TYPE_VOLUME; break;
+ case PORT_CONTROL_TYPE_BALANCE:
+ jsType = CONTROL_TYPE_BALANCE; break;
+ case PORT_CONTROL_TYPE_MONITOR_GAIN:
+ jsType = CONTROL_TYPE_VOLUME; break;
+ case PORT_CONTROL_TYPE_OUTPUT_MUTED:
+ jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break;
+ }
+ if (isBoolean) {
+ TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n");
+ newControl = (creator->newBooleanControl)(creator, controlID, jsType);
+ }
+ else if (jsType == CONTROL_TYPE_BALANCE) {
+ TRACE0(" PORT_CONTROL_TYPE_BALANCE\n");
+ newControl = (creator->newFloatControl)(creator, controlID, jsType,
+ -1.0f, 1.0f, 2.0f / 65.0f, "");
+ } else {
+ TRACE0(" PORT_CONTROL_TYPE_FLOAT\n");
+ newControl = (creator->newFloatControl)(creator, controlID, jsType,
+ 0.0f, 1.0f, 1.0f / 256.0f, "");
+ }
+ if (newControl) {
+ controlObjects[*controlCount] = newControl;
+ (*controlCount)++;
+ info->usedControlIDs++;
+ }
+ TRACE0("<createPortControl\n");
+}
+
+
+void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) {
+ void* compControl;
+
+ TRACE1(">addCompoundControl %d controls\n", *controlCount);
+ if (*controlCount) {
+ // create compound control and add it to the vector
+ compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount);
+ if (compControl) {
+ TRACE1(" addCompoundControl: calling addControl %p\n", compControl);
+ (creator->addControl)(creator, compControl);
+ }
+ *controlCount = 0;
+ }
+ TRACE0("<addCompoundControl\n");
+}
+
+void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) {
+ int i = 0;
+
+ TRACE0(">addAllControl\n");
+ // go through all controls and add them to the vector
+ for (i = 0; i < *controlCount; i++) {
+ (creator->addControl)(creator, controlObjects[i]);
+ }
+ *controlCount = 0;
+ TRACE0("<addAllControl\n");
+}
+
+void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
+ PortInfo* info = (PortInfo*) id;
+ int portCount = PORT_GetPortCount(id);
+ void* controls[4];
+ int controlCount = 0;
+ INT32 type;
+ int selectable = 1;
+ memset(controls, 0, sizeof(controls));
+
+ TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n",
+ id, portIndex, info->controlIDs, info->maxControlCount);
+ if ((portIndex >= 0) && (portIndex < portCount)) {
+ // if the memory isn't reserved for the control structures, allocate it
+ if (!info->controlIDs) {
+ int maxCount = 0;
+ TRACE0("getControl: allocate mem\n");
+ // get a maximum number of controls:
+ // each port has a select, balance, and volume control.
+ maxCount = 3 * portCount;
+ // then there is monitorGain and outputMuted
+ maxCount += (2 * info->targetPortCount);
+ info->maxControlCount = maxCount;
+ info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount);
+ }
+ if (!isSourcePort(info, portIndex)) {
+ type = PORT_CONTROL_TYPE_PLAY;
+ // add master mute control
+ createPortControl(info, creator, portIndex,
+ type | PORT_CONTROL_TYPE_OUTPUT_MUTED,
+ controls, &controlCount);
+ addAllControls(info, creator, controls, &controlCount);
+#ifdef SOLARIS7_COMPATIBLE
+ selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]];
+#else
+ selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]];
+#endif
+ } else {
+ type = PORT_CONTROL_TYPE_RECORD;
+#ifdef SOLARIS7_COMPATIBLE
+ selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]];
+#else
+ selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]];
+#endif
+ }
+ // add a mixer strip with volume, ...
+ createPortControl(info, creator, portIndex,
+ type | PORT_CONTROL_TYPE_GAIN,
+ controls, &controlCount);
+ // ... balance, ...
+ createPortControl(info, creator, portIndex,
+ type | PORT_CONTROL_TYPE_BALANCE,
+ controls, &controlCount);
+ // ... and select control (if not always on)...
+ if (selectable) {
+ createPortControl(info, creator, portIndex,
+ type | PORT_CONTROL_TYPE_SELECT_PORT,
+ controls, &controlCount);
+ }
+ // ... packaged in a compound control.
+ addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount);
+
+ if (type == PORT_CONTROL_TYPE_PLAY) {
+ // add a single strip for source ports with monitor gain
+ createPortControl(info, creator, portIndex,
+ type | PORT_CONTROL_TYPE_MONITOR_GAIN,
+ controls, &controlCount);
+ // also in a compound control
+ addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount);
+ }
+ }
+ TRACE0("< PORT_getControls\n");
+}
+
+INT32 PORT_GetIntValue(void* controlIDV) {
+ PortControlID* controlID = (PortControlID*) controlIDV;
+ audio_info_t audioInfo;
+ audio_prinfo_t* prinfo;
+
+ AUDIO_INITINFO(&audioInfo);
+ if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
+ if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
+ prinfo = &(audioInfo.play);
+ } else {
+ prinfo = &(audioInfo.record);
+ }
+ switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
+ case PORT_CONTROL_TYPE_SELECT_PORT:
+ return (prinfo->port & controlID->port)?TRUE:FALSE;
+ case PORT_CONTROL_TYPE_OUTPUT_MUTED:
+ return (audioInfo.output_muted)?TRUE:FALSE;
+ default:
+ ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
+ }
+ }
+ ERROR0("PORT_GetIntValue: Could not ioctl!\n");
+ return 0;
+}
+
+void PORT_SetIntValue(void* controlIDV, INT32 value) {
+ PortControlID* controlID = (PortControlID*) controlIDV;
+ audio_info_t audioInfo;
+ audio_prinfo_t* prinfo;
+ int setPort;
+
+ if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
+ prinfo = &(audioInfo.play);
+ } else {
+ prinfo = &(audioInfo.record);
+ }
+ switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
+ case PORT_CONTROL_TYPE_SELECT_PORT:
+ // first try to just add this port. if that fails, set ONLY to this port.
+ AUDIO_INITINFO(&audioInfo);
+ if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
+ if (value) {
+ setPort = (prinfo->port | controlID->port);
+ } else {
+ setPort = (prinfo->port - controlID->port);
+ }
+ AUDIO_INITINFO(&audioInfo);
+ prinfo->port = setPort;
+ if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
+ // didn't work. Either this line doesn't support to select several
+ // ports at once (e.g. record), or a real error
+ if (value) {
+ // set to ONLY this port (and disable any other currently selected ports)
+ AUDIO_INITINFO(&audioInfo);
+ prinfo->port = controlID->port;
+ if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
+ ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port);
+ }
+ } else {
+ // assume it's an error
+ ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort);
+ }
+ }
+ break;
+ case PORT_CONTROL_TYPE_OUTPUT_MUTED:
+ AUDIO_INITINFO(&audioInfo);
+ audioInfo.output_muted = (value?TRUE:FALSE);
+ if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
+ ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value);
+ }
+ break;
+ default:
+ ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
+ }
+ }
+}
+
+float PORT_GetFloatValue(void* controlIDV) {
+ PortControlID* controlID = (PortControlID*) controlIDV;
+ audio_info_t audioInfo;
+ audio_prinfo_t* prinfo;
+
+ AUDIO_INITINFO(&audioInfo);
+ if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
+ if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
+ prinfo = &(audioInfo.play);
+ } else {
+ prinfo = &(audioInfo.record);
+ }
+ switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
+ case PORT_CONTROL_TYPE_GAIN:
+ return ((float) (prinfo->gain - AUDIO_MIN_GAIN))
+ / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
+ case PORT_CONTROL_TYPE_BALANCE:
+ return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1))
+ / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE));
+ case PORT_CONTROL_TYPE_MONITOR_GAIN:
+ return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN))
+ / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
+ default:
+ ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
+ }
+ }
+ ERROR0("PORT_GetFloatValue: Could not ioctl!\n");
+ return 0.0f;
+}
+
+void PORT_SetFloatValue(void* controlIDV, float value) {
+ PortControlID* controlID = (PortControlID*) controlIDV;
+ audio_info_t audioInfo;
+ audio_prinfo_t* prinfo;
+
+ AUDIO_INITINFO(&audioInfo);
+
+ if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
+ prinfo = &(audioInfo.play);
+ } else {
+ prinfo = &(audioInfo.record);
+ }
+ switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
+ case PORT_CONTROL_TYPE_GAIN:
+ prinfo->gain = AUDIO_MIN_GAIN
+ + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
+ break;
+ case PORT_CONTROL_TYPE_BALANCE:
+ prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE
+ + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f);
+ break;
+ case PORT_CONTROL_TYPE_MONITOR_GAIN:
+ audioInfo.monitor_gain = AUDIO_MIN_GAIN
+ + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
+ break;
+ default:
+ ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
+ return;
+ }
+ if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
+ ERROR0("PORT_SetFloatValue: Could not ioctl!\n");
+ }
+}
+
+#endif // USE_PORTS
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.c Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2002, 2007, 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_SolarisOS_Utils.h"
+
+#define MAX_AUDIO_DEVICES 20
+
+// not thread safe...
+static AudioDevicePath globalADPaths[MAX_AUDIO_DEVICES];
+static int globalADCount = -1;
+static int globalADCacheTime = -1;
+/* how many seconds do we cache devices */
+#define AD_CACHE_TIME 30
+
+// return seconds
+long getTimeInSeconds() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec;
+}
+
+
+int getAudioDeviceCount() {
+ int count = MAX_AUDIO_DEVICES;
+
+ getAudioDevices(globalADPaths, &count);
+ return count;
+}
+
+/* returns TRUE if the path exists at all */
+int addAudioDevice(char* path, AudioDevicePath* adPath, int* count) {
+ int i;
+ int found = 0;
+ int fileExists = 0;
+ // not thread safe...
+ static struct stat statBuf;
+
+ // get stats on the file
+ if (stat(path, &statBuf) == 0) {
+ // file exists.
+ fileExists = 1;
+ // If it is not yet in the adPath array, add it to the array
+ for (i = 0; i < *count; i++) {
+ if (adPath[i].st_ino == statBuf.st_ino
+ && adPath[i].st_dev == statBuf.st_dev) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ adPath[*count].st_ino = statBuf.st_ino;
+ adPath[*count].st_dev = statBuf.st_dev;
+ strncpy(adPath[*count].path, path, MAX_NAME_LENGTH);
+ adPath[*count].path[MAX_NAME_LENGTH - 1] = 0;
+ (*count)++;
+ TRACE1("Added audio device %s\n", path);
+ }
+ }
+ return fileExists;
+}
+
+
+void getAudioDevices(AudioDevicePath* adPath, int* count) {
+ int maxCount = *count;
+ char* audiodev;
+ char devsound[15];
+ int i;
+ long timeInSeconds = getTimeInSeconds();
+
+ if (globalADCount < 0
+ || (getTimeInSeconds() - globalADCacheTime) > AD_CACHE_TIME
+ || (adPath != globalADPaths)) {
+ *count = 0;
+ // first device, if set, is AUDIODEV variable
+ audiodev = getenv("AUDIODEV");
+ if (audiodev != NULL && audiodev[0] != 0) {
+ addAudioDevice(audiodev, adPath, count);
+ }
+ // then try /dev/audio
+ addAudioDevice("/dev/audio", adPath, count);
+ // then go through all of the /dev/sound/? devices
+ for (i = 0; i < 100; i++) {
+ sprintf(devsound, "/dev/sound/%d", i);
+ if (!addAudioDevice(devsound, adPath, count)) {
+ break;
+ }
+ }
+ if (adPath == globalADPaths) {
+ /* commit cache */
+ globalADCount = *count;
+ /* set cache time */
+ globalADCacheTime = timeInSeconds;
+ }
+ } else {
+ /* return cache */
+ *count = globalADCount;
+ }
+ // that's it
+}
+
+int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames) {
+ int count = MAX_AUDIO_DEVICES;
+ int ret = 0;
+
+ getAudioDevices(globalADPaths, &count);
+ if (index>=0 && index < count) {
+ ret = getAudioDeviceDescription(globalADPaths[index].path, adDesc, getNames);
+ }
+ return ret;
+}
+
+int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames) {
+ int fd;
+ int mixerMode;
+ int len;
+ audio_info_t info;
+ audio_device_t deviceInfo;
+
+ strncpy(adDesc->path, path, MAX_NAME_LENGTH);
+ adDesc->path[MAX_NAME_LENGTH] = 0;
+ strcpy(adDesc->pathctl, adDesc->path);
+ strcat(adDesc->pathctl, "ctl");
+ strcpy(adDesc->name, adDesc->path);
+ adDesc->vendor[0] = 0;
+ adDesc->version[0] = 0;
+ adDesc->description[0] = 0;
+ adDesc->maxSimulLines = 1;
+
+ // try to open the pseudo device and get more information
+ fd = open(adDesc->pathctl, O_WRONLY | O_NONBLOCK);
+ if (fd >= 0) {
+ close(fd);
+ if (getNames) {
+ fd = open(adDesc->pathctl, O_RDONLY);
+ if (fd >= 0) {
+ if (ioctl(fd, AUDIO_GETDEV, &deviceInfo) >= 0) {
+ strncpy(adDesc->vendor, deviceInfo.name, MAX_AUDIO_DEV_LEN);
+ adDesc->vendor[MAX_AUDIO_DEV_LEN] = 0;
+ strncpy(adDesc->version, deviceInfo.version, MAX_AUDIO_DEV_LEN);
+ adDesc->version[MAX_AUDIO_DEV_LEN] = 0;
+ /* add config string to the dev name
+ * creates a string like "/dev/audio (onboard1)"
+ */
+ len = strlen(adDesc->name) + 1;
+ if (MAX_NAME_LENGTH - len > 3) {
+ strcat(adDesc->name, " (");
+ strncat(adDesc->name, deviceInfo.config, MAX_NAME_LENGTH - len);
+ strcat(adDesc->name, ")");
+ }
+ adDesc->name[MAX_NAME_LENGTH-1] = 0;
+ }
+ if (ioctl(fd, AUDIO_MIXERCTL_GET_MODE, &mixerMode) >= 0) {
+ if (mixerMode == AM_MIXER_MODE) {
+ TRACE1(" getAudioDeviceDescription: %s is in mixer mode\n", adDesc->path);
+ adDesc->maxSimulLines = -1;
+ }
+ } else {
+ ERROR1("ioctl AUDIO_MIXERCTL_GET_MODE failed on %s!\n", adDesc->path);
+ }
+ close(fd);
+ } else {
+ ERROR1("could not open %s!\n", adDesc->pathctl);
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_Utils.h Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2002, 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.
+ */
+
+#include <Utilities.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+/* does not work on Solaris 2.7 */
+#include <sys/audio.h>
+#include <sys/mixer.h>
+#include <sys/types.h>
+#ifndef __linux__
+#include <stropts.h>
+#endif
+#include <sys/conf.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifndef PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
+#define PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
+
+/* defines for Solaris 2.7
+ #ifndef AUDIO_AUX1_OUT
+ #define AUDIO_AUX1_OUT (0x08) // output to aux1 out
+ #define AUDIO_AUX2_OUT (0x10) // output to aux2 out
+ #define AUDIO_SPDIF_OUT (0x20) // output to SPDIF port
+ #define AUDIO_AUX1_IN (0x08) // input from aux1 in
+ #define AUDIO_AUX2_IN (0x10) // input from aux2 in
+ #define AUDIO_SPDIF_IN (0x20) // input from SPDIF port
+ #endif
+*/
+
+/* input from Codec inter. loopback */
+#ifndef AUDIO_CODEC_LOOPB_IN
+#define AUDIO_CODEC_LOOPB_IN (0x40)
+#endif
+
+
+#define MAX_NAME_LENGTH 300
+
+typedef struct tag_AudioDevicePath {
+ char path[MAX_NAME_LENGTH];
+ ino_t st_ino; // inode number to detect duplicate devices
+ dev_t st_dev; // device ID to detect duplicate audio devices
+} AudioDevicePath;
+
+typedef struct tag_AudioDeviceDescription {
+ INT32 maxSimulLines;
+ char path[MAX_NAME_LENGTH+1];
+ char pathctl[MAX_NAME_LENGTH+4];
+ char name[MAX_NAME_LENGTH+1];
+ char vendor[MAX_NAME_LENGTH+1];
+ char version[MAX_NAME_LENGTH+1];
+ char description[MAX_NAME_LENGTH+1];
+} AudioDeviceDescription;
+
+int getAudioDeviceCount();
+
+/*
+ * adPath is an array of AudioDevicePath structures
+ * count contains initially the number of elements in adPath
+ * and will be set to the returned number of paths.
+ */
+void getAudioDevices(AudioDevicePath* adPath, int* count);
+
+/*
+ * fills adDesc from the audio device given in path
+ * returns 0 if an error occurred
+ * if getNames is 0, only path and pathctl are filled
+ */
+int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames);
+int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames);
+
+
+#endif // PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c Fri Mar 23 18:44:47 2018 +0000
@@ -45,18 +45,18 @@
static GtkLib gtk_libs[] = {
{
+ GTK_3,
+ JNI_LIB_NAME("gtk-3"),
+ VERSIONED_JNI_LIB_NAME("gtk-3", "0"),
+ >k3_load,
+ >k3_check
+ },
+ {
GTK_2,
JNI_LIB_NAME("gtk-x11-2.0"),
VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0"),
>k2_load,
>k2_check
- },
- {
- GTK_3,
- JNI_LIB_NAME("gtk-3"),
- VERSIONED_JNI_LIB_NAME("gtk-3", "0"),
- >k3_load,
- >k3_check
}
};
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_CommonUtils.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_CommonUtils.h Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,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.
- */
-
-#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
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiIn.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,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
-
-#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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiOut.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,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
-
-#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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiUtils.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,481 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiUtils.h Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,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.
- */
-
-#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
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCM.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,941 +0,0 @@
-/*
- * Copyright (c) 2002, 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_PCMUtils.h"
-#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
-#include "DirectAudio.h"
-
-#if USE_DAUDIO == TRUE
-
-// GetPosition method 1: based on how many bytes are passed to the kernel driver
-// + does not need much processor resources
-// - not very exact, "jumps"
-// GetPosition method 2: ask kernel about actual position of playback.
-// - very exact
-// - switch to kernel layer for each call
-// GetPosition method 3: use snd_pcm_avail() call - not yet in official ALSA
-// quick tests on a Pentium 200MMX showed max. 1.5% processor usage
-// for playing back a CD-quality file and printing 20x per second a line
-// on the console with the current time. So I guess performance is not such a
-// factor here.
-//#define GET_POSITION_METHOD1
-#define GET_POSITION_METHOD2
-
-
-// The default time for a period in microseconds.
-// For very small buffers, only 2 periods are used.
-#define DEFAULT_PERIOD_TIME 20000 /* 20ms */
-
-///// implemented functions of DirectAudio.h
-
-INT32 DAUDIO_GetDirectAudioDeviceCount() {
- return (INT32) getAudioDeviceCount();
-}
-
-
-INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* description) {
- ALSA_AudioDeviceDescription adesc;
-
- adesc.index = (int) mixerIndex;
- adesc.strLen = DAUDIO_STRING_LENGTH;
-
- adesc.maxSimultaneousLines = (int*) (&(description->maxSimulLines));
- adesc.deviceID = &(description->deviceID);
- adesc.name = description->name;
- adesc.vendor = description->vendor;
- adesc.description = description->description;
- adesc.version = description->version;
-
- return getAudioDeviceDescriptionByIndex(&adesc);
-}
-
-#define MAX_BIT_INDEX 6
-// returns
-// 6: for anything above 24-bit
-// 5: for 4 bytes sample size, 24-bit
-// 4: for 3 bytes sample size, 24-bit
-// 3: for 3 bytes sample size, 20-bit
-// 2: for 2 bytes sample size, 16-bit
-// 1: for 1 byte sample size, 8-bit
-// 0: for anything else
-int getBitIndex(int sampleSizeInBytes, int significantBits) {
- if (significantBits > 24) return 6;
- if (sampleSizeInBytes == 4 && significantBits == 24) return 5;
- if (sampleSizeInBytes == 3) {
- if (significantBits == 24) return 4;
- if (significantBits == 20) return 3;
- }
- if (sampleSizeInBytes == 2 && significantBits == 16) return 2;
- if (sampleSizeInBytes == 1 && significantBits == 8) return 1;
- return 0;
-}
-
-int getSampleSizeInBytes(int bitIndex, int sampleSizeInBytes) {
- switch(bitIndex) {
- case 1: return 1;
- case 2: return 2;
- case 3: /* fall through */
- case 4: return 3;
- case 5: return 4;
- }
- return sampleSizeInBytes;
-}
-
-int getSignificantBits(int bitIndex, int significantBits) {
- switch(bitIndex) {
- case 1: return 8;
- case 2: return 16;
- case 3: return 20;
- case 4: /* fall through */
- case 5: return 24;
- }
- return significantBits;
-}
-
-void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
- snd_pcm_t* handle;
- snd_pcm_format_mask_t* formatMask;
- snd_pcm_format_t format;
- snd_pcm_hw_params_t* hwParams;
- int handledBits[MAX_BIT_INDEX+1];
-
- int ret;
- int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc;
- int origSampleSizeInBytes, origSignificantBits;
- unsigned int channels, minChannels, maxChannels;
- int rate, bitIndex;
-
- for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE;
- if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) {
- return;
- }
- ret = snd_pcm_format_mask_malloc(&formatMask);
- if (ret != 0) {
- ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret);
- } else {
- ret = snd_pcm_hw_params_malloc(&hwParams);
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
- } else {
- ret = snd_pcm_hw_params_any(handle, hwParams);
- /* snd_pcm_hw_params_any can return a positive value on success too */
- if (ret < 0) {
- ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
- } else {
- /* for the logic following this code, set ret to 0 to indicate success */
- ret = 0;
- }
- }
- snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
- if (ret == 0) {
- ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels);
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret);
- }
- }
- if (ret == 0) {
- ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels);
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret);
- }
- }
-
- // since we queried the hw: device, for many soundcards, it will only
- // report the maximum number of channels (which is the only way to talk
- // to the hw: device). Since we will, however, open the plughw: device
- // when opening the Source/TargetDataLine, we can safely assume that
- // also the channels 1..maxChannels are available.
-#ifdef ALSA_PCM_USE_PLUGHW
- minChannels = 1;
-#endif
- if (ret == 0) {
- // plughw: supports any sample rate
- rate = -1;
- for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
- if (snd_pcm_format_mask_test(formatMask, format)) {
- // format exists
- if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes,
- &origSignificantBits,
- &isSigned, &isBigEndian, &enc)) {
- // now if we use plughw:, we can use any bit size below the
- // natively supported ones. Some ALSA drivers only support the maximum
- // bit size, so we add any sample rates below the reported one.
- // E.g. this iteration reports support for 16-bit.
- // getBitIndex will return 2, so it will add entries for
- // 16-bit (bitIndex=2) and in the next do-while loop iteration,
- // it will decrease bitIndex and will therefore add 8-bit support.
- bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits);
- do {
- if (bitIndex == 0
- || bitIndex == MAX_BIT_INDEX
- || !handledBits[bitIndex]) {
- handledBits[bitIndex] = TRUE;
- sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes);
- significantBits = getSignificantBits(bitIndex, origSignificantBits);
- if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) {
- // avoid too many channels explicitly listed
- // just add -1, min, and max
- DAUDIO_AddAudioFormat(creator, significantBits,
- -1, -1, rate,
- enc, isSigned, isBigEndian);
- DAUDIO_AddAudioFormat(creator, significantBits,
- sampleSizeInBytes * minChannels,
- minChannels, rate,
- enc, isSigned, isBigEndian);
- DAUDIO_AddAudioFormat(creator, significantBits,
- sampleSizeInBytes * maxChannels,
- maxChannels, rate,
- enc, isSigned, isBigEndian);
- } else {
- for (channels = minChannels; channels <= maxChannels; channels++) {
- DAUDIO_AddAudioFormat(creator, significantBits,
- sampleSizeInBytes * channels,
- channels, rate,
- enc, isSigned, isBigEndian);
- }
- }
- }
-#ifndef ALSA_PCM_USE_PLUGHW
- // without plugin, do not add fake formats
- break;
-#endif
- } while (--bitIndex > 0);
- } else {
- TRACE1("could not get format from alsa for format %d\n", format);
- }
- } else {
- //TRACE1("Format %d not supported\n", format);
- }
- } // for loop
- snd_pcm_hw_params_free(hwParams);
- }
- snd_pcm_format_mask_free(formatMask);
- }
- snd_pcm_close(handle);
-}
-
-/** Workaround for cr 7033899, 7030629:
- * dmix plugin doesn't like flush (snd_pcm_drop) when the buffer is empty
- * (just opened, underruned or already flushed).
- * Sometimes it causes PCM falls to -EBADFD error,
- * sometimes causes bufferSize change.
- * To prevent unnecessary flushes AlsaPcmInfo::isRunning & isFlushed are used.
- */
-/* ******* ALSA PCM INFO ******************** */
-typedef struct tag_AlsaPcmInfo {
- snd_pcm_t* handle;
- snd_pcm_hw_params_t* hwParams;
- snd_pcm_sw_params_t* swParams;
- int bufferSizeInBytes;
- int frameSize; // storage size in Bytes
- unsigned int periods;
- snd_pcm_uframes_t periodSize;
- short int isRunning; // see comment above
- short int isFlushed; // see comment above
-#ifdef GET_POSITION_METHOD2
- // to be used exclusively by getBytePosition!
- snd_pcm_status_t* positionStatus;
-#endif
-} AlsaPcmInfo;
-
-
-int setStartThresholdNoCommit(AlsaPcmInfo* info, int useThreshold) {
- int ret;
- int threshold;
-
- if (useThreshold) {
- // start device whenever anything is written to the buffer
- threshold = 1;
- } else {
- // never start the device automatically
- threshold = 2000000000; /* near UINT_MAX */
- }
- ret = snd_pcm_sw_params_set_start_threshold(info->handle, info->swParams, threshold);
- if (ret < 0) {
- ERROR1("Unable to set start threshold mode: %s\n", snd_strerror(ret));
- return FALSE;
- }
- return TRUE;
-}
-
-int setStartThreshold(AlsaPcmInfo* info, int useThreshold) {
- int ret = 0;
-
- if (!setStartThresholdNoCommit(info, useThreshold)) {
- ret = -1;
- }
- if (ret == 0) {
- // commit it
- ret = snd_pcm_sw_params(info->handle, info->swParams);
- if (ret < 0) {
- ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
- }
- }
- return (ret == 0)?TRUE:FALSE;
-}
-
-
-// returns TRUE if successful
-int setHWParams(AlsaPcmInfo* info,
- float sampleRate,
- int channels,
- int bufferSizeInFrames,
- snd_pcm_format_t format) {
- unsigned int rrate, periodTime, periods;
- int ret, dir;
- snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames;
-
- /* choose all parameters */
- ret = snd_pcm_hw_params_any(info->handle, info->hwParams);
- if (ret < 0) {
- ERROR1("Broken configuration: no configurations available: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* set the interleaved read/write format */
- ret = snd_pcm_hw_params_set_access(info->handle, info->hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
- if (ret < 0) {
- ERROR1("SND_PCM_ACCESS_RW_INTERLEAVED access type not available: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* set the sample format */
- ret = snd_pcm_hw_params_set_format(info->handle, info->hwParams, format);
- if (ret < 0) {
- ERROR1("Sample format not available: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* set the count of channels */
- ret = snd_pcm_hw_params_set_channels(info->handle, info->hwParams, channels);
- if (ret < 0) {
- ERROR2("Channels count (%d) not available: %s\n", channels, snd_strerror(ret));
- return FALSE;
- }
- /* set the stream rate */
- rrate = (int) (sampleRate + 0.5f);
- dir = 0;
- ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir);
- if (ret < 0) {
- ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret));
- return FALSE;
- }
- if ((rrate-sampleRate > 2) || (rrate-sampleRate < - 2)) {
- ERROR2("Rate doesn't match (requested %2.2fHz, got %dHz)\n", sampleRate, rrate);
- return FALSE;
- }
- /* set the buffer time */
- ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames);
- if (ret < 0) {
- ERROR2("Unable to set buffer size to %d frames: %s\n",
- (int) alsaBufferSizeInFrames, snd_strerror(ret));
- return FALSE;
- }
- bufferSizeInFrames = (int) alsaBufferSizeInFrames;
- /* set the period time */
- if (bufferSizeInFrames > 1024) {
- dir = 0;
- periodTime = DEFAULT_PERIOD_TIME;
- ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir);
- if (ret < 0) {
- ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret));
- return FALSE;
- }
- } else {
- /* set the period count for very small buffer sizes to 2 */
- dir = 0;
- periods = 2;
- ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir);
- if (ret < 0) {
- ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret));
- return FALSE;
- }
- }
- /* write the parameters to device */
- ret = snd_pcm_hw_params(info->handle, info->hwParams);
- if (ret < 0) {
- ERROR1("Unable to set hw params: %s\n", snd_strerror(ret));
- return FALSE;
- }
- return TRUE;
-}
-
-// returns 1 if successful
-int setSWParams(AlsaPcmInfo* info) {
- int ret;
-
- /* get the current swparams */
- ret = snd_pcm_sw_params_current(info->handle, info->swParams);
- if (ret < 0) {
- ERROR1("Unable to determine current swparams: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* never start the transfer automatically */
- if (!setStartThresholdNoCommit(info, FALSE /* don't use threshold */)) {
- return FALSE;
- }
-
- /* allow the transfer when at least period_size samples can be processed */
- ret = snd_pcm_sw_params_set_avail_min(info->handle, info->swParams, info->periodSize);
- if (ret < 0) {
- ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* write the parameters to the playback device */
- ret = snd_pcm_sw_params(info->handle, info->swParams);
- if (ret < 0) {
- ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
- return FALSE;
- }
- return TRUE;
-}
-
-static snd_output_t* ALSA_OUTPUT = NULL;
-
-void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
- int encoding, float sampleRate, int sampleSizeInBits,
- int frameSize, int channels,
- int isSigned, int isBigEndian, int bufferSizeInBytes) {
- snd_pcm_format_mask_t* formatMask;
- snd_pcm_format_t format;
- int dir;
- int ret = 0;
- AlsaPcmInfo* info = NULL;
- /* snd_pcm_uframes_t is 64 bit on 64-bit systems */
- snd_pcm_uframes_t alsaBufferSizeInFrames = 0;
-
-
- TRACE0("> DAUDIO_Open\n");
-#ifdef USE_TRACE
- // for using ALSA debug dump methods
- if (ALSA_OUTPUT == NULL) {
- snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
- }
-#endif
- if (channels <= 0) {
- ERROR1("ERROR: Invalid number of channels=%d!\n", channels);
- return NULL;
- }
- info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
- if (!info) {
- ERROR0("Out of memory\n");
- return NULL;
- }
- memset(info, 0, sizeof(AlsaPcmInfo));
- // initial values are: stopped, flushed
- info->isRunning = 0;
- info->isFlushed = 1;
-
- ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
- if (ret == 0) {
- // set to blocking mode
- snd_pcm_nonblock(info->handle, 0);
- ret = snd_pcm_hw_params_malloc(&(info->hwParams));
- if (ret != 0) {
- ERROR1(" snd_pcm_hw_params_malloc returned error %d\n", ret);
- } else {
- ret = -1;
- if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
- isSigned, isBigEndian, encoding)) {
- if (setHWParams(info,
- sampleRate,
- channels,
- bufferSizeInBytes / frameSize,
- format)) {
- info->frameSize = frameSize;
- ret = snd_pcm_hw_params_get_period_size(info->hwParams, &info->periodSize, &dir);
- if (ret < 0) {
- ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
- }
- snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
- snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
- info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
- TRACE3(" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
- (int) info->periodSize, info->periods, info->bufferSizeInBytes);
- }
- }
- }
- if (ret == 0) {
- // set software parameters
- ret = snd_pcm_sw_params_malloc(&(info->swParams));
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
- } else {
- if (!setSWParams(info)) {
- ret = -1;
- }
- }
- }
- if (ret == 0) {
- // prepare device
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
- }
- }
-
-#ifdef GET_POSITION_METHOD2
- if (ret == 0) {
- ret = snd_pcm_status_malloc(&(info->positionStatus));
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
- }
- }
-#endif
- }
- if (ret != 0) {
- DAUDIO_Close((void*) info, isSource);
- info = NULL;
- } else {
- // set to non-blocking mode
- snd_pcm_nonblock(info->handle, 1);
- TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
- (void*) info->handle);
- }
- return (void*) info;
-}
-
-#ifdef USE_TRACE
-void printState(snd_pcm_state_t state) {
- if (state == SND_PCM_STATE_OPEN) {
- TRACE0("State: SND_PCM_STATE_OPEN\n");
- }
- else if (state == SND_PCM_STATE_SETUP) {
- TRACE0("State: SND_PCM_STATE_SETUP\n");
- }
- else if (state == SND_PCM_STATE_PREPARED) {
- TRACE0("State: SND_PCM_STATE_PREPARED\n");
- }
- else if (state == SND_PCM_STATE_RUNNING) {
- TRACE0("State: SND_PCM_STATE_RUNNING\n");
- }
- else if (state == SND_PCM_STATE_XRUN) {
- TRACE0("State: SND_PCM_STATE_XRUN\n");
- }
- else if (state == SND_PCM_STATE_DRAINING) {
- TRACE0("State: SND_PCM_STATE_DRAINING\n");
- }
- else if (state == SND_PCM_STATE_PAUSED) {
- TRACE0("State: SND_PCM_STATE_PAUSED\n");
- }
- else if (state == SND_PCM_STATE_SUSPENDED) {
- TRACE0("State: SND_PCM_STATE_SUSPENDED\n");
- }
-}
-#endif
-
-int DAUDIO_Start(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
- snd_pcm_state_t state;
-
- TRACE0("> DAUDIO_Start\n");
- // set to blocking mode
- snd_pcm_nonblock(info->handle, 0);
- // set start mode so that it always starts as soon as data is there
- setStartThreshold(info, TRUE /* use threshold */);
- state = snd_pcm_state(info->handle);
- if (state == SND_PCM_STATE_PAUSED) {
- // in case it was stopped previously
- TRACE0(" Un-pausing...\n");
- ret = snd_pcm_pause(info->handle, FALSE);
- if (ret != 0) {
- ERROR2(" NOTE: error in snd_pcm_pause:%d: %s\n", ret, snd_strerror(ret));
- }
- }
- if (state == SND_PCM_STATE_SUSPENDED) {
- TRACE0(" Resuming...\n");
- ret = snd_pcm_resume(info->handle);
- if (ret < 0) {
- if ((ret != -EAGAIN) && (ret != -ENOSYS)) {
- ERROR2(" ERROR: error in snd_pcm_resume:%d: %s\n", ret, snd_strerror(ret));
- }
- }
- }
- if (state == SND_PCM_STATE_SETUP) {
- TRACE0("need to call prepare again...\n");
- // prepare device
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
- }
- }
- // in case there is still data in the buffers
- ret = snd_pcm_start(info->handle);
- if (ret != 0) {
- if (ret != -EPIPE) {
- ERROR2(" NOTE: error in snd_pcm_start: %d: %s\n", ret, snd_strerror(ret));
- }
- }
- // set to non-blocking mode
- ret = snd_pcm_nonblock(info->handle, 1);
- if (ret != 0) {
- ERROR1(" ERROR in snd_pcm_nonblock: %s\n", snd_strerror(ret));
- }
- state = snd_pcm_state(info->handle);
-#ifdef USE_TRACE
- printState(state);
-#endif
- ret = (state == SND_PCM_STATE_PREPARED)
- || (state == SND_PCM_STATE_RUNNING)
- || (state == SND_PCM_STATE_XRUN)
- || (state == SND_PCM_STATE_SUSPENDED);
- if (ret) {
- info->isRunning = 1;
- // source line should keep isFlushed value until Write() is called;
- // for target data line reset it right now.
- if (!isSource) {
- info->isFlushed = 0;
- }
- }
- TRACE1("< DAUDIO_Start %s\n", ret?"success":"error");
- return ret?TRUE:FALSE;
-}
-
-int DAUDIO_Stop(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
-
- TRACE0("> DAUDIO_Stop\n");
- // set to blocking mode
- snd_pcm_nonblock(info->handle, 0);
- setStartThreshold(info, FALSE /* don't use threshold */); // device will not start after buffer xrun
- ret = snd_pcm_pause(info->handle, 1);
- // set to non-blocking mode
- snd_pcm_nonblock(info->handle, 1);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_pause: %s\n", snd_strerror(ret));
- return FALSE;
- }
- info->isRunning = 0;
- TRACE0("< DAUDIO_Stop success\n");
- return TRUE;
-}
-
-void DAUDIO_Close(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
-
- TRACE0("DAUDIO_Close\n");
- if (info != NULL) {
- if (info->handle != NULL) {
- snd_pcm_close(info->handle);
- }
- if (info->hwParams) {
- snd_pcm_hw_params_free(info->hwParams);
- }
- if (info->swParams) {
- snd_pcm_sw_params_free(info->swParams);
- }
-#ifdef GET_POSITION_METHOD2
- if (info->positionStatus) {
- snd_pcm_status_free(info->positionStatus);
- }
-#endif
- free(info);
- }
-}
-
-/*
- * Underrun and suspend recovery
- * returns
- * 0: exit native and return 0
- * 1: try again to write/read
- * -1: error - exit native with return value -1
- */
-int xrun_recovery(AlsaPcmInfo* info, int err) {
- int ret;
-
- if (err == -EPIPE) { /* underrun / overflow */
- TRACE0("xrun_recovery: underrun/overflow.\n");
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
- return -1;
- }
- return 1;
- } else if (err == -ESTRPIPE) {
- TRACE0("xrun_recovery: suspended.\n");
- ret = snd_pcm_resume(info->handle);
- if (ret < 0) {
- if (ret == -EAGAIN) {
- return 0; /* wait until the suspend flag is released */
- }
- return -1;
- }
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
- return -1;
- }
- return 1;
- } else if (err == -EAGAIN) {
- TRACE0("xrun_recovery: EAGAIN try again flag.\n");
- return 0;
- }
-
- TRACE2("xrun_recovery: unexpected error %d: %s\n", err, snd_strerror(err));
- return -1;
-}
-
-// returns -1 on error
-int DAUDIO_Write(void* id, char* data, int byteSize) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret, count;
- snd_pcm_sframes_t frameSize, writtenFrames;
-
- TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
-
- /* sanity */
- if (byteSize <= 0 || info->frameSize <= 0) {
- ERROR2(" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
- (int) byteSize, (int) info->frameSize);
- TRACE0("< DAUDIO_Write returning -1\n");
- return -1;
- }
-
- count = 2; // maximum number of trials to recover from underrun
- //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
- frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
- do {
- writtenFrames = snd_pcm_writei(info->handle, (const void*) data, (snd_pcm_uframes_t) frameSize);
-
- if (writtenFrames < 0) {
- ret = xrun_recovery(info, (int) writtenFrames);
- if (ret <= 0) {
- TRACE1("DAUDIO_Write: xrun recovery returned %d -> return.\n", ret);
- return ret;
- }
- if (count-- <= 0) {
- ERROR0("DAUDIO_Write: too many attempts to recover from xrun/suspend\n");
- return -1;
- }
- } else {
- break;
- }
- } while (TRUE);
- //ret = snd_pcm_frames_to_bytes(info->handle, writtenFrames);
-
- if (writtenFrames > 0) {
- // reset "flushed" flag
- info->isFlushed = 0;
- }
-
- ret = (int) (writtenFrames * info->frameSize);
- TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
- return ret;
-}
-
-// returns -1 on error
-int DAUDIO_Read(void* id, char* data, int byteSize) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret, count;
- snd_pcm_sframes_t frameSize, readFrames;
-
- TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
- /*TRACE3(" info=%p, data=%p, byteSize=%d\n",
- (void*) info, (void*) data, (int) byteSize);
- TRACE2(" info->frameSize=%d, info->handle=%p\n",
- (int) info->frameSize, (void*) info->handle);
- */
- /* sanity */
- if (byteSize <= 0 || info->frameSize <= 0) {
- ERROR2(" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
- (int) byteSize, (int) info->frameSize);
- TRACE0("< DAUDIO_Read returning -1\n");
- return -1;
- }
- if (!info->isRunning && info->isFlushed) {
- // PCM has nothing to read
- return 0;
- }
-
- count = 2; // maximum number of trials to recover from error
- //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
- frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
- do {
- readFrames = snd_pcm_readi(info->handle, (void*) data, (snd_pcm_uframes_t) frameSize);
- if (readFrames < 0) {
- ret = xrun_recovery(info, (int) readFrames);
- if (ret <= 0) {
- TRACE1("DAUDIO_Read: xrun recovery returned %d -> return.\n", ret);
- return ret;
- }
- if (count-- <= 0) {
- ERROR0("DAUDIO_Read: too many attempts to recover from xrun/suspend\n");
- return -1;
- }
- } else {
- break;
- }
- } while (TRUE);
- //ret = snd_pcm_frames_to_bytes(info->handle, readFrames);
- ret = (int) (readFrames * info->frameSize);
- TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
- return ret;
-}
-
-
-int DAUDIO_GetBufferSize(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
-
- return info->bufferSizeInBytes;
-}
-
-int DAUDIO_StillDraining(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- snd_pcm_state_t state;
-
- state = snd_pcm_state(info->handle);
- //printState(state);
- //TRACE1("Still draining: %s\n", (state != SND_PCM_STATE_XRUN)?"TRUE":"FALSE");
- return (state == SND_PCM_STATE_RUNNING)?TRUE:FALSE;
-}
-
-
-int DAUDIO_Flush(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
-
- TRACE0("DAUDIO_Flush\n");
-
- if (info->isFlushed) {
- // nothing to drop
- return 1;
- }
-
- ret = snd_pcm_drop(info->handle);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_drop: %s\n", snd_strerror(ret));
- return FALSE;
- }
-
- info->isFlushed = 1;
- if (info->isRunning) {
- ret = DAUDIO_Start(id, isSource);
- }
- return ret;
-}
-
-int DAUDIO_GetAvailable(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- snd_pcm_sframes_t availableInFrames;
- snd_pcm_state_t state;
- int ret;
-
- state = snd_pcm_state(info->handle);
- if (info->isFlushed || state == SND_PCM_STATE_XRUN) {
- // if in xrun state then we have the entire buffer available,
- // not 0 as alsa reports
- ret = info->bufferSizeInBytes;
- } else {
- availableInFrames = snd_pcm_avail_update(info->handle);
- if (availableInFrames < 0) {
- ret = 0;
- } else {
- //ret = snd_pcm_frames_to_bytes(info->handle, availableInFrames);
- ret = (int) (availableInFrames * info->frameSize);
- }
- }
- TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
- return ret;
-}
-
-INT64 estimatePositionFromAvail(AlsaPcmInfo* info, int isSource, INT64 javaBytePos, int availInBytes) {
- // estimate the current position with the buffer size and
- // the available bytes to read or write in the buffer.
- // not an elegant solution - bytePos will stop on xruns,
- // and in race conditions it may jump backwards
- // Advantage is that it is indeed based on the samples that go through
- // the system (rather than time-based methods)
- if (isSource) {
- // javaBytePos is the position that is reached when the current
- // buffer is played completely
- return (INT64) (javaBytePos - info->bufferSizeInBytes + availInBytes);
- } else {
- // javaBytePos is the position that was when the current buffer was empty
- return (INT64) (javaBytePos + availInBytes);
- }
-}
-
-INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
- INT64 result = javaBytePos;
- snd_pcm_state_t state;
- state = snd_pcm_state(info->handle);
-
- if (!info->isFlushed && state != SND_PCM_STATE_XRUN) {
-#ifdef GET_POSITION_METHOD2
- snd_timestamp_t* ts;
- snd_pcm_uframes_t framesAvail;
-
- // note: slight race condition if this is called simultaneously from 2 threads
- ret = snd_pcm_status(info->handle, info->positionStatus);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_status: %s\n", snd_strerror(ret));
- result = javaBytePos;
- } else {
- // calculate from time value, or from available bytes
- framesAvail = snd_pcm_status_get_avail(info->positionStatus);
- result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
- }
-#endif
-#ifdef GET_POSITION_METHOD3
- snd_pcm_uframes_t framesAvail;
- ret = snd_pcm_avail(info->handle, &framesAvail);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_avail: %s\n", snd_strerror(ret));
- result = javaBytePos;
- } else {
- result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
- }
-#endif
-#ifdef GET_POSITION_METHOD1
- result = estimatePositionFromAvail(info, isSource, javaBytePos, DAUDIO_GetAvailable(id, isSource));
-#endif
- }
- //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
- return result;
-}
-
-
-
-void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
- /* save to ignore, since GetBytePosition
- * takes the javaBytePos param into account
- */
-}
-
-int DAUDIO_RequiresServicing(void* id, int isSource) {
- // never need servicing on Bsd
- return FALSE;
-}
-
-void DAUDIO_Service(void* id, int isSource) {
- // never need servicing on Bsd
-}
-
-
-#endif // USE_DAUDIO
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCMUtils.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,292 +0,0 @@
-/*
- * 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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCMUtils.h Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,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 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
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_Ports.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-/*
- * Copyright (c) 2003, 2016, 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 "Ports.h"
-#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
-#include <alsa/asoundlib.h>
-
-#if USE_PORTS == TRUE
-
-#define MAX_ELEMS (300)
-#define MAX_CONTROLS (MAX_ELEMS * 4)
-
-#define CHANNELS_MONO (SND_MIXER_SCHN_LAST + 1)
-#define CHANNELS_STEREO (SND_MIXER_SCHN_LAST + 2)
-
-typedef struct {
- snd_mixer_elem_t* elem;
- INT32 portType; /* one of PORT_XXX_xx */
- char* controlType; /* one of CONTROL_TYPE_xx */
- /* Values: either SND_MIXER_SCHN_FRONT_xx, CHANNELS_MONO or CHANNELS_STEREO.
- For SND_MIXER_SCHN_FRONT_xx, exactly this channel is set/retrieved directly.
- For CHANNELS_MONO, ALSA channel SND_MIXER_SCHN_MONO is set/retrieved directly.
- For CHANNELS_STEREO, ALSA channels SND_MIXER_SCHN_FRONT_LEFT and SND_MIXER_SCHN_FRONT_RIGHT
- are set after a calculation that takes balance into account. Retrieved? Average of both
- channels? (Using a cached value is not a good idea since the value in the HW may have been
- altered.) */
- INT32 channel;
-} PortControl;
-
-
-typedef struct tag_PortMixer {
- snd_mixer_t* mixer_handle;
- /* Number of array elements used in elems and types. */
- int numElems;
- snd_mixer_elem_t** elems;
- /* Array of port types (PORT_SRC_UNKNOWN etc.). Indices are the same as in elems. */
- INT32* types;
- /* Number of array elements used in controls. */
- int numControls;
- PortControl* controls;
-} PortMixer;
-
-
-///// implemented functions of Ports.h
-
-INT32 PORT_GetPortMixerCount() {
- INT32 mixerCount;
- int card;
- char devname[16];
- int err;
- snd_ctl_t *handle;
- snd_ctl_card_info_t* info;
-
- TRACE0("> PORT_GetPortMixerCount\n");
-
- initAlsaSupport();
-
- snd_ctl_card_info_malloc(&info);
- card = -1;
- mixerCount = 0;
- if (snd_card_next(&card) >= 0) {
- while (card >= 0) {
- sprintf(devname, ALSA_HARDWARE_CARD, card);
- TRACE1("PORT_GetPortMixerCount: Opening alsa device \"%s\"...\n", devname);
- err = snd_ctl_open(&handle, devname, 0);
- if (err < 0) {
- ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
- } else {
- mixerCount++;
- snd_ctl_close(handle);
- }
- if (snd_card_next(&card) < 0) {
- break;
- }
- }
- }
- snd_ctl_card_info_free(info);
- TRACE0("< PORT_GetPortMixerCount\n");
- return mixerCount;
-}
-
-
-INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
- snd_ctl_t* handle;
- snd_ctl_card_info_t* card_info;
- char devname[16];
- int err;
- char buffer[100];
-
- TRACE0("> PORT_GetPortMixerDescription\n");
- snd_ctl_card_info_malloc(&card_info);
-
- sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
- TRACE1("Opening alsa device \"%s\"...\n", devname);
- err = snd_ctl_open(&handle, devname, 0);
- if (err < 0) {
- ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
- return FALSE;
- }
- err = snd_ctl_card_info(handle, card_info);
- if (err < 0) {
- ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
- }
- strncpy(description->name, snd_ctl_card_info_get_id(card_info), PORT_STRING_LENGTH - 1);
- sprintf(buffer, " [%s]", devname);
- strncat(description->name, buffer, PORT_STRING_LENGTH - 1 - strlen(description->name));
- strncpy(description->vendor, "ALSA (http://www.alsa-project.org)", PORT_STRING_LENGTH - 1);
- strncpy(description->description, snd_ctl_card_info_get_name(card_info), PORT_STRING_LENGTH - 1);
- strncat(description->description, ", ", PORT_STRING_LENGTH - 1 - strlen(description->description));
- strncat(description->description, snd_ctl_card_info_get_mixername(card_info), PORT_STRING_LENGTH - 1 - strlen(description->description));
- getALSAVersion(description->version, PORT_STRING_LENGTH - 1);
-
- snd_ctl_close(handle);
- snd_ctl_card_info_free(card_info);
- TRACE0("< PORT_GetPortMixerDescription\n");
- return TRUE;
-}
-
-
-void* PORT_Open(INT32 mixerIndex) {
- char devname[16];
- snd_mixer_t* mixer_handle;
- int err;
- PortMixer* handle;
-
- TRACE0("> PORT_Open\n");
- sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
- if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
- ERROR2("Mixer %s open error: %s", devname, snd_strerror(err));
- return NULL;
- }
- if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) {
- ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err));
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) {
- ERROR1("Mixer register error: %s", snd_strerror(err));
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- err = snd_mixer_load(mixer_handle);
- if (err < 0) {
- ERROR2("Mixer %s load error: %s", devname, snd_strerror(err));
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- handle = (PortMixer*) calloc(1, sizeof(PortMixer));
- if (handle == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- handle->numElems = 0;
- handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*));
- if (handle->elems == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- free(handle);
- return NULL;
- }
- handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32));
- if (handle->types == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- free(handle->elems);
- free(handle);
- return NULL;
- }
- handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl));
- if (handle->controls == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- free(handle->elems);
- free(handle->types);
- free(handle);
- return NULL;
- }
- handle->mixer_handle = mixer_handle;
- // necessary to initialize data structures
- PORT_GetPortCount(handle);
- TRACE0("< PORT_Open\n");
- return handle;
-}
-
-
-void PORT_Close(void* id) {
- TRACE0("> PORT_Close\n");
- if (id != NULL) {
- PortMixer* handle = (PortMixer*) id;
- if (handle->mixer_handle != NULL) {
- snd_mixer_close(handle->mixer_handle);
- }
- if (handle->elems != NULL) {
- free(handle->elems);
- }
- if (handle->types != NULL) {
- free(handle->types);
- }
- if (handle->controls != NULL) {
- free(handle->controls);
- }
- free(handle);
- }
- TRACE0("< PORT_Close\n");
-}
-
-
-
-INT32 PORT_GetPortCount(void* id) {
- PortMixer* portMixer;
- snd_mixer_elem_t *elem;
-
- TRACE0("> PORT_GetPortCount\n");
- if (id == NULL) {
- // $$mp: Should become a descriptive error code (invalid handle).
- return -1;
- }
- portMixer = (PortMixer*) id;
- if (portMixer->numElems == 0) {
- for (elem = snd_mixer_first_elem(portMixer->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
- if (!snd_mixer_selem_is_active(elem))
- continue;
- TRACE2("Simple mixer control '%s',%i\n",
- snd_mixer_selem_get_name(elem),
- snd_mixer_selem_get_index(elem));
- if (snd_mixer_selem_has_playback_volume(elem)) {
- portMixer->elems[portMixer->numElems] = elem;
- portMixer->types[portMixer->numElems] = PORT_DST_UNKNOWN;
- portMixer->numElems++;
- }
- // to prevent buffer overflow
- if (portMixer->numElems >= MAX_ELEMS) {
- break;
- }
- /* If an element has both playback an capture volume, it is put into the arrays
- twice. */
- if (snd_mixer_selem_has_capture_volume(elem)) {
- portMixer->elems[portMixer->numElems] = elem;
- portMixer->types[portMixer->numElems] = PORT_SRC_UNKNOWN;
- portMixer->numElems++;
- }
- // to prevent buffer overflow
- if (portMixer->numElems >= MAX_ELEMS) {
- break;
- }
- }
- }
- TRACE0("< PORT_GetPortCount\n");
- return portMixer->numElems;
-}
-
-
-INT32 PORT_GetPortType(void* id, INT32 portIndex) {
- PortMixer* portMixer;
- INT32 type;
- TRACE0("> PORT_GetPortType\n");
- if (id == NULL) {
- // $$mp: Should become a descriptive error code (invalid handle).
- return -1;
- }
- portMixer = (PortMixer*) id;
- if (portIndex < 0 || portIndex >= portMixer->numElems) {
- // $$mp: Should become a descriptive error code (index out of bounds).
- return -1;
- }
- type = portMixer->types[portIndex];
- TRACE0("< PORT_GetPortType\n");
- return type;
-}
-
-
-INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
- PortMixer* portMixer;
- const char* nam;
-
- TRACE0("> PORT_GetPortName\n");
- if (id == NULL) {
- // $$mp: Should become a descriptive error code (invalid handle).
- return -1;
- }
- portMixer = (PortMixer*) id;
- if (portIndex < 0 || portIndex >= portMixer->numElems) {
- // $$mp: Should become a descriptive error code (index out of bounds).
- return -1;
- }
- nam = snd_mixer_selem_get_name(portMixer->elems[portIndex]);
- strncpy(name, nam, len - 1);
- name[len - 1] = 0;
- TRACE0("< PORT_GetPortName\n");
- return TRUE;
-}
-
-
-static int isPlaybackFunction(INT32 portType) {
- return (portType & PORT_DST_MASK);
-}
-
-
-/* Sets portControl to a pointer to the next free array element in the PortControl (pointer)
- array of the passed portMixer. Returns TRUE if successful. May return FALSE if there is no
- free slot. In this case, portControl is not altered */
-static int getControlSlot(PortMixer* portMixer, PortControl** portControl) {
- if (portMixer->numControls >= MAX_CONTROLS) {
- return FALSE;
- } else {
- *portControl = &(portMixer->controls[portMixer->numControls]);
- portMixer->numControls++;
- return TRUE;
- }
-}
-
-
-/* Protect against illegal min-max values, preventing divisions by zero.
- */
-inline static long getRange(long min, long max) {
- if (max > min) {
- return max - min;
- } else {
- return 1;
- }
-}
-
-
-/* Idea: we may specify that if unit is an empty string, the values are linear and if unit is "dB",
- the values are logarithmic.
-*/
-static void* createVolumeControl(PortControlCreator* creator,
- PortControl* portControl,
- snd_mixer_elem_t* elem, int isPlayback) {
- void* control;
- float precision;
- long min, max;
-
- if (isPlayback) {
- snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
- } else {
- snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
- }
- /* $$mp: The volume values retrieved with the ALSA API are strongly supposed to be logarithmic.
- So the following calculation is wrong. However, there is no correct calculation, since
- for equal-distant logarithmic steps, the precision expressed in linear varies over the
- scale. */
- precision = 1.0F / getRange(min, max);
- control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_VOLUME, 0.0F, +1.0F, precision, "");
- return control;
-}
-
-
-void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
- PortMixer* portMixer;
- snd_mixer_elem_t* elem;
- void* control;
- PortControl* portControl;
- void* controls[10];
- int numControls;
- char* portName;
- int isPlayback = 0;
- int isMono;
- int isStereo;
- char* type;
- snd_mixer_selem_channel_id_t channel;
- memset(controls, 0, sizeof(controls));
-
- TRACE0("> PORT_GetControls\n");
- if (id == NULL) {
- ERROR0("Invalid handle!");
- // $$mp: an error code should be returned.
- return;
- }
- portMixer = (PortMixer*) id;
- if (portIndex < 0 || portIndex >= portMixer->numElems) {
- ERROR0("Port index out of range!");
- // $$mp: an error code should be returned.
- return;
- }
- numControls = 0;
- elem = portMixer->elems[portIndex];
- if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) {
- /* Since we've split/duplicated elements with both playback and capture on the recovery
- of elements, we now can assume that we handle only to deal with either playback or
- capture. */
- isPlayback = isPlaybackFunction(portMixer->types[portIndex]);
- isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) ||
- (!isPlayback && snd_mixer_selem_is_capture_mono(elem));
- isStereo = (isPlayback &&
- snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
- snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) ||
- (!isPlayback &&
- snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
- snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT));
- // single volume control
- if (isMono || isStereo) {
- if (getControlSlot(portMixer, &portControl)) {
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = CONTROL_TYPE_VOLUME;
- if (isMono) {
- portControl->channel = CHANNELS_MONO;
- } else {
- portControl->channel = CHANNELS_STEREO;
- }
- control = createVolumeControl(creator, portControl, elem, isPlayback);
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- } else { // more than two channels, each channels has its own control.
- for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) {
- if (isPlayback && snd_mixer_selem_has_playback_channel(elem, channel) ||
- !isPlayback && snd_mixer_selem_has_capture_channel(elem, channel)) {
- if (getControlSlot(portMixer, &portControl)) {
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = CONTROL_TYPE_VOLUME;
- portControl->channel = channel;
- control = createVolumeControl(creator, portControl, elem, isPlayback);
- // We wrap in a compound control to provide the channel name.
- if (control != NULL) {
- /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
- declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
- to take a const char* parameter. */
- control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1);
- }
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- }
- }
- }
- // BALANCE control
- if (isStereo) {
- if (getControlSlot(portMixer, &portControl)) {
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = CONTROL_TYPE_BALANCE;
- portControl->channel = CHANNELS_STEREO;
- /* $$mp: The value for precision is chosen more or less arbitrarily. */
- control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, "");
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- }
- }
- if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) {
- if (getControlSlot(portMixer, &portControl)) {
- type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT;
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = type;
- control = (creator->newBooleanControl)(creator, portControl, type);
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- }
- /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
- declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
- to take a const char* parameter. */
- portName = (char*) snd_mixer_selem_get_name(elem);
- control = (creator->newCompoundControl)(creator, portName, controls, numControls);
- if (control != NULL) {
- (creator->addControl)(creator, control);
- }
- TRACE0("< PORT_GetControls\n");
-}
-
-
-INT32 PORT_GetIntValue(void* controlIDV) {
- PortControl* portControl = (PortControl*) controlIDV;
- int value = 0;
- snd_mixer_selem_channel_id_t channel;
-
- if (portControl != NULL) {
- switch (portControl->channel) {
- case CHANNELS_MONO:
- channel = SND_MIXER_SCHN_MONO;
- break;
-
- case CHANNELS_STEREO:
- channel = SND_MIXER_SCHN_FRONT_LEFT;
- break;
-
- default:
- channel = portControl->channel;
- }
- if (portControl->controlType == CONTROL_TYPE_MUTE ||
- portControl->controlType == CONTROL_TYPE_SELECT) {
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_get_playback_switch(portControl->elem, channel, &value);
- } else {
- snd_mixer_selem_get_capture_switch(portControl->elem, channel, &value);
- }
- if (portControl->controlType == CONTROL_TYPE_MUTE) {
- value = ! value;
- }
- } else {
- ERROR1("PORT_GetIntValue(): inappropriate control type: %s\n",
- portControl->controlType);
- }
- }
- return (INT32) value;
-}
-
-
-void PORT_SetIntValue(void* controlIDV, INT32 value) {
- PortControl* portControl = (PortControl*) controlIDV;
- snd_mixer_selem_channel_id_t channel;
-
- if (portControl != NULL) {
- if (portControl->controlType == CONTROL_TYPE_MUTE) {
- value = ! value;
- }
- if (portControl->controlType == CONTROL_TYPE_MUTE ||
- portControl->controlType == CONTROL_TYPE_SELECT) {
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_set_playback_switch_all(portControl->elem, value);
- } else {
- snd_mixer_selem_set_capture_switch_all(portControl->elem, value);
- }
- } else {
- ERROR1("PORT_SetIntValue(): inappropriate control type: %s\n",
- portControl->controlType);
- }
- }
-}
-
-
-static float scaleVolumeValueToNormalized(long value, long min, long max) {
- return (float) (value - min) / getRange(min, max);
-}
-
-
-static long scaleVolumeValueToHardware(float value, long min, long max) {
- return (long)(value * getRange(min, max) + min);
-}
-
-
-float getRealVolume(PortControl* portControl,
- snd_mixer_selem_channel_id_t channel) {
- float fValue;
- long lValue = 0;
- long min = 0;
- long max = 0;
-
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_get_playback_volume_range(portControl->elem,
- &min, &max);
- snd_mixer_selem_get_playback_volume(portControl->elem,
- channel, &lValue);
- } else {
- snd_mixer_selem_get_capture_volume_range(portControl->elem,
- &min, &max);
- snd_mixer_selem_get_capture_volume(portControl->elem,
- channel, &lValue);
- }
- fValue = scaleVolumeValueToNormalized(lValue, min, max);
- return fValue;
-}
-
-
-void setRealVolume(PortControl* portControl,
- snd_mixer_selem_channel_id_t channel, float value) {
- long lValue = 0;
- long min = 0;
- long max = 0;
-
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_get_playback_volume_range(portControl->elem,
- &min, &max);
- lValue = scaleVolumeValueToHardware(value, min, max);
- snd_mixer_selem_set_playback_volume(portControl->elem,
- channel, lValue);
- } else {
- snd_mixer_selem_get_capture_volume_range(portControl->elem,
- &min, &max);
- lValue = scaleVolumeValueToHardware(value, min, max);
- snd_mixer_selem_set_capture_volume(portControl->elem,
- channel, lValue);
- }
-}
-
-
-static float getFakeBalance(PortControl* portControl) {
- float volL, volR;
-
- // pan is the ratio of left and right
- volL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
- volR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
- if (volL > volR) {
- return -1.0f + (volR / volL);
- }
- else if (volR > volL) {
- return 1.0f - (volL / volR);
- }
- return 0.0f;
-}
-
-
-static float getFakeVolume(PortControl* portControl) {
- float valueL;
- float valueR;
- float value;
-
- valueL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
- valueR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
- // volume is the greater value of both
- value = valueL > valueR ? valueL : valueR ;
- return value;
-}
-
-
-/*
- * sets the unsigned values for left and right volume according to
- * the given volume (0...1) and balance (-1..0..+1)
- */
-static void setFakeVolume(PortControl* portControl, float vol, float bal) {
- float volumeLeft;
- float volumeRight;
-
- if (bal < 0.0f) {
- volumeLeft = vol;
- volumeRight = vol * (bal + 1.0f);
- } else {
- volumeLeft = vol * (1.0f - bal);
- volumeRight = vol;
- }
- setRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT, volumeLeft);
- setRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT, volumeRight);
-}
-
-
-float PORT_GetFloatValue(void* controlIDV) {
- PortControl* portControl = (PortControl*) controlIDV;
- float value = 0.0F;
-
- if (portControl != NULL) {
- if (portControl->controlType == CONTROL_TYPE_VOLUME) {
- switch (portControl->channel) {
- case CHANNELS_MONO:
- value = getRealVolume(portControl, SND_MIXER_SCHN_MONO);
- break;
-
- case CHANNELS_STEREO:
- value = getFakeVolume(portControl);
- break;
-
- default:
- value = getRealVolume(portControl, portControl->channel);
- }
- } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
- if (portControl->channel == CHANNELS_STEREO) {
- value = getFakeBalance(portControl);
- } else {
- ERROR0("PORT_GetFloatValue(): Balance only allowed for stereo channels!\n");
- }
- } else {
- ERROR1("PORT_GetFloatValue(): inappropriate control type: %s!\n",
- portControl->controlType);
- }
- }
- return value;
-}
-
-
-void PORT_SetFloatValue(void* controlIDV, float value) {
- PortControl* portControl = (PortControl*) controlIDV;
-
- if (portControl != NULL) {
- if (portControl->controlType == CONTROL_TYPE_VOLUME) {
- switch (portControl->channel) {
- case CHANNELS_MONO:
- setRealVolume(portControl, SND_MIXER_SCHN_MONO, value);
- break;
-
- case CHANNELS_STEREO:
- setFakeVolume(portControl, value, getFakeBalance(portControl));
- break;
-
- default:
- setRealVolume(portControl, portControl->channel, value);
- }
- } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
- if (portControl->channel == CHANNELS_STEREO) {
- setFakeVolume(portControl, getFakeVolume(portControl), value);
- } else {
- ERROR0("PORT_SetFloatValue(): Balance only allowed for stereo channels!\n");
- }
- } else {
- ERROR1("PORT_SetFloatValue(): inappropriate control type: %s!\n",
- portControl->controlType);
- }
- }
-}
-
-
-#endif // USE_PORTS
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2003, 2015, 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_LinuxOS_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
-
-/*
- * Declare library specific JNI_Onload entry if static build
- */
-DEF_STATIC_JNI_OnLoad
-
-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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.h Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2003, 2007, 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_LINUXOS_ALSA_COMMONUTILS_H_INCLUDED
-#define PLATFORM_API_LINUXOS_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_LINUXOS_ALSA_COMMONUTILS_H_INCLUDED
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, 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_LinuxOS_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 linux
- * 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 jre32onlinux64 = -1;
- if (jre32onlinux64 < 0) {
- jre32onlinux64 = 0;
- /* The workaround may be disabled setting "JAVASOUND_ENABLE_MIDIIN"
- * environment variable.
- */
- if (getenv("JAVASOUND_ENABLE_MIDIIN") == NULL) {
- struct utsname u;
- jre32onlinux64 = 0;
- if (uname(&u) == 0) {
- if (strstr(u.machine, "64") != NULL) {
- TRACE0("jre32 on linux64 detected - report no midiIn devices\n");
- jre32onlinux64 = 1;
- }
- }
- }
- }
- if (jre32onlinux64) {
- 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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2003, 2007, 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_LinuxOS_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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,481 +0,0 @@
-/*
- * 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_LinuxOS_ALSA_MidiUtils.h"
-#include "PLATFORM_API_LinuxOS_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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.h Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2003, 2007, 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_LINUXOS_ALSA_MIDIUTILS_H_INCLUDED
-#define PLATFORM_API_LINUXOS_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_LINUXOS_ALSA_MIDIUTILS_H_INCLUDED
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,941 +0,0 @@
-/*
- * Copyright (c) 2002, 2011, 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_LinuxOS_ALSA_PCMUtils.h"
-#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
-#include "DirectAudio.h"
-
-#if USE_DAUDIO == TRUE
-
-// GetPosition method 1: based on how many bytes are passed to the kernel driver
-// + does not need much processor resources
-// - not very exact, "jumps"
-// GetPosition method 2: ask kernel about actual position of playback.
-// - very exact
-// - switch to kernel layer for each call
-// GetPosition method 3: use snd_pcm_avail() call - not yet in official ALSA
-// quick tests on a Pentium 200MMX showed max. 1.5% processor usage
-// for playing back a CD-quality file and printing 20x per second a line
-// on the console with the current time. So I guess performance is not such a
-// factor here.
-//#define GET_POSITION_METHOD1
-#define GET_POSITION_METHOD2
-
-
-// The default time for a period in microseconds.
-// For very small buffers, only 2 periods are used.
-#define DEFAULT_PERIOD_TIME 20000 /* 20ms */
-
-///// implemented functions of DirectAudio.h
-
-INT32 DAUDIO_GetDirectAudioDeviceCount() {
- return (INT32) getAudioDeviceCount();
-}
-
-
-INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* description) {
- ALSA_AudioDeviceDescription adesc;
-
- adesc.index = (int) mixerIndex;
- adesc.strLen = DAUDIO_STRING_LENGTH;
-
- adesc.maxSimultaneousLines = (int*) (&(description->maxSimulLines));
- adesc.deviceID = &(description->deviceID);
- adesc.name = description->name;
- adesc.vendor = description->vendor;
- adesc.description = description->description;
- adesc.version = description->version;
-
- return getAudioDeviceDescriptionByIndex(&adesc);
-}
-
-#define MAX_BIT_INDEX 6
-// returns
-// 6: for anything above 24-bit
-// 5: for 4 bytes sample size, 24-bit
-// 4: for 3 bytes sample size, 24-bit
-// 3: for 3 bytes sample size, 20-bit
-// 2: for 2 bytes sample size, 16-bit
-// 1: for 1 byte sample size, 8-bit
-// 0: for anything else
-int getBitIndex(int sampleSizeInBytes, int significantBits) {
- if (significantBits > 24) return 6;
- if (sampleSizeInBytes == 4 && significantBits == 24) return 5;
- if (sampleSizeInBytes == 3) {
- if (significantBits == 24) return 4;
- if (significantBits == 20) return 3;
- }
- if (sampleSizeInBytes == 2 && significantBits == 16) return 2;
- if (sampleSizeInBytes == 1 && significantBits == 8) return 1;
- return 0;
-}
-
-int getSampleSizeInBytes(int bitIndex, int sampleSizeInBytes) {
- switch(bitIndex) {
- case 1: return 1;
- case 2: return 2;
- case 3: /* fall through */
- case 4: return 3;
- case 5: return 4;
- }
- return sampleSizeInBytes;
-}
-
-int getSignificantBits(int bitIndex, int significantBits) {
- switch(bitIndex) {
- case 1: return 8;
- case 2: return 16;
- case 3: return 20;
- case 4: /* fall through */
- case 5: return 24;
- }
- return significantBits;
-}
-
-void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
- snd_pcm_t* handle;
- snd_pcm_format_mask_t* formatMask;
- snd_pcm_format_t format;
- snd_pcm_hw_params_t* hwParams;
- int handledBits[MAX_BIT_INDEX+1];
-
- int ret;
- int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc;
- int origSampleSizeInBytes, origSignificantBits;
- unsigned int channels, minChannels, maxChannels;
- int rate, bitIndex;
-
- for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE;
- if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) {
- return;
- }
- ret = snd_pcm_format_mask_malloc(&formatMask);
- if (ret != 0) {
- ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret);
- } else {
- ret = snd_pcm_hw_params_malloc(&hwParams);
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
- } else {
- ret = snd_pcm_hw_params_any(handle, hwParams);
- /* snd_pcm_hw_params_any can return a positive value on success too */
- if (ret < 0) {
- ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
- } else {
- /* for the logic following this code, set ret to 0 to indicate success */
- ret = 0;
- }
- }
- snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
- if (ret == 0) {
- ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels);
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret);
- }
- }
- if (ret == 0) {
- ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels);
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret);
- }
- }
-
- // since we queried the hw: device, for many soundcards, it will only
- // report the maximum number of channels (which is the only way to talk
- // to the hw: device). Since we will, however, open the plughw: device
- // when opening the Source/TargetDataLine, we can safely assume that
- // also the channels 1..maxChannels are available.
-#ifdef ALSA_PCM_USE_PLUGHW
- minChannels = 1;
-#endif
- if (ret == 0) {
- // plughw: supports any sample rate
- rate = -1;
- for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
- if (snd_pcm_format_mask_test(formatMask, format)) {
- // format exists
- if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes,
- &origSignificantBits,
- &isSigned, &isBigEndian, &enc)) {
- // now if we use plughw:, we can use any bit size below the
- // natively supported ones. Some ALSA drivers only support the maximum
- // bit size, so we add any sample rates below the reported one.
- // E.g. this iteration reports support for 16-bit.
- // getBitIndex will return 2, so it will add entries for
- // 16-bit (bitIndex=2) and in the next do-while loop iteration,
- // it will decrease bitIndex and will therefore add 8-bit support.
- bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits);
- do {
- if (bitIndex == 0
- || bitIndex == MAX_BIT_INDEX
- || !handledBits[bitIndex]) {
- handledBits[bitIndex] = TRUE;
- sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes);
- significantBits = getSignificantBits(bitIndex, origSignificantBits);
- if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) {
- // avoid too many channels explicitly listed
- // just add -1, min, and max
- DAUDIO_AddAudioFormat(creator, significantBits,
- -1, -1, rate,
- enc, isSigned, isBigEndian);
- DAUDIO_AddAudioFormat(creator, significantBits,
- sampleSizeInBytes * minChannels,
- minChannels, rate,
- enc, isSigned, isBigEndian);
- DAUDIO_AddAudioFormat(creator, significantBits,
- sampleSizeInBytes * maxChannels,
- maxChannels, rate,
- enc, isSigned, isBigEndian);
- } else {
- for (channels = minChannels; channels <= maxChannels; channels++) {
- DAUDIO_AddAudioFormat(creator, significantBits,
- sampleSizeInBytes * channels,
- channels, rate,
- enc, isSigned, isBigEndian);
- }
- }
- }
-#ifndef ALSA_PCM_USE_PLUGHW
- // without plugin, do not add fake formats
- break;
-#endif
- } while (--bitIndex > 0);
- } else {
- TRACE1("could not get format from alsa for format %d\n", format);
- }
- } else {
- //TRACE1("Format %d not supported\n", format);
- }
- } // for loop
- snd_pcm_hw_params_free(hwParams);
- }
- snd_pcm_format_mask_free(formatMask);
- }
- snd_pcm_close(handle);
-}
-
-/** Workaround for cr 7033899, 7030629:
- * dmix plugin doesn't like flush (snd_pcm_drop) when the buffer is empty
- * (just opened, underruned or already flushed).
- * Sometimes it causes PCM falls to -EBADFD error,
- * sometimes causes bufferSize change.
- * To prevent unnecessary flushes AlsaPcmInfo::isRunning & isFlushed are used.
- */
-/* ******* ALSA PCM INFO ******************** */
-typedef struct tag_AlsaPcmInfo {
- snd_pcm_t* handle;
- snd_pcm_hw_params_t* hwParams;
- snd_pcm_sw_params_t* swParams;
- int bufferSizeInBytes;
- int frameSize; // storage size in Bytes
- unsigned int periods;
- snd_pcm_uframes_t periodSize;
- short int isRunning; // see comment above
- short int isFlushed; // see comment above
-#ifdef GET_POSITION_METHOD2
- // to be used exclusively by getBytePosition!
- snd_pcm_status_t* positionStatus;
-#endif
-} AlsaPcmInfo;
-
-
-int setStartThresholdNoCommit(AlsaPcmInfo* info, int useThreshold) {
- int ret;
- int threshold;
-
- if (useThreshold) {
- // start device whenever anything is written to the buffer
- threshold = 1;
- } else {
- // never start the device automatically
- threshold = 2000000000; /* near UINT_MAX */
- }
- ret = snd_pcm_sw_params_set_start_threshold(info->handle, info->swParams, threshold);
- if (ret < 0) {
- ERROR1("Unable to set start threshold mode: %s\n", snd_strerror(ret));
- return FALSE;
- }
- return TRUE;
-}
-
-int setStartThreshold(AlsaPcmInfo* info, int useThreshold) {
- int ret = 0;
-
- if (!setStartThresholdNoCommit(info, useThreshold)) {
- ret = -1;
- }
- if (ret == 0) {
- // commit it
- ret = snd_pcm_sw_params(info->handle, info->swParams);
- if (ret < 0) {
- ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
- }
- }
- return (ret == 0)?TRUE:FALSE;
-}
-
-
-// returns TRUE if successful
-int setHWParams(AlsaPcmInfo* info,
- float sampleRate,
- int channels,
- int bufferSizeInFrames,
- snd_pcm_format_t format) {
- unsigned int rrate, periodTime, periods;
- int ret, dir;
- snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames;
-
- /* choose all parameters */
- ret = snd_pcm_hw_params_any(info->handle, info->hwParams);
- if (ret < 0) {
- ERROR1("Broken configuration: no configurations available: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* set the interleaved read/write format */
- ret = snd_pcm_hw_params_set_access(info->handle, info->hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
- if (ret < 0) {
- ERROR1("SND_PCM_ACCESS_RW_INTERLEAVED access type not available: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* set the sample format */
- ret = snd_pcm_hw_params_set_format(info->handle, info->hwParams, format);
- if (ret < 0) {
- ERROR1("Sample format not available: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* set the count of channels */
- ret = snd_pcm_hw_params_set_channels(info->handle, info->hwParams, channels);
- if (ret < 0) {
- ERROR2("Channels count (%d) not available: %s\n", channels, snd_strerror(ret));
- return FALSE;
- }
- /* set the stream rate */
- rrate = (int) (sampleRate + 0.5f);
- dir = 0;
- ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir);
- if (ret < 0) {
- ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret));
- return FALSE;
- }
- if ((rrate-sampleRate > 2) || (rrate-sampleRate < - 2)) {
- ERROR2("Rate doesn't match (requested %2.2fHz, got %dHz)\n", sampleRate, rrate);
- return FALSE;
- }
- /* set the buffer time */
- ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames);
- if (ret < 0) {
- ERROR2("Unable to set buffer size to %d frames: %s\n",
- (int) alsaBufferSizeInFrames, snd_strerror(ret));
- return FALSE;
- }
- bufferSizeInFrames = (int) alsaBufferSizeInFrames;
- /* set the period time */
- if (bufferSizeInFrames > 1024) {
- dir = 0;
- periodTime = DEFAULT_PERIOD_TIME;
- ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir);
- if (ret < 0) {
- ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret));
- return FALSE;
- }
- } else {
- /* set the period count for very small buffer sizes to 2 */
- dir = 0;
- periods = 2;
- ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir);
- if (ret < 0) {
- ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret));
- return FALSE;
- }
- }
- /* write the parameters to device */
- ret = snd_pcm_hw_params(info->handle, info->hwParams);
- if (ret < 0) {
- ERROR1("Unable to set hw params: %s\n", snd_strerror(ret));
- return FALSE;
- }
- return TRUE;
-}
-
-// returns 1 if successful
-int setSWParams(AlsaPcmInfo* info) {
- int ret;
-
- /* get the current swparams */
- ret = snd_pcm_sw_params_current(info->handle, info->swParams);
- if (ret < 0) {
- ERROR1("Unable to determine current swparams: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* never start the transfer automatically */
- if (!setStartThresholdNoCommit(info, FALSE /* don't use threshold */)) {
- return FALSE;
- }
-
- /* allow the transfer when at least period_size samples can be processed */
- ret = snd_pcm_sw_params_set_avail_min(info->handle, info->swParams, info->periodSize);
- if (ret < 0) {
- ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret));
- return FALSE;
- }
- /* write the parameters to the playback device */
- ret = snd_pcm_sw_params(info->handle, info->swParams);
- if (ret < 0) {
- ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
- return FALSE;
- }
- return TRUE;
-}
-
-static snd_output_t* ALSA_OUTPUT = NULL;
-
-void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
- int encoding, float sampleRate, int sampleSizeInBits,
- int frameSize, int channels,
- int isSigned, int isBigEndian, int bufferSizeInBytes) {
- snd_pcm_format_mask_t* formatMask;
- snd_pcm_format_t format;
- int dir;
- int ret = 0;
- AlsaPcmInfo* info = NULL;
- /* snd_pcm_uframes_t is 64 bit on 64-bit systems */
- snd_pcm_uframes_t alsaBufferSizeInFrames = 0;
-
-
- TRACE0("> DAUDIO_Open\n");
-#ifdef USE_TRACE
- // for using ALSA debug dump methods
- if (ALSA_OUTPUT == NULL) {
- snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
- }
-#endif
- if (channels <= 0) {
- ERROR1("ERROR: Invalid number of channels=%d!\n", channels);
- return NULL;
- }
- info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
- if (!info) {
- ERROR0("Out of memory\n");
- return NULL;
- }
- memset(info, 0, sizeof(AlsaPcmInfo));
- // initial values are: stopped, flushed
- info->isRunning = 0;
- info->isFlushed = 1;
-
- ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
- if (ret == 0) {
- // set to blocking mode
- snd_pcm_nonblock(info->handle, 0);
- ret = snd_pcm_hw_params_malloc(&(info->hwParams));
- if (ret != 0) {
- ERROR1(" snd_pcm_hw_params_malloc returned error %d\n", ret);
- } else {
- ret = -1;
- if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
- isSigned, isBigEndian, encoding)) {
- if (setHWParams(info,
- sampleRate,
- channels,
- bufferSizeInBytes / frameSize,
- format)) {
- info->frameSize = frameSize;
- ret = snd_pcm_hw_params_get_period_size(info->hwParams, &info->periodSize, &dir);
- if (ret < 0) {
- ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
- }
- snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
- snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
- info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
- TRACE3(" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
- (int) info->periodSize, info->periods, info->bufferSizeInBytes);
- }
- }
- }
- if (ret == 0) {
- // set software parameters
- ret = snd_pcm_sw_params_malloc(&(info->swParams));
- if (ret != 0) {
- ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
- } else {
- if (!setSWParams(info)) {
- ret = -1;
- }
- }
- }
- if (ret == 0) {
- // prepare device
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
- }
- }
-
-#ifdef GET_POSITION_METHOD2
- if (ret == 0) {
- ret = snd_pcm_status_malloc(&(info->positionStatus));
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
- }
- }
-#endif
- }
- if (ret != 0) {
- DAUDIO_Close((void*) info, isSource);
- info = NULL;
- } else {
- // set to non-blocking mode
- snd_pcm_nonblock(info->handle, 1);
- TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
- (void*) info->handle);
- }
- return (void*) info;
-}
-
-#ifdef USE_TRACE
-void printState(snd_pcm_state_t state) {
- if (state == SND_PCM_STATE_OPEN) {
- TRACE0("State: SND_PCM_STATE_OPEN\n");
- }
- else if (state == SND_PCM_STATE_SETUP) {
- TRACE0("State: SND_PCM_STATE_SETUP\n");
- }
- else if (state == SND_PCM_STATE_PREPARED) {
- TRACE0("State: SND_PCM_STATE_PREPARED\n");
- }
- else if (state == SND_PCM_STATE_RUNNING) {
- TRACE0("State: SND_PCM_STATE_RUNNING\n");
- }
- else if (state == SND_PCM_STATE_XRUN) {
- TRACE0("State: SND_PCM_STATE_XRUN\n");
- }
- else if (state == SND_PCM_STATE_DRAINING) {
- TRACE0("State: SND_PCM_STATE_DRAINING\n");
- }
- else if (state == SND_PCM_STATE_PAUSED) {
- TRACE0("State: SND_PCM_STATE_PAUSED\n");
- }
- else if (state == SND_PCM_STATE_SUSPENDED) {
- TRACE0("State: SND_PCM_STATE_SUSPENDED\n");
- }
-}
-#endif
-
-int DAUDIO_Start(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
- snd_pcm_state_t state;
-
- TRACE0("> DAUDIO_Start\n");
- // set to blocking mode
- snd_pcm_nonblock(info->handle, 0);
- // set start mode so that it always starts as soon as data is there
- setStartThreshold(info, TRUE /* use threshold */);
- state = snd_pcm_state(info->handle);
- if (state == SND_PCM_STATE_PAUSED) {
- // in case it was stopped previously
- TRACE0(" Un-pausing...\n");
- ret = snd_pcm_pause(info->handle, FALSE);
- if (ret != 0) {
- ERROR2(" NOTE: error in snd_pcm_pause:%d: %s\n", ret, snd_strerror(ret));
- }
- }
- if (state == SND_PCM_STATE_SUSPENDED) {
- TRACE0(" Resuming...\n");
- ret = snd_pcm_resume(info->handle);
- if (ret < 0) {
- if ((ret != -EAGAIN) && (ret != -ENOSYS)) {
- ERROR2(" ERROR: error in snd_pcm_resume:%d: %s\n", ret, snd_strerror(ret));
- }
- }
- }
- if (state == SND_PCM_STATE_SETUP) {
- TRACE0("need to call prepare again...\n");
- // prepare device
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
- }
- }
- // in case there is still data in the buffers
- ret = snd_pcm_start(info->handle);
- if (ret != 0) {
- if (ret != -EPIPE) {
- ERROR2(" NOTE: error in snd_pcm_start: %d: %s\n", ret, snd_strerror(ret));
- }
- }
- // set to non-blocking mode
- ret = snd_pcm_nonblock(info->handle, 1);
- if (ret != 0) {
- ERROR1(" ERROR in snd_pcm_nonblock: %s\n", snd_strerror(ret));
- }
- state = snd_pcm_state(info->handle);
-#ifdef USE_TRACE
- printState(state);
-#endif
- ret = (state == SND_PCM_STATE_PREPARED)
- || (state == SND_PCM_STATE_RUNNING)
- || (state == SND_PCM_STATE_XRUN)
- || (state == SND_PCM_STATE_SUSPENDED);
- if (ret) {
- info->isRunning = 1;
- // source line should keep isFlushed value until Write() is called;
- // for target data line reset it right now.
- if (!isSource) {
- info->isFlushed = 0;
- }
- }
- TRACE1("< DAUDIO_Start %s\n", ret?"success":"error");
- return ret?TRUE:FALSE;
-}
-
-int DAUDIO_Stop(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
-
- TRACE0("> DAUDIO_Stop\n");
- // set to blocking mode
- snd_pcm_nonblock(info->handle, 0);
- setStartThreshold(info, FALSE /* don't use threshold */); // device will not start after buffer xrun
- ret = snd_pcm_pause(info->handle, 1);
- // set to non-blocking mode
- snd_pcm_nonblock(info->handle, 1);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_pause: %s\n", snd_strerror(ret));
- return FALSE;
- }
- info->isRunning = 0;
- TRACE0("< DAUDIO_Stop success\n");
- return TRUE;
-}
-
-void DAUDIO_Close(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
-
- TRACE0("DAUDIO_Close\n");
- if (info != NULL) {
- if (info->handle != NULL) {
- snd_pcm_close(info->handle);
- }
- if (info->hwParams) {
- snd_pcm_hw_params_free(info->hwParams);
- }
- if (info->swParams) {
- snd_pcm_sw_params_free(info->swParams);
- }
-#ifdef GET_POSITION_METHOD2
- if (info->positionStatus) {
- snd_pcm_status_free(info->positionStatus);
- }
-#endif
- free(info);
- }
-}
-
-/*
- * Underrun and suspend recovery
- * returns
- * 0: exit native and return 0
- * 1: try again to write/read
- * -1: error - exit native with return value -1
- */
-int xrun_recovery(AlsaPcmInfo* info, int err) {
- int ret;
-
- if (err == -EPIPE) { /* underrun / overflow */
- TRACE0("xrun_recovery: underrun/overflow.\n");
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
- return -1;
- }
- return 1;
- } else if (err == -ESTRPIPE) {
- TRACE0("xrun_recovery: suspended.\n");
- ret = snd_pcm_resume(info->handle);
- if (ret < 0) {
- if (ret == -EAGAIN) {
- return 0; /* wait until the suspend flag is released */
- }
- return -1;
- }
- ret = snd_pcm_prepare(info->handle);
- if (ret < 0) {
- ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
- return -1;
- }
- return 1;
- } else if (err == -EAGAIN) {
- TRACE0("xrun_recovery: EAGAIN try again flag.\n");
- return 0;
- }
-
- TRACE2("xrun_recovery: unexpected error %d: %s\n", err, snd_strerror(err));
- return -1;
-}
-
-// returns -1 on error
-int DAUDIO_Write(void* id, char* data, int byteSize) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret, count;
- snd_pcm_sframes_t frameSize, writtenFrames;
-
- TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
-
- /* sanity */
- if (byteSize <= 0 || info->frameSize <= 0) {
- ERROR2(" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
- (int) byteSize, (int) info->frameSize);
- TRACE0("< DAUDIO_Write returning -1\n");
- return -1;
- }
-
- count = 2; // maximum number of trials to recover from underrun
- //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
- frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
- do {
- writtenFrames = snd_pcm_writei(info->handle, (const void*) data, (snd_pcm_uframes_t) frameSize);
-
- if (writtenFrames < 0) {
- ret = xrun_recovery(info, (int) writtenFrames);
- if (ret <= 0) {
- TRACE1("DAUDIO_Write: xrun recovery returned %d -> return.\n", ret);
- return ret;
- }
- if (count-- <= 0) {
- ERROR0("DAUDIO_Write: too many attempts to recover from xrun/suspend\n");
- return -1;
- }
- } else {
- break;
- }
- } while (TRUE);
- //ret = snd_pcm_frames_to_bytes(info->handle, writtenFrames);
-
- if (writtenFrames > 0) {
- // reset "flushed" flag
- info->isFlushed = 0;
- }
-
- ret = (int) (writtenFrames * info->frameSize);
- TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
- return ret;
-}
-
-// returns -1 on error
-int DAUDIO_Read(void* id, char* data, int byteSize) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret, count;
- snd_pcm_sframes_t frameSize, readFrames;
-
- TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
- /*TRACE3(" info=%p, data=%p, byteSize=%d\n",
- (void*) info, (void*) data, (int) byteSize);
- TRACE2(" info->frameSize=%d, info->handle=%p\n",
- (int) info->frameSize, (void*) info->handle);
- */
- /* sanity */
- if (byteSize <= 0 || info->frameSize <= 0) {
- ERROR2(" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
- (int) byteSize, (int) info->frameSize);
- TRACE0("< DAUDIO_Read returning -1\n");
- return -1;
- }
- if (!info->isRunning && info->isFlushed) {
- // PCM has nothing to read
- return 0;
- }
-
- count = 2; // maximum number of trials to recover from error
- //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
- frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
- do {
- readFrames = snd_pcm_readi(info->handle, (void*) data, (snd_pcm_uframes_t) frameSize);
- if (readFrames < 0) {
- ret = xrun_recovery(info, (int) readFrames);
- if (ret <= 0) {
- TRACE1("DAUDIO_Read: xrun recovery returned %d -> return.\n", ret);
- return ret;
- }
- if (count-- <= 0) {
- ERROR0("DAUDIO_Read: too many attempts to recover from xrun/suspend\n");
- return -1;
- }
- } else {
- break;
- }
- } while (TRUE);
- //ret = snd_pcm_frames_to_bytes(info->handle, readFrames);
- ret = (int) (readFrames * info->frameSize);
- TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
- return ret;
-}
-
-
-int DAUDIO_GetBufferSize(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
-
- return info->bufferSizeInBytes;
-}
-
-int DAUDIO_StillDraining(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- snd_pcm_state_t state;
-
- state = snd_pcm_state(info->handle);
- //printState(state);
- //TRACE1("Still draining: %s\n", (state != SND_PCM_STATE_XRUN)?"TRUE":"FALSE");
- return (state == SND_PCM_STATE_RUNNING)?TRUE:FALSE;
-}
-
-
-int DAUDIO_Flush(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
-
- TRACE0("DAUDIO_Flush\n");
-
- if (info->isFlushed) {
- // nothing to drop
- return 1;
- }
-
- ret = snd_pcm_drop(info->handle);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_drop: %s\n", snd_strerror(ret));
- return FALSE;
- }
-
- info->isFlushed = 1;
- if (info->isRunning) {
- ret = DAUDIO_Start(id, isSource);
- }
- return ret;
-}
-
-int DAUDIO_GetAvailable(void* id, int isSource) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- snd_pcm_sframes_t availableInFrames;
- snd_pcm_state_t state;
- int ret;
-
- state = snd_pcm_state(info->handle);
- if (info->isFlushed || state == SND_PCM_STATE_XRUN) {
- // if in xrun state then we have the entire buffer available,
- // not 0 as alsa reports
- ret = info->bufferSizeInBytes;
- } else {
- availableInFrames = snd_pcm_avail_update(info->handle);
- if (availableInFrames < 0) {
- ret = 0;
- } else {
- //ret = snd_pcm_frames_to_bytes(info->handle, availableInFrames);
- ret = (int) (availableInFrames * info->frameSize);
- }
- }
- TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
- return ret;
-}
-
-INT64 estimatePositionFromAvail(AlsaPcmInfo* info, int isSource, INT64 javaBytePos, int availInBytes) {
- // estimate the current position with the buffer size and
- // the available bytes to read or write in the buffer.
- // not an elegant solution - bytePos will stop on xruns,
- // and in race conditions it may jump backwards
- // Advantage is that it is indeed based on the samples that go through
- // the system (rather than time-based methods)
- if (isSource) {
- // javaBytePos is the position that is reached when the current
- // buffer is played completely
- return (INT64) (javaBytePos - info->bufferSizeInBytes + availInBytes);
- } else {
- // javaBytePos is the position that was when the current buffer was empty
- return (INT64) (javaBytePos + availInBytes);
- }
-}
-
-INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
- AlsaPcmInfo* info = (AlsaPcmInfo*) id;
- int ret;
- INT64 result = javaBytePos;
- snd_pcm_state_t state;
- state = snd_pcm_state(info->handle);
-
- if (!info->isFlushed && state != SND_PCM_STATE_XRUN) {
-#ifdef GET_POSITION_METHOD2
- snd_timestamp_t* ts;
- snd_pcm_uframes_t framesAvail;
-
- // note: slight race condition if this is called simultaneously from 2 threads
- ret = snd_pcm_status(info->handle, info->positionStatus);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_status: %s\n", snd_strerror(ret));
- result = javaBytePos;
- } else {
- // calculate from time value, or from available bytes
- framesAvail = snd_pcm_status_get_avail(info->positionStatus);
- result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
- }
-#endif
-#ifdef GET_POSITION_METHOD3
- snd_pcm_uframes_t framesAvail;
- ret = snd_pcm_avail(info->handle, &framesAvail);
- if (ret != 0) {
- ERROR1("ERROR in snd_pcm_avail: %s\n", snd_strerror(ret));
- result = javaBytePos;
- } else {
- result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
- }
-#endif
-#ifdef GET_POSITION_METHOD1
- result = estimatePositionFromAvail(info, isSource, javaBytePos, DAUDIO_GetAvailable(id, isSource));
-#endif
- }
- //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
- return result;
-}
-
-
-
-void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
- /* save to ignore, since GetBytePosition
- * takes the javaBytePos param into account
- */
-}
-
-int DAUDIO_RequiresServicing(void* id, int isSource) {
- // never need servicing on Linux
- return FALSE;
-}
-
-void DAUDIO_Service(void* id, int isSource) {
- // never need servicing on Linux
-}
-
-
-#endif // USE_DAUDIO
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,292 +0,0 @@
-/*
- * 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_LinuxOS_ALSA_PCMUtils.h"
-#include "PLATFORM_API_LinuxOS_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 */
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, 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_LINUXOS_ALSA_PCMUTILS_H_INCLUDED
-#define PLATFORM_API_LINUXOS_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_LINUXOS_ALSA_PCMUTILS_H_INCLUDED
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,724 +0,0 @@
-/*
- * Copyright (c) 2003, 2016, 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 "Ports.h"
-#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
-#include <alsa/asoundlib.h>
-
-#if USE_PORTS == TRUE
-
-#define MAX_ELEMS (300)
-#define MAX_CONTROLS (MAX_ELEMS * 4)
-
-#define CHANNELS_MONO (SND_MIXER_SCHN_LAST + 1)
-#define CHANNELS_STEREO (SND_MIXER_SCHN_LAST + 2)
-
-typedef struct {
- snd_mixer_elem_t* elem;
- INT32 portType; /* one of PORT_XXX_xx */
- char* controlType; /* one of CONTROL_TYPE_xx */
- /* Values: either SND_MIXER_SCHN_FRONT_xx, CHANNELS_MONO or CHANNELS_STEREO.
- For SND_MIXER_SCHN_FRONT_xx, exactly this channel is set/retrieved directly.
- For CHANNELS_MONO, ALSA channel SND_MIXER_SCHN_MONO is set/retrieved directly.
- For CHANNELS_STEREO, ALSA channels SND_MIXER_SCHN_FRONT_LEFT and SND_MIXER_SCHN_FRONT_RIGHT
- are set after a calculation that takes balance into account. Retrieved? Average of both
- channels? (Using a cached value is not a good idea since the value in the HW may have been
- altered.) */
- INT32 channel;
-} PortControl;
-
-
-typedef struct tag_PortMixer {
- snd_mixer_t* mixer_handle;
- /* Number of array elements used in elems and types. */
- int numElems;
- snd_mixer_elem_t** elems;
- /* Array of port types (PORT_SRC_UNKNOWN etc.). Indices are the same as in elems. */
- INT32* types;
- /* Number of array elements used in controls. */
- int numControls;
- PortControl* controls;
-} PortMixer;
-
-
-///// implemented functions of Ports.h
-
-INT32 PORT_GetPortMixerCount() {
- INT32 mixerCount;
- int card;
- char devname[16];
- int err;
- snd_ctl_t *handle;
- snd_ctl_card_info_t* info;
-
- TRACE0("> PORT_GetPortMixerCount\n");
-
- initAlsaSupport();
-
- snd_ctl_card_info_malloc(&info);
- card = -1;
- mixerCount = 0;
- if (snd_card_next(&card) >= 0) {
- while (card >= 0) {
- sprintf(devname, ALSA_HARDWARE_CARD, card);
- TRACE1("PORT_GetPortMixerCount: Opening alsa device \"%s\"...\n", devname);
- err = snd_ctl_open(&handle, devname, 0);
- if (err < 0) {
- ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
- } else {
- mixerCount++;
- snd_ctl_close(handle);
- }
- if (snd_card_next(&card) < 0) {
- break;
- }
- }
- }
- snd_ctl_card_info_free(info);
- TRACE0("< PORT_GetPortMixerCount\n");
- return mixerCount;
-}
-
-
-INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
- snd_ctl_t* handle;
- snd_ctl_card_info_t* card_info;
- char devname[16];
- int err;
- char buffer[100];
-
- TRACE0("> PORT_GetPortMixerDescription\n");
- snd_ctl_card_info_malloc(&card_info);
-
- sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
- TRACE1("Opening alsa device \"%s\"...\n", devname);
- err = snd_ctl_open(&handle, devname, 0);
- if (err < 0) {
- ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
- return FALSE;
- }
- err = snd_ctl_card_info(handle, card_info);
- if (err < 0) {
- ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
- }
- strncpy(description->name, snd_ctl_card_info_get_id(card_info), PORT_STRING_LENGTH - 1);
- sprintf(buffer, " [%s]", devname);
- strncat(description->name, buffer, PORT_STRING_LENGTH - 1 - strlen(description->name));
- strncpy(description->vendor, "ALSA (http://www.alsa-project.org)", PORT_STRING_LENGTH - 1);
- strncpy(description->description, snd_ctl_card_info_get_name(card_info), PORT_STRING_LENGTH - 1);
- strncat(description->description, ", ", PORT_STRING_LENGTH - 1 - strlen(description->description));
- strncat(description->description, snd_ctl_card_info_get_mixername(card_info), PORT_STRING_LENGTH - 1 - strlen(description->description));
- getALSAVersion(description->version, PORT_STRING_LENGTH - 1);
-
- snd_ctl_close(handle);
- snd_ctl_card_info_free(card_info);
- TRACE0("< PORT_GetPortMixerDescription\n");
- return TRUE;
-}
-
-
-void* PORT_Open(INT32 mixerIndex) {
- char devname[16];
- snd_mixer_t* mixer_handle;
- int err;
- PortMixer* handle;
-
- TRACE0("> PORT_Open\n");
- sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
- if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
- ERROR2("Mixer %s open error: %s", devname, snd_strerror(err));
- return NULL;
- }
- if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) {
- ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err));
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) {
- ERROR1("Mixer register error: %s", snd_strerror(err));
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- err = snd_mixer_load(mixer_handle);
- if (err < 0) {
- ERROR2("Mixer %s load error: %s", devname, snd_strerror(err));
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- handle = (PortMixer*) calloc(1, sizeof(PortMixer));
- if (handle == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- return NULL;
- }
- handle->numElems = 0;
- handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*));
- if (handle->elems == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- free(handle);
- return NULL;
- }
- handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32));
- if (handle->types == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- free(handle->elems);
- free(handle);
- return NULL;
- }
- handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl));
- if (handle->controls == NULL) {
- ERROR0("malloc() failed.");
- snd_mixer_close(mixer_handle);
- free(handle->elems);
- free(handle->types);
- free(handle);
- return NULL;
- }
- handle->mixer_handle = mixer_handle;
- // necessary to initialize data structures
- PORT_GetPortCount(handle);
- TRACE0("< PORT_Open\n");
- return handle;
-}
-
-
-void PORT_Close(void* id) {
- TRACE0("> PORT_Close\n");
- if (id != NULL) {
- PortMixer* handle = (PortMixer*) id;
- if (handle->mixer_handle != NULL) {
- snd_mixer_close(handle->mixer_handle);
- }
- if (handle->elems != NULL) {
- free(handle->elems);
- }
- if (handle->types != NULL) {
- free(handle->types);
- }
- if (handle->controls != NULL) {
- free(handle->controls);
- }
- free(handle);
- }
- TRACE0("< PORT_Close\n");
-}
-
-
-
-INT32 PORT_GetPortCount(void* id) {
- PortMixer* portMixer;
- snd_mixer_elem_t *elem;
-
- TRACE0("> PORT_GetPortCount\n");
- if (id == NULL) {
- // $$mp: Should become a descriptive error code (invalid handle).
- return -1;
- }
- portMixer = (PortMixer*) id;
- if (portMixer->numElems == 0) {
- for (elem = snd_mixer_first_elem(portMixer->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
- if (!snd_mixer_selem_is_active(elem))
- continue;
- TRACE2("Simple mixer control '%s',%i\n",
- snd_mixer_selem_get_name(elem),
- snd_mixer_selem_get_index(elem));
- if (snd_mixer_selem_has_playback_volume(elem)) {
- portMixer->elems[portMixer->numElems] = elem;
- portMixer->types[portMixer->numElems] = PORT_DST_UNKNOWN;
- portMixer->numElems++;
- }
- // to prevent buffer overflow
- if (portMixer->numElems >= MAX_ELEMS) {
- break;
- }
- /* If an element has both playback an capture volume, it is put into the arrays
- twice. */
- if (snd_mixer_selem_has_capture_volume(elem)) {
- portMixer->elems[portMixer->numElems] = elem;
- portMixer->types[portMixer->numElems] = PORT_SRC_UNKNOWN;
- portMixer->numElems++;
- }
- // to prevent buffer overflow
- if (portMixer->numElems >= MAX_ELEMS) {
- break;
- }
- }
- }
- TRACE0("< PORT_GetPortCount\n");
- return portMixer->numElems;
-}
-
-
-INT32 PORT_GetPortType(void* id, INT32 portIndex) {
- PortMixer* portMixer;
- INT32 type;
- TRACE0("> PORT_GetPortType\n");
- if (id == NULL) {
- // $$mp: Should become a descriptive error code (invalid handle).
- return -1;
- }
- portMixer = (PortMixer*) id;
- if (portIndex < 0 || portIndex >= portMixer->numElems) {
- // $$mp: Should become a descriptive error code (index out of bounds).
- return -1;
- }
- type = portMixer->types[portIndex];
- TRACE0("< PORT_GetPortType\n");
- return type;
-}
-
-
-INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
- PortMixer* portMixer;
- const char* nam;
-
- TRACE0("> PORT_GetPortName\n");
- if (id == NULL) {
- // $$mp: Should become a descriptive error code (invalid handle).
- return -1;
- }
- portMixer = (PortMixer*) id;
- if (portIndex < 0 || portIndex >= portMixer->numElems) {
- // $$mp: Should become a descriptive error code (index out of bounds).
- return -1;
- }
- nam = snd_mixer_selem_get_name(portMixer->elems[portIndex]);
- strncpy(name, nam, len - 1);
- name[len - 1] = 0;
- TRACE0("< PORT_GetPortName\n");
- return TRUE;
-}
-
-
-static int isPlaybackFunction(INT32 portType) {
- return (portType & PORT_DST_MASK);
-}
-
-
-/* Sets portControl to a pointer to the next free array element in the PortControl (pointer)
- array of the passed portMixer. Returns TRUE if successful. May return FALSE if there is no
- free slot. In this case, portControl is not altered */
-static int getControlSlot(PortMixer* portMixer, PortControl** portControl) {
- if (portMixer->numControls >= MAX_CONTROLS) {
- return FALSE;
- } else {
- *portControl = &(portMixer->controls[portMixer->numControls]);
- portMixer->numControls++;
- return TRUE;
- }
-}
-
-
-/* Protect against illegal min-max values, preventing divisions by zero.
- */
-inline static long getRange(long min, long max) {
- if (max > min) {
- return max - min;
- } else {
- return 1;
- }
-}
-
-
-/* Idea: we may specify that if unit is an empty string, the values are linear and if unit is "dB",
- the values are logarithmic.
-*/
-static void* createVolumeControl(PortControlCreator* creator,
- PortControl* portControl,
- snd_mixer_elem_t* elem, int isPlayback) {
- void* control;
- float precision;
- long min, max;
-
- if (isPlayback) {
- snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
- } else {
- snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
- }
- /* $$mp: The volume values retrieved with the ALSA API are strongly supposed to be logarithmic.
- So the following calculation is wrong. However, there is no correct calculation, since
- for equal-distant logarithmic steps, the precision expressed in linear varies over the
- scale. */
- precision = 1.0F / getRange(min, max);
- control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_VOLUME, 0.0F, +1.0F, precision, "");
- return control;
-}
-
-
-void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
- PortMixer* portMixer;
- snd_mixer_elem_t* elem;
- void* control;
- PortControl* portControl;
- void* controls[10];
- int numControls;
- char* portName;
- int isPlayback = 0;
- int isMono;
- int isStereo;
- char* type;
- snd_mixer_selem_channel_id_t channel;
- memset(controls, 0, sizeof(controls));
-
- TRACE0("> PORT_GetControls\n");
- if (id == NULL) {
- ERROR0("Invalid handle!");
- // $$mp: an error code should be returned.
- return;
- }
- portMixer = (PortMixer*) id;
- if (portIndex < 0 || portIndex >= portMixer->numElems) {
- ERROR0("Port index out of range!");
- // $$mp: an error code should be returned.
- return;
- }
- numControls = 0;
- elem = portMixer->elems[portIndex];
- if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) {
- /* Since we've split/duplicated elements with both playback and capture on the recovery
- of elements, we now can assume that we handle only to deal with either playback or
- capture. */
- isPlayback = isPlaybackFunction(portMixer->types[portIndex]);
- isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) ||
- (!isPlayback && snd_mixer_selem_is_capture_mono(elem));
- isStereo = (isPlayback &&
- snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
- snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) ||
- (!isPlayback &&
- snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
- snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT));
- // single volume control
- if (isMono || isStereo) {
- if (getControlSlot(portMixer, &portControl)) {
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = CONTROL_TYPE_VOLUME;
- if (isMono) {
- portControl->channel = CHANNELS_MONO;
- } else {
- portControl->channel = CHANNELS_STEREO;
- }
- control = createVolumeControl(creator, portControl, elem, isPlayback);
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- } else { // more than two channels, each channels has its own control.
- for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) {
- if ((isPlayback && snd_mixer_selem_has_playback_channel(elem, channel)) ||
- (!isPlayback && snd_mixer_selem_has_capture_channel(elem, channel))) {
- if (getControlSlot(portMixer, &portControl)) {
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = CONTROL_TYPE_VOLUME;
- portControl->channel = channel;
- control = createVolumeControl(creator, portControl, elem, isPlayback);
- // We wrap in a compound control to provide the channel name.
- if (control != NULL) {
- /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
- declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
- to take a const char* parameter. */
- control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1);
- }
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- }
- }
- }
- // BALANCE control
- if (isStereo) {
- if (getControlSlot(portMixer, &portControl)) {
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = CONTROL_TYPE_BALANCE;
- portControl->channel = CHANNELS_STEREO;
- /* $$mp: The value for precision is chosen more or less arbitrarily. */
- control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, "");
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- }
- }
- if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) {
- if (getControlSlot(portMixer, &portControl)) {
- type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT;
- portControl->elem = elem;
- portControl->portType = portMixer->types[portIndex];
- portControl->controlType = type;
- control = (creator->newBooleanControl)(creator, portControl, type);
- if (control != NULL) {
- controls[numControls++] = control;
- }
- }
- }
- /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
- declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
- to take a const char* parameter. */
- portName = (char*) snd_mixer_selem_get_name(elem);
- control = (creator->newCompoundControl)(creator, portName, controls, numControls);
- if (control != NULL) {
- (creator->addControl)(creator, control);
- }
- TRACE0("< PORT_GetControls\n");
-}
-
-
-INT32 PORT_GetIntValue(void* controlIDV) {
- PortControl* portControl = (PortControl*) controlIDV;
- int value = 0;
- snd_mixer_selem_channel_id_t channel;
-
- if (portControl != NULL) {
- switch (portControl->channel) {
- case CHANNELS_MONO:
- channel = SND_MIXER_SCHN_MONO;
- break;
-
- case CHANNELS_STEREO:
- channel = SND_MIXER_SCHN_FRONT_LEFT;
- break;
-
- default:
- channel = portControl->channel;
- }
- if (portControl->controlType == CONTROL_TYPE_MUTE ||
- portControl->controlType == CONTROL_TYPE_SELECT) {
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_get_playback_switch(portControl->elem, channel, &value);
- } else {
- snd_mixer_selem_get_capture_switch(portControl->elem, channel, &value);
- }
- if (portControl->controlType == CONTROL_TYPE_MUTE) {
- value = ! value;
- }
- } else {
- ERROR1("PORT_GetIntValue(): inappropriate control type: %s\n",
- portControl->controlType);
- }
- }
- return (INT32) value;
-}
-
-
-void PORT_SetIntValue(void* controlIDV, INT32 value) {
- PortControl* portControl = (PortControl*) controlIDV;
- snd_mixer_selem_channel_id_t channel;
-
- if (portControl != NULL) {
- if (portControl->controlType == CONTROL_TYPE_MUTE) {
- value = ! value;
- }
- if (portControl->controlType == CONTROL_TYPE_MUTE ||
- portControl->controlType == CONTROL_TYPE_SELECT) {
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_set_playback_switch_all(portControl->elem, value);
- } else {
- snd_mixer_selem_set_capture_switch_all(portControl->elem, value);
- }
- } else {
- ERROR1("PORT_SetIntValue(): inappropriate control type: %s\n",
- portControl->controlType);
- }
- }
-}
-
-
-static float scaleVolumeValueToNormalized(long value, long min, long max) {
- return (float) (value - min) / getRange(min, max);
-}
-
-
-static long scaleVolumeValueToHardware(float value, long min, long max) {
- return (long)(value * getRange(min, max) + min);
-}
-
-
-float getRealVolume(PortControl* portControl,
- snd_mixer_selem_channel_id_t channel) {
- float fValue;
- long lValue = 0;
- long min = 0;
- long max = 0;
-
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_get_playback_volume_range(portControl->elem,
- &min, &max);
- snd_mixer_selem_get_playback_volume(portControl->elem,
- channel, &lValue);
- } else {
- snd_mixer_selem_get_capture_volume_range(portControl->elem,
- &min, &max);
- snd_mixer_selem_get_capture_volume(portControl->elem,
- channel, &lValue);
- }
- fValue = scaleVolumeValueToNormalized(lValue, min, max);
- return fValue;
-}
-
-
-void setRealVolume(PortControl* portControl,
- snd_mixer_selem_channel_id_t channel, float value) {
- long lValue = 0;
- long min = 0;
- long max = 0;
-
- if (isPlaybackFunction(portControl->portType)) {
- snd_mixer_selem_get_playback_volume_range(portControl->elem,
- &min, &max);
- lValue = scaleVolumeValueToHardware(value, min, max);
- snd_mixer_selem_set_playback_volume(portControl->elem,
- channel, lValue);
- } else {
- snd_mixer_selem_get_capture_volume_range(portControl->elem,
- &min, &max);
- lValue = scaleVolumeValueToHardware(value, min, max);
- snd_mixer_selem_set_capture_volume(portControl->elem,
- channel, lValue);
- }
-}
-
-
-static float getFakeBalance(PortControl* portControl) {
- float volL, volR;
-
- // pan is the ratio of left and right
- volL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
- volR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
- if (volL > volR) {
- return -1.0f + (volR / volL);
- }
- else if (volR > volL) {
- return 1.0f - (volL / volR);
- }
- return 0.0f;
-}
-
-
-static float getFakeVolume(PortControl* portControl) {
- float valueL;
- float valueR;
- float value;
-
- valueL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
- valueR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
- // volume is the greater value of both
- value = valueL > valueR ? valueL : valueR ;
- return value;
-}
-
-
-/*
- * sets the unsigned values for left and right volume according to
- * the given volume (0...1) and balance (-1..0..+1)
- */
-static void setFakeVolume(PortControl* portControl, float vol, float bal) {
- float volumeLeft;
- float volumeRight;
-
- if (bal < 0.0f) {
- volumeLeft = vol;
- volumeRight = vol * (bal + 1.0f);
- } else {
- volumeLeft = vol * (1.0f - bal);
- volumeRight = vol;
- }
- setRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT, volumeLeft);
- setRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT, volumeRight);
-}
-
-
-float PORT_GetFloatValue(void* controlIDV) {
- PortControl* portControl = (PortControl*) controlIDV;
- float value = 0.0F;
-
- if (portControl != NULL) {
- if (portControl->controlType == CONTROL_TYPE_VOLUME) {
- switch (portControl->channel) {
- case CHANNELS_MONO:
- value = getRealVolume(portControl, SND_MIXER_SCHN_MONO);
- break;
-
- case CHANNELS_STEREO:
- value = getFakeVolume(portControl);
- break;
-
- default:
- value = getRealVolume(portControl, portControl->channel);
- }
- } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
- if (portControl->channel == CHANNELS_STEREO) {
- value = getFakeBalance(portControl);
- } else {
- ERROR0("PORT_GetFloatValue(): Balance only allowed for stereo channels!\n");
- }
- } else {
- ERROR1("PORT_GetFloatValue(): inappropriate control type: %s!\n",
- portControl->controlType);
- }
- }
- return value;
-}
-
-
-void PORT_SetFloatValue(void* controlIDV, float value) {
- PortControl* portControl = (PortControl*) controlIDV;
-
- if (portControl != NULL) {
- if (portControl->controlType == CONTROL_TYPE_VOLUME) {
- switch (portControl->channel) {
- case CHANNELS_MONO:
- setRealVolume(portControl, SND_MIXER_SCHN_MONO, value);
- break;
-
- case CHANNELS_STEREO:
- setFakeVolume(portControl, value, getFakeBalance(portControl));
- break;
-
- default:
- setRealVolume(portControl, portControl->channel, value);
- }
- } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
- if (portControl->channel == CHANNELS_STEREO) {
- setFakeVolume(portControl, getFakeVolume(portControl), value);
- } else {
- ERROR0("PORT_SetFloatValue(): Balance only allowed for stereo channels!\n");
- }
- } else {
- ERROR1("PORT_SetFloatValue(): inappropriate control type: %s!\n",
- portControl->controlType);
- }
- }
-}
-
-
-#endif // USE_PORTS
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_PCM.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,626 +0,0 @@
-/*
- * Copyright (c) 2003, 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 USE_ERROR
-#define USE_TRACE
-
-#include "PLATFORM_API_SolarisOS_Utils.h"
-#include "DirectAudio.h"
-
-#if USE_DAUDIO == TRUE
-
-
-// The default buffer time
-#define DEFAULT_PERIOD_TIME_MILLIS 50
-
-///// implemented functions of DirectAudio.h
-
-INT32 DAUDIO_GetDirectAudioDeviceCount() {
- return (INT32) getAudioDeviceCount();
-}
-
-
-INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex,
- DirectAudioDeviceDescription* description) {
- AudioDeviceDescription desc;
-
- if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
- description->maxSimulLines = desc.maxSimulLines;
- strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1);
- description->name[DAUDIO_STRING_LENGTH-1] = 0;
- strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1);
- description->vendor[DAUDIO_STRING_LENGTH-1] = 0;
- strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1);
- description->version[DAUDIO_STRING_LENGTH-1] = 0;
- /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/
- strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1);
- description->description[DAUDIO_STRING_LENGTH-1] = 0;
- return TRUE;
- }
- return FALSE;
-
-}
-
-#define MAX_SAMPLE_RATES 20
-
-void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
- int fd = -1;
- AudioDeviceDescription desc;
- am_sample_rates_t *sr;
- /* hardcoded bits and channels */
- int bits[] = {8, 16};
- int bitsCount = 2;
- int channels[] = {1, 2};
- int channelsCount = 2;
- /* for querying sample rates */
- int err;
- int ch, b, s;
-
- TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource);
- if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
- fd = open(desc.pathctl, O_RDONLY);
- }
- if (fd < 0) {
- ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
- return;
- }
-
- /* get sample rates */
- sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES));
- if (sr == NULL) {
- ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex);
- close(fd);
- return;
- }
-
- sr->num_samp_rates = MAX_SAMPLE_RATES;
- sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD;
- sr->samp_rates[0] = -2;
- err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
- if (err < 0) {
- ERROR1(" DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n",
- (int)mixerIndex);
- ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n",
- (int) sr->num_samp_rates,
- (int) sr->samp_rates[0]);
- /* Some Solaris 8 drivers fail for get sample rates!
- * Do as if we support all sample rates
- */
- sr->flags = MIXER_SR_LIMITS;
- }
- if ((sr->flags & MIXER_SR_LIMITS)
- || (sr->num_samp_rates > MAX_SAMPLE_RATES)) {
-#ifdef USE_TRACE
- if ((sr->flags & MIXER_SR_LIMITS)) {
- TRACE1(" DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n",
- (int)mixerIndex);
- }
- if (sr->num_samp_rates > MAX_SAMPLE_RATES) {
- TRACE2(" DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n",
- MAX_SAMPLE_RATES, (int)mixerIndex);
- }
-#endif
- /*
- * Fake it to have only one sample rate: -1
- */
- sr->num_samp_rates = 1;
- sr->samp_rates[0] = -1;
- }
- close(fd);
-
- for (ch = 0; ch < channelsCount; ch++) {
- for (b = 0; b < bitsCount; b++) {
- for (s = 0; s < sr->num_samp_rates; s++) {
- DAUDIO_AddAudioFormat(creator,
- bits[b], /* significant bits */
- 0, /* frameSize: let it be calculated */
- channels[ch],
- (float) ((int) sr->samp_rates[s]),
- DAUDIO_PCM, /* encoding - let's only do PCM */
- (bits[b] > 8)?TRUE:TRUE, /* isSigned */
-#ifdef _LITTLE_ENDIAN
- FALSE /* little endian */
-#else
- (bits[b] > 8)?TRUE:FALSE /* big endian */
-#endif
- );
- }
- }
- }
- free(sr);
-}
-
-
-typedef struct {
- int fd;
- audio_info_t info;
- int bufferSizeInBytes;
- int frameSize; /* storage size in Bytes */
- /* how many bytes were written or read */
- INT32 transferedBytes;
- /* if transferedBytes exceed 32-bit boundary,
- * it will be reset and positionOffset will receive
- * the offset
- */
- INT64 positionOffset;
-} SolPcmInfo;
-
-
-void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
- int encoding, float sampleRate, int sampleSizeInBits,
- int frameSize, int channels,
- int isSigned, int isBigEndian, int bufferSizeInBytes) {
- int err = 0;
- int openMode;
- AudioDeviceDescription desc;
- SolPcmInfo* info;
-
- TRACE0("> DAUDIO_Open\n");
- if (encoding != DAUDIO_PCM) {
- ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding);
- return NULL;
- }
- if (channels <= 0) {
- ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels);
- return NULL;
- }
-
- info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo));
- if (!info) {
- ERROR0("Out of memory\n");
- return NULL;
- }
- memset(info, 0, sizeof(SolPcmInfo));
- info->frameSize = frameSize;
- info->fd = -1;
-
- if (isSource) {
- openMode = O_WRONLY;
- } else {
- openMode = O_RDONLY;
- }
-
-#ifndef __linux__
- /* blackdown does not use NONBLOCK */
- openMode |= O_NONBLOCK;
-#endif
-
- if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
- info->fd = open(desc.path, openMode);
- }
- if (info->fd < 0) {
- ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex);
- free(info);
- return NULL;
- }
- /* set to multiple open */
- if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) {
- TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path);
- } else {
- ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path);
- }
-
- AUDIO_INITINFO(&(info->info));
- /* need AUDIO_GETINFO ioctl to get this to work on solaris x86 */
- err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
-
- /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */
- AUDIO_INITINFO(&(info->info));
-
- if (isSource) {
- info->info.play.sample_rate = sampleRate;
- info->info.play.precision = sampleSizeInBits;
- info->info.play.channels = channels;
- info->info.play.encoding = AUDIO_ENCODING_LINEAR;
- info->info.play.buffer_size = bufferSizeInBytes;
- info->info.play.pause = 1;
- } else {
- info->info.record.sample_rate = sampleRate;
- info->info.record.precision = sampleSizeInBits;
- info->info.record.channels = channels;
- info->info.record.encoding = AUDIO_ENCODING_LINEAR;
- info->info.record.buffer_size = bufferSizeInBytes;
- info->info.record.pause = 1;
- }
- err = ioctl(info->fd, AUDIO_SETINFO, &(info->info));
- if (err < 0) {
- ERROR0("DAUDIO_Open: could not set info!\n");
- DAUDIO_Close((void*) info, isSource);
- return NULL;
- }
- DAUDIO_Flush((void*) info, isSource);
-
- err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
- if (err >= 0) {
- if (isSource) {
- info->bufferSizeInBytes = info->info.play.buffer_size;
- } else {
- info->bufferSizeInBytes = info->info.record.buffer_size;
- }
- TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n",
- (int) bufferSizeInBytes,
- (int) info->bufferSizeInBytes);
- } else {
- ERROR0("DAUDIO_Open: cannot get info!\n");
- DAUDIO_Close((void*) info, isSource);
- return NULL;
- }
- TRACE0("< DAUDIO_Open: Opened device successfully.\n");
- return (void*) info;
-}
-
-
-int DAUDIO_Start(void* id, int isSource) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int err, modified;
- audio_info_t audioInfo;
-
- TRACE0("> DAUDIO_Start\n");
-
- AUDIO_INITINFO(&audioInfo);
- err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
- if (err >= 0) {
- // unpause
- modified = FALSE;
- if (isSource && audioInfo.play.pause) {
- audioInfo.play.pause = 0;
- modified = TRUE;
- }
- if (!isSource && audioInfo.record.pause) {
- audioInfo.record.pause = 0;
- modified = TRUE;
- }
- if (modified) {
- err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
- }
- }
-
- TRACE1("< DAUDIO_Start %s\n", (err>=0)?"success":"error");
- return (err >= 0)?TRUE:FALSE;
-}
-
-int DAUDIO_Stop(void* id, int isSource) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int err, modified;
- audio_info_t audioInfo;
-
- TRACE0("> DAUDIO_Stop\n");
-
- AUDIO_INITINFO(&audioInfo);
- err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
- if (err >= 0) {
- // pause
- modified = FALSE;
- if (isSource && !audioInfo.play.pause) {
- audioInfo.play.pause = 1;
- modified = TRUE;
- }
- if (!isSource && !audioInfo.record.pause) {
- audioInfo.record.pause = 1;
- modified = TRUE;
- }
- if (modified) {
- err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
- }
- }
-
- TRACE1("< DAUDIO_Stop %s\n", (err>=0)?"success":"error");
- return (err >= 0)?TRUE:FALSE;
-}
-
-void DAUDIO_Close(void* id, int isSource) {
- SolPcmInfo* info = (SolPcmInfo*) id;
-
- TRACE0("DAUDIO_Close\n");
- if (info != NULL) {
- if (info->fd >= 0) {
- DAUDIO_Flush(id, isSource);
- close(info->fd);
- }
- free(info);
- }
-}
-
-#ifndef USE_TRACE
-/* close to 2^31 */
-#define POSITION_MAX 2000000000
-#else
-/* for testing */
-#define POSITION_MAX 1000000
-#endif
-
-void resetErrorFlagAndAdjustPosition(SolPcmInfo* info, int isSource, int count) {
- audio_info_t audioInfo;
- audio_prinfo_t* prinfo;
- int err;
- int offset = -1;
- int underrun = FALSE;
- int devBytes = 0;
-
- if (count > 0) {
- info->transferedBytes += count;
-
- if (isSource) {
- prinfo = &(audioInfo.play);
- } else {
- prinfo = &(audioInfo.record);
- }
- AUDIO_INITINFO(&audioInfo);
- err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
- if (err >= 0) {
- underrun = prinfo->error;
- devBytes = prinfo->samples * info->frameSize;
- }
- AUDIO_INITINFO(&audioInfo);
- if (underrun) {
- /* if an underrun occurred, reset */
- ERROR1("DAUDIO_Write/Read: Underrun/overflow: adjusting positionOffset by %d:\n",
- (devBytes - info->transferedBytes));
- ERROR1(" devBytes from %d to 0, ", devBytes);
- ERROR2(" positionOffset from %d to %d ",
- (int) info->positionOffset,
- (int) (info->positionOffset + info->transferedBytes));
- ERROR1(" transferedBytes from %d to 0\n",
- (int) info->transferedBytes);
- prinfo->samples = 0;
- info->positionOffset += info->transferedBytes;
- info->transferedBytes = 0;
- }
- else if (info->transferedBytes > POSITION_MAX) {
- /* we will reset transferedBytes and
- * the samples field in prinfo
- */
- offset = devBytes;
- prinfo->samples = 0;
- }
- /* reset error flag */
- prinfo->error = 0;
-
- err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
- if (err >= 0) {
- if (offset > 0) {
- /* upon exit of AUDIO_SETINFO, the samples parameter
- * was set to the previous value. This is our
- * offset.
- */
- TRACE1("Adjust samplePos: offset=%d, ", (int) offset);
- TRACE2("transferedBytes=%d -> %d, ",
- (int) info->transferedBytes,
- (int) (info->transferedBytes - offset));
- TRACE2("positionOffset=%d -> %d\n",
- (int) (info->positionOffset),
- (int) (((int) info->positionOffset) + offset));
- info->transferedBytes -= offset;
- info->positionOffset += offset;
- }
- } else {
- ERROR0("DAUDIO: resetErrorFlagAndAdjustPosition ioctl failed!\n");
- }
- }
-}
-
-// returns -1 on error
-int DAUDIO_Write(void* id, char* data, int byteSize) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int ret = -1;
-
- TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
- if (info!=NULL) {
- ret = write(info->fd, data, byteSize);
- resetErrorFlagAndAdjustPosition(info, TRUE, ret);
- /* sets ret to -1 if buffer full, no error! */
- if (ret < 0) {
- ret = 0;
- }
- }
- TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
- return ret;
-}
-
-// returns -1 on error
-int DAUDIO_Read(void* id, char* data, int byteSize) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int ret = -1;
-
- TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
- if (info != NULL) {
- ret = read(info->fd, data, byteSize);
- resetErrorFlagAndAdjustPosition(info, TRUE, ret);
- /* sets ret to -1 if buffer full, no error! */
- if (ret < 0) {
- ret = 0;
- }
- }
- TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
- return ret;
-}
-
-
-int DAUDIO_GetBufferSize(void* id, int isSource) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- if (info) {
- return info->bufferSizeInBytes;
- }
- return 0;
-}
-
-int DAUDIO_StillDraining(void* id, int isSource) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- audio_info_t audioInfo;
- audio_prinfo_t* prinfo;
- int ret = FALSE;
-
- if (info!=NULL) {
- if (isSource) {
- prinfo = &(audioInfo.play);
- } else {
- prinfo = &(audioInfo.record);
- }
- /* check error flag */
- AUDIO_INITINFO(&audioInfo);
- ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
- ret = (prinfo->error != 0)?FALSE:TRUE;
- }
- return ret;
-}
-
-
-int getDevicePosition(SolPcmInfo* info, int isSource) {
- audio_info_t audioInfo;
- audio_prinfo_t* prinfo;
- int err;
-
- if (isSource) {
- prinfo = &(audioInfo.play);
- } else {
- prinfo = &(audioInfo.record);
- }
- AUDIO_INITINFO(&audioInfo);
- err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
- if (err >= 0) {
- /*TRACE2("---> device paused: %d eof=%d\n",
- prinfo->pause, prinfo->eof);
- */
- return (int) (prinfo->samples * info->frameSize);
- }
- ERROR0("DAUDIO: getDevicePosition: ioctl failed!\n");
- return -1;
-}
-
-int DAUDIO_Flush(void* id, int isSource) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int err = -1;
- int pos;
-
- TRACE0("DAUDIO_Flush\n");
- if (info) {
- if (isSource) {
- err = ioctl(info->fd, I_FLUSH, FLUSHW);
- } else {
- err = ioctl(info->fd, I_FLUSH, FLUSHR);
- }
- if (err >= 0) {
- /* resets the transferedBytes parameter to
- * the current samples count of the device
- */
- pos = getDevicePosition(info, isSource);
- if (pos >= 0) {
- info->transferedBytes = pos;
- }
- }
- }
- if (err < 0) {
- ERROR0("ERROR in DAUDIO_Flush\n");
- }
- return (err < 0)?FALSE:TRUE;
-}
-
-int DAUDIO_GetAvailable(void* id, int isSource) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int ret = 0;
- int pos;
-
- if (info) {
- /* unfortunately, the STREAMS architecture
- * seems to not have a method for querying
- * the available bytes to read/write!
- * estimate it...
- */
- pos = getDevicePosition(info, isSource);
- if (pos >= 0) {
- if (isSource) {
- /* we usually have written more bytes
- * to the queue than the device position should be
- */
- ret = (info->bufferSizeInBytes) - (info->transferedBytes - pos);
- } else {
- /* for record, the device stream should
- * be usually ahead of our read actions
- */
- ret = pos - info->transferedBytes;
- }
- if (ret > info->bufferSizeInBytes) {
- ERROR2("DAUDIO_GetAvailable: available=%d, too big at bufferSize=%d!\n",
- (int) ret, (int) info->bufferSizeInBytes);
- ERROR2(" devicePos=%d, transferedBytes=%d\n",
- (int) pos, (int) info->transferedBytes);
- ret = info->bufferSizeInBytes;
- }
- else if (ret < 0) {
- ERROR1("DAUDIO_GetAvailable: available=%d, in theory not possible!\n",
- (int) ret);
- ERROR2(" devicePos=%d, transferedBytes=%d\n",
- (int) pos, (int) info->transferedBytes);
- ret = 0;
- }
- }
- }
-
- TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
- return ret;
-}
-
-INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int ret;
- int pos;
- INT64 result = javaBytePos;
-
- if (info) {
- pos = getDevicePosition(info, isSource);
- if (pos >= 0) {
- result = info->positionOffset + pos;
- }
- }
-
- //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
- return result;
-}
-
-
-void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
- SolPcmInfo* info = (SolPcmInfo*) id;
- int ret;
- int pos;
-
- if (info) {
- pos = getDevicePosition(info, isSource);
- if (pos >= 0) {
- info->positionOffset = javaBytePos - pos;
- }
- }
-}
-
-int DAUDIO_RequiresServicing(void* id, int isSource) {
- // never need servicing on Solaris
- return FALSE;
-}
-
-void DAUDIO_Service(void* id, int isSource) {
- // never need servicing on Solaris
-}
-
-
-#endif // USE_DAUDIO
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Ports.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,600 +0,0 @@
-/*
- * Copyright (c) 2002, 2016, 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 "Ports.h"
-#include "PLATFORM_API_SolarisOS_Utils.h"
-
-#if USE_PORTS == TRUE
-
-#define MONITOR_GAIN_STRING "Monitor Gain"
-
-#define ALL_TARGET_PORT_COUNT 6
-
-// define the following to not use audio_prinfo_t.mod_ports
-#define SOLARIS7_COMPATIBLE
-
-// Solaris audio defines
-static int targetPorts[ALL_TARGET_PORT_COUNT] = {
- AUDIO_SPEAKER,
- AUDIO_HEADPHONE,
- AUDIO_LINE_OUT,
- AUDIO_AUX1_OUT,
- AUDIO_AUX2_OUT,
- AUDIO_SPDIF_OUT
-};
-
-static char* targetPortNames[ALL_TARGET_PORT_COUNT] = {
- "Speaker",
- "Headphone",
- "Line Out",
- "AUX1 Out",
- "AUX2 Out",
- "SPDIF Out"
-};
-
-// defined in Ports.h
-static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = {
- PORT_DST_SPEAKER,
- PORT_DST_HEADPHONE,
- PORT_DST_LINE_OUT,
- PORT_DST_UNKNOWN,
- PORT_DST_UNKNOWN,
- PORT_DST_UNKNOWN,
-};
-
-#define ALL_SOURCE_PORT_COUNT 7
-
-// Solaris audio defines
-static int sourcePorts[ALL_SOURCE_PORT_COUNT] = {
- AUDIO_MICROPHONE,
- AUDIO_LINE_IN,
- AUDIO_CD,
- AUDIO_AUX1_IN,
- AUDIO_AUX2_IN,
- AUDIO_SPDIF_IN,
- AUDIO_CODEC_LOOPB_IN
-};
-
-static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = {
- "Microphone In",
- "Line In",
- "Compact Disc In",
- "AUX1 In",
- "AUX2 In",
- "SPDIF In",
- "Internal Loopback"
-};
-
-// Ports.h defines
-static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = {
- PORT_SRC_MICROPHONE,
- PORT_SRC_LINE_IN,
- PORT_SRC_COMPACT_DISC,
- PORT_SRC_UNKNOWN,
- PORT_SRC_UNKNOWN,
- PORT_SRC_UNKNOWN,
- PORT_SRC_UNKNOWN
-};
-
-struct tag_PortControlID;
-
-typedef struct tag_PortInfo {
- int fd; // file descriptor of the pseudo device
- audio_info_t audioInfo;
- // ports
- int targetPortCount;
- int sourcePortCount;
- // indexes to sourcePorts/targetPorts
- // contains first target ports, then source ports
- int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT];
- // controls
- int maxControlCount; // upper bound of number of controls
- int usedControlIDs; // number of items already filled in controlIDs
- struct tag_PortControlID* controlIDs; // the control IDs themselves
-} PortInfo;
-
-#define PORT_CONTROL_TYPE_PLAY 0x4000000
-#define PORT_CONTROL_TYPE_RECORD 0x8000000
-#define PORT_CONTROL_TYPE_SELECT_PORT 1
-#define PORT_CONTROL_TYPE_GAIN 2
-#define PORT_CONTROL_TYPE_BALANCE 3
-#define PORT_CONTROL_TYPE_MONITOR_GAIN 10
-#define PORT_CONTROL_TYPE_OUTPUT_MUTED 11
-#define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD
-#define PORT_CONTROL_TYPE_MASK 0xFFFFFF
-
-
-typedef struct tag_PortControlID {
- PortInfo* portInfo;
- INT32 controlType; // PORT_CONTROL_TYPE_XX
- uint_t port;
-} PortControlID;
-
-
-///// implemented functions of Ports.h
-
-INT32 PORT_GetPortMixerCount() {
- return (INT32) getAudioDeviceCount();
-}
-
-
-INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
- AudioDeviceDescription desc;
-
- if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
- strncpy(description->name, desc.name, PORT_STRING_LENGTH-1);
- description->name[PORT_STRING_LENGTH-1] = 0;
- strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1);
- description->vendor[PORT_STRING_LENGTH-1] = 0;
- strncpy(description->version, desc.version, PORT_STRING_LENGTH-1);
- description->version[PORT_STRING_LENGTH-1] = 0;
- /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/
- strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1);
- description->description[PORT_STRING_LENGTH-1] = 0;
- return TRUE;
- }
- return FALSE;
-}
-
-
-void* PORT_Open(INT32 mixerIndex) {
- PortInfo* info = NULL;
- int fd = -1;
- AudioDeviceDescription desc;
- int success = FALSE;
-
- TRACE0("PORT_Open\n");
- if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
- fd = open(desc.pathctl, O_RDWR);
- }
- if (fd < 0) {
- ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
- return NULL;
- }
-
- info = (PortInfo*) malloc(sizeof(PortInfo));
- if (info != NULL) {
- memset(info, 0, sizeof(PortInfo));
- info->fd = fd;
- success = TRUE;
- }
- if (!success) {
- if (fd >= 0) {
- close(fd);
- }
- PORT_Close((void*) info);
- info = NULL;
- }
- return info;
-}
-
-void PORT_Close(void* id) {
- TRACE0("PORT_Close\n");
- if (id != NULL) {
- PortInfo* info = (PortInfo*) id;
- if (info->fd >= 0) {
- close(info->fd);
- info->fd = -1;
- }
- if (info->controlIDs) {
- free(info->controlIDs);
- info->controlIDs = NULL;
- }
- free(info);
- }
-}
-
-
-
-INT32 PORT_GetPortCount(void* id) {
- int ret = 0;
- PortInfo* info = (PortInfo*) id;
- if (info != NULL) {
- if (!info->targetPortCount && !info->sourcePortCount) {
- int i;
- AUDIO_INITINFO(&info->audioInfo);
- if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) {
- for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) {
- if (info->audioInfo.play.avail_ports & targetPorts[i]) {
- info->ports[info->targetPortCount] = i;
- info->targetPortCount++;
- }
-#ifdef SOLARIS7_COMPATIBLE
- TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i],
- info->audioInfo.play.avail_ports & targetPorts[i]);
-#else
- TRACE4("Target %d %s: avail=%d mod=%d\n", i, targetPortNames[i],
- info->audioInfo.play.avail_ports & targetPorts[i],
- info->audioInfo.play.mod_ports & targetPorts[i]);
-#endif
- }
- for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) {
- if (info->audioInfo.record.avail_ports & sourcePorts[i]) {
- info->ports[info->targetPortCount + info->sourcePortCount] = i;
- info->sourcePortCount++;
- }
-#ifdef SOLARIS7_COMPATIBLE
- TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i],
- info->audioInfo.record.avail_ports & sourcePorts[i]);
-#else
- TRACE4("Source %d %s: avail=%d mod=%d\n", i, sourcePortNames[i],
- info->audioInfo.record.avail_ports & sourcePorts[i],
- info->audioInfo.record.mod_ports & sourcePorts[i]);
-#endif
- }
- }
- }
- ret = info->targetPortCount + info->sourcePortCount;
- }
- return ret;
-}
-
-int isSourcePort(PortInfo* info, INT32 portIndex) {
- return (portIndex >= info->targetPortCount);
-}
-
-INT32 PORT_GetPortType(void* id, INT32 portIndex) {
- PortInfo* info = (PortInfo*) id;
- if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
- if (isSourcePort(info, portIndex)) {
- return sourcePortJavaSoundMapping[info->ports[portIndex]];
- } else {
- return targetPortJavaSoundMapping[info->ports[portIndex]];
- }
- }
- return 0;
-}
-
-// pre-condition: portIndex must have been verified!
-char* getPortName(PortInfo* info, INT32 portIndex) {
- char* ret = NULL;
-
- if (isSourcePort(info, portIndex)) {
- ret = sourcePortNames[info->ports[portIndex]];
- } else {
- ret = targetPortNames[info->ports[portIndex]];
- }
- return ret;
-}
-
-INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
- PortInfo* info = (PortInfo*) id;
- char* n;
-
- if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) {
- n = getPortName(info, portIndex);
- if (n) {
- strncpy(name, n, len-1);
- name[len-1] = 0;
- return TRUE;
- }
- }
- return FALSE;
-}
-
-void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex,
- INT32 type, void** controlObjects, int* controlCount) {
- PortControlID* controlID;
- void* newControl = NULL;
- int controlIndex;
- char* jsType = NULL;
- int isBoolean = FALSE;
-
- TRACE0(">createPortControl\n");
-
- // fill the ControlID structure and add this control
- if (info->usedControlIDs >= info->maxControlCount) {
- ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount);
- return;
- }
- controlID = &(info->controlIDs[info->usedControlIDs]);
- controlID->portInfo = info;
- controlID->controlType = type;
- controlIndex = info->ports[portIndex];
- if (isSourcePort(info, portIndex)) {
- controlID->port = sourcePorts[controlIndex];
- } else {
- controlID->port = targetPorts[controlIndex];
- }
- switch (type & PORT_CONTROL_TYPE_MASK) {
- case PORT_CONTROL_TYPE_SELECT_PORT:
- jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break;
- case PORT_CONTROL_TYPE_GAIN:
- jsType = CONTROL_TYPE_VOLUME; break;
- case PORT_CONTROL_TYPE_BALANCE:
- jsType = CONTROL_TYPE_BALANCE; break;
- case PORT_CONTROL_TYPE_MONITOR_GAIN:
- jsType = CONTROL_TYPE_VOLUME; break;
- case PORT_CONTROL_TYPE_OUTPUT_MUTED:
- jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break;
- }
- if (isBoolean) {
- TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n");
- newControl = (creator->newBooleanControl)(creator, controlID, jsType);
- }
- else if (jsType == CONTROL_TYPE_BALANCE) {
- TRACE0(" PORT_CONTROL_TYPE_BALANCE\n");
- newControl = (creator->newFloatControl)(creator, controlID, jsType,
- -1.0f, 1.0f, 2.0f / 65.0f, "");
- } else {
- TRACE0(" PORT_CONTROL_TYPE_FLOAT\n");
- newControl = (creator->newFloatControl)(creator, controlID, jsType,
- 0.0f, 1.0f, 1.0f / 256.0f, "");
- }
- if (newControl) {
- controlObjects[*controlCount] = newControl;
- (*controlCount)++;
- info->usedControlIDs++;
- }
- TRACE0("<createPortControl\n");
-}
-
-
-void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) {
- void* compControl;
-
- TRACE1(">addCompoundControl %d controls\n", *controlCount);
- if (*controlCount) {
- // create compound control and add it to the vector
- compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount);
- if (compControl) {
- TRACE1(" addCompoundControl: calling addControl %p\n", compControl);
- (creator->addControl)(creator, compControl);
- }
- *controlCount = 0;
- }
- TRACE0("<addCompoundControl\n");
-}
-
-void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) {
- int i = 0;
-
- TRACE0(">addAllControl\n");
- // go through all controls and add them to the vector
- for (i = 0; i < *controlCount; i++) {
- (creator->addControl)(creator, controlObjects[i]);
- }
- *controlCount = 0;
- TRACE0("<addAllControl\n");
-}
-
-void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
- PortInfo* info = (PortInfo*) id;
- int portCount = PORT_GetPortCount(id);
- void* controls[4];
- int controlCount = 0;
- INT32 type;
- int selectable = 1;
- memset(controls, 0, sizeof(controls));
-
- TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n",
- id, portIndex, info->controlIDs, info->maxControlCount);
- if ((portIndex >= 0) && (portIndex < portCount)) {
- // if the memory isn't reserved for the control structures, allocate it
- if (!info->controlIDs) {
- int maxCount = 0;
- TRACE0("getControl: allocate mem\n");
- // get a maximum number of controls:
- // each port has a select, balance, and volume control.
- maxCount = 3 * portCount;
- // then there is monitorGain and outputMuted
- maxCount += (2 * info->targetPortCount);
- info->maxControlCount = maxCount;
- info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount);
- }
- if (!isSourcePort(info, portIndex)) {
- type = PORT_CONTROL_TYPE_PLAY;
- // add master mute control
- createPortControl(info, creator, portIndex,
- type | PORT_CONTROL_TYPE_OUTPUT_MUTED,
- controls, &controlCount);
- addAllControls(info, creator, controls, &controlCount);
-#ifdef SOLARIS7_COMPATIBLE
- selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]];
-#else
- selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]];
-#endif
- } else {
- type = PORT_CONTROL_TYPE_RECORD;
-#ifdef SOLARIS7_COMPATIBLE
- selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]];
-#else
- selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]];
-#endif
- }
- // add a mixer strip with volume, ...
- createPortControl(info, creator, portIndex,
- type | PORT_CONTROL_TYPE_GAIN,
- controls, &controlCount);
- // ... balance, ...
- createPortControl(info, creator, portIndex,
- type | PORT_CONTROL_TYPE_BALANCE,
- controls, &controlCount);
- // ... and select control (if not always on)...
- if (selectable) {
- createPortControl(info, creator, portIndex,
- type | PORT_CONTROL_TYPE_SELECT_PORT,
- controls, &controlCount);
- }
- // ... packaged in a compound control.
- addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount);
-
- if (type == PORT_CONTROL_TYPE_PLAY) {
- // add a single strip for source ports with monitor gain
- createPortControl(info, creator, portIndex,
- type | PORT_CONTROL_TYPE_MONITOR_GAIN,
- controls, &controlCount);
- // also in a compound control
- addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount);
- }
- }
- TRACE0("< PORT_getControls\n");
-}
-
-INT32 PORT_GetIntValue(void* controlIDV) {
- PortControlID* controlID = (PortControlID*) controlIDV;
- audio_info_t audioInfo;
- audio_prinfo_t* prinfo;
-
- AUDIO_INITINFO(&audioInfo);
- if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
- if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
- prinfo = &(audioInfo.play);
- } else {
- prinfo = &(audioInfo.record);
- }
- switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
- case PORT_CONTROL_TYPE_SELECT_PORT:
- return (prinfo->port & controlID->port)?TRUE:FALSE;
- case PORT_CONTROL_TYPE_OUTPUT_MUTED:
- return (audioInfo.output_muted)?TRUE:FALSE;
- default:
- ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
- }
- }
- ERROR0("PORT_GetIntValue: Could not ioctl!\n");
- return 0;
-}
-
-void PORT_SetIntValue(void* controlIDV, INT32 value) {
- PortControlID* controlID = (PortControlID*) controlIDV;
- audio_info_t audioInfo;
- audio_prinfo_t* prinfo;
- int setPort;
-
- if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
- prinfo = &(audioInfo.play);
- } else {
- prinfo = &(audioInfo.record);
- }
- switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
- case PORT_CONTROL_TYPE_SELECT_PORT:
- // first try to just add this port. if that fails, set ONLY to this port.
- AUDIO_INITINFO(&audioInfo);
- if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
- if (value) {
- setPort = (prinfo->port | controlID->port);
- } else {
- setPort = (prinfo->port - controlID->port);
- }
- AUDIO_INITINFO(&audioInfo);
- prinfo->port = setPort;
- if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
- // didn't work. Either this line doesn't support to select several
- // ports at once (e.g. record), or a real error
- if (value) {
- // set to ONLY this port (and disable any other currently selected ports)
- AUDIO_INITINFO(&audioInfo);
- prinfo->port = controlID->port;
- if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
- ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port);
- }
- } else {
- // assume it's an error
- ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort);
- }
- }
- break;
- case PORT_CONTROL_TYPE_OUTPUT_MUTED:
- AUDIO_INITINFO(&audioInfo);
- audioInfo.output_muted = (value?TRUE:FALSE);
- if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
- ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value);
- }
- break;
- default:
- ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
- }
- }
-}
-
-float PORT_GetFloatValue(void* controlIDV) {
- PortControlID* controlID = (PortControlID*) controlIDV;
- audio_info_t audioInfo;
- audio_prinfo_t* prinfo;
-
- AUDIO_INITINFO(&audioInfo);
- if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) {
- if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
- prinfo = &(audioInfo.play);
- } else {
- prinfo = &(audioInfo.record);
- }
- switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
- case PORT_CONTROL_TYPE_GAIN:
- return ((float) (prinfo->gain - AUDIO_MIN_GAIN))
- / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
- case PORT_CONTROL_TYPE_BALANCE:
- return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1))
- / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE));
- case PORT_CONTROL_TYPE_MONITOR_GAIN:
- return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN))
- / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN));
- default:
- ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
- }
- }
- ERROR0("PORT_GetFloatValue: Could not ioctl!\n");
- return 0.0f;
-}
-
-void PORT_SetFloatValue(void* controlIDV, float value) {
- PortControlID* controlID = (PortControlID*) controlIDV;
- audio_info_t audioInfo;
- audio_prinfo_t* prinfo;
-
- AUDIO_INITINFO(&audioInfo);
-
- if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) {
- prinfo = &(audioInfo.play);
- } else {
- prinfo = &(audioInfo.record);
- }
- switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) {
- case PORT_CONTROL_TYPE_GAIN:
- prinfo->gain = AUDIO_MIN_GAIN
- + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
- break;
- case PORT_CONTROL_TYPE_BALANCE:
- prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE
- + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f);
- break;
- case PORT_CONTROL_TYPE_MONITOR_GAIN:
- audioInfo.monitor_gain = AUDIO_MIN_GAIN
- + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f);
- break;
- default:
- ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK);
- return;
- }
- if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) {
- ERROR0("PORT_SetFloatValue: Could not ioctl!\n");
- }
-}
-
-#endif // USE_PORTS
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Utils.c Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2002, 2007, 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_SolarisOS_Utils.h"
-
-#define MAX_AUDIO_DEVICES 20
-
-// not thread safe...
-static AudioDevicePath globalADPaths[MAX_AUDIO_DEVICES];
-static int globalADCount = -1;
-static int globalADCacheTime = -1;
-/* how many seconds do we cache devices */
-#define AD_CACHE_TIME 30
-
-// return seconds
-long getTimeInSeconds() {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec;
-}
-
-
-int getAudioDeviceCount() {
- int count = MAX_AUDIO_DEVICES;
-
- getAudioDevices(globalADPaths, &count);
- return count;
-}
-
-/* returns TRUE if the path exists at all */
-int addAudioDevice(char* path, AudioDevicePath* adPath, int* count) {
- int i;
- int found = 0;
- int fileExists = 0;
- // not thread safe...
- static struct stat statBuf;
-
- // get stats on the file
- if (stat(path, &statBuf) == 0) {
- // file exists.
- fileExists = 1;
- // If it is not yet in the adPath array, add it to the array
- for (i = 0; i < *count; i++) {
- if (adPath[i].st_ino == statBuf.st_ino
- && adPath[i].st_dev == statBuf.st_dev) {
- found = 1;
- break;
- }
- }
- if (!found) {
- adPath[*count].st_ino = statBuf.st_ino;
- adPath[*count].st_dev = statBuf.st_dev;
- strncpy(adPath[*count].path, path, MAX_NAME_LENGTH);
- adPath[*count].path[MAX_NAME_LENGTH - 1] = 0;
- (*count)++;
- TRACE1("Added audio device %s\n", path);
- }
- }
- return fileExists;
-}
-
-
-void getAudioDevices(AudioDevicePath* adPath, int* count) {
- int maxCount = *count;
- char* audiodev;
- char devsound[15];
- int i;
- long timeInSeconds = getTimeInSeconds();
-
- if (globalADCount < 0
- || (getTimeInSeconds() - globalADCacheTime) > AD_CACHE_TIME
- || (adPath != globalADPaths)) {
- *count = 0;
- // first device, if set, is AUDIODEV variable
- audiodev = getenv("AUDIODEV");
- if (audiodev != NULL && audiodev[0] != 0) {
- addAudioDevice(audiodev, adPath, count);
- }
- // then try /dev/audio
- addAudioDevice("/dev/audio", adPath, count);
- // then go through all of the /dev/sound/? devices
- for (i = 0; i < 100; i++) {
- sprintf(devsound, "/dev/sound/%d", i);
- if (!addAudioDevice(devsound, adPath, count)) {
- break;
- }
- }
- if (adPath == globalADPaths) {
- /* commit cache */
- globalADCount = *count;
- /* set cache time */
- globalADCacheTime = timeInSeconds;
- }
- } else {
- /* return cache */
- *count = globalADCount;
- }
- // that's it
-}
-
-int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames) {
- int count = MAX_AUDIO_DEVICES;
- int ret = 0;
-
- getAudioDevices(globalADPaths, &count);
- if (index>=0 && index < count) {
- ret = getAudioDeviceDescription(globalADPaths[index].path, adDesc, getNames);
- }
- return ret;
-}
-
-int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames) {
- int fd;
- int mixerMode;
- int len;
- audio_info_t info;
- audio_device_t deviceInfo;
-
- strncpy(adDesc->path, path, MAX_NAME_LENGTH);
- adDesc->path[MAX_NAME_LENGTH] = 0;
- strcpy(adDesc->pathctl, adDesc->path);
- strcat(adDesc->pathctl, "ctl");
- strcpy(adDesc->name, adDesc->path);
- adDesc->vendor[0] = 0;
- adDesc->version[0] = 0;
- adDesc->description[0] = 0;
- adDesc->maxSimulLines = 1;
-
- // try to open the pseudo device and get more information
- fd = open(adDesc->pathctl, O_WRONLY | O_NONBLOCK);
- if (fd >= 0) {
- close(fd);
- if (getNames) {
- fd = open(adDesc->pathctl, O_RDONLY);
- if (fd >= 0) {
- if (ioctl(fd, AUDIO_GETDEV, &deviceInfo) >= 0) {
- strncpy(adDesc->vendor, deviceInfo.name, MAX_AUDIO_DEV_LEN);
- adDesc->vendor[MAX_AUDIO_DEV_LEN] = 0;
- strncpy(adDesc->version, deviceInfo.version, MAX_AUDIO_DEV_LEN);
- adDesc->version[MAX_AUDIO_DEV_LEN] = 0;
- /* add config string to the dev name
- * creates a string like "/dev/audio (onboard1)"
- */
- len = strlen(adDesc->name) + 1;
- if (MAX_NAME_LENGTH - len > 3) {
- strcat(adDesc->name, " (");
- strncat(adDesc->name, deviceInfo.config, MAX_NAME_LENGTH - len);
- strcat(adDesc->name, ")");
- }
- adDesc->name[MAX_NAME_LENGTH-1] = 0;
- }
- if (ioctl(fd, AUDIO_MIXERCTL_GET_MODE, &mixerMode) >= 0) {
- if (mixerMode == AM_MIXER_MODE) {
- TRACE1(" getAudioDeviceDescription: %s is in mixer mode\n", adDesc->path);
- adDesc->maxSimulLines = -1;
- }
- } else {
- ERROR1("ioctl AUDIO_MIXERCTL_GET_MODE failed on %s!\n", adDesc->path);
- }
- close(fd);
- } else {
- ERROR1("could not open %s!\n", adDesc->pathctl);
- }
- }
- return 1;
- }
- return 0;
-}
--- a/src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Utils.h Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2002, 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.
- */
-
-#include <Utilities.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-/* does not work on Solaris 2.7 */
-#include <sys/audio.h>
-#include <sys/mixer.h>
-#include <sys/types.h>
-#ifndef __linux__
-#include <stropts.h>
-#endif
-#include <sys/conf.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#ifndef PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
-#define PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
-
-/* defines for Solaris 2.7
- #ifndef AUDIO_AUX1_OUT
- #define AUDIO_AUX1_OUT (0x08) // output to aux1 out
- #define AUDIO_AUX2_OUT (0x10) // output to aux2 out
- #define AUDIO_SPDIF_OUT (0x20) // output to SPDIF port
- #define AUDIO_AUX1_IN (0x08) // input from aux1 in
- #define AUDIO_AUX2_IN (0x10) // input from aux2 in
- #define AUDIO_SPDIF_IN (0x20) // input from SPDIF port
- #endif
-*/
-
-/* input from Codec inter. loopback */
-#ifndef AUDIO_CODEC_LOOPB_IN
-#define AUDIO_CODEC_LOOPB_IN (0x40)
-#endif
-
-
-#define MAX_NAME_LENGTH 300
-
-typedef struct tag_AudioDevicePath {
- char path[MAX_NAME_LENGTH];
- ino_t st_ino; // inode number to detect duplicate devices
- dev_t st_dev; // device ID to detect duplicate audio devices
-} AudioDevicePath;
-
-typedef struct tag_AudioDeviceDescription {
- INT32 maxSimulLines;
- char path[MAX_NAME_LENGTH+1];
- char pathctl[MAX_NAME_LENGTH+4];
- char name[MAX_NAME_LENGTH+1];
- char vendor[MAX_NAME_LENGTH+1];
- char version[MAX_NAME_LENGTH+1];
- char description[MAX_NAME_LENGTH+1];
-} AudioDeviceDescription;
-
-int getAudioDeviceCount();
-
-/*
- * adPath is an array of AudioDevicePath structures
- * count contains initially the number of elements in adPath
- * and will be set to the returned number of paths.
- */
-void getAudioDevices(AudioDevicePath* adPath, int* count);
-
-/*
- * fills adDesc from the audio device given in path
- * returns 0 if an error occurred
- * if getNames is 0, only path and pathctl are filled
- */
-int getAudioDeviceDescription(char* path, AudioDeviceDescription* adDesc, int getNames);
-int getAudioDeviceDescriptionByIndex(int index, AudioDeviceDescription* adDesc, int getNames);
-
-
-#endif // PLATFORM_API_SOLARISOS_UTILS_H_INCLUDED
--- a/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java Fri Mar 23 18:44:47 2018 +0000
@@ -38,7 +38,6 @@
import java.awt.peer.WindowPeer;
import java.util.ArrayList;
-import jdk.internal.perf.PerfCounter;
import sun.awt.AWTAccessor;
import sun.awt.AWTAccessor.ComponentAccessor;
import sun.awt.Win32GraphicsDevice;
@@ -70,9 +69,6 @@
if (d3dAvailable) {
// we don't use pixel formats for the d3d pipeline
pfDisabled = true;
- PerfCounter.getD3DAvailable().set(1);
- } else {
- PerfCounter.getD3DAvailable().set(0);
}
}
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -7127,9 +7127,9 @@
{
TRY;
- return (jboolean)AwtToolkit::GetInstance().SyncCall(
+ return (jboolean)((intptr_t)AwtToolkit::GetInstance().SyncCall(
(void *(*)(void *))AwtComponent::_NativeHandlesWheelScrolling,
- env->NewGlobalRef(self));
+ env->NewGlobalRef(self)));
// global ref is deleted in _NativeHandlesWheelScrolling
CATCH_BAD_ALLOC_RET(NULL);
@@ -7148,9 +7148,9 @@
jobject selfGlobalRef = env->NewGlobalRef(self);
- return (jboolean)AwtToolkit::GetInstance().SyncCall(
+ return (jboolean)((intptr_t)AwtToolkit::GetInstance().SyncCall(
(void*(*)(void*))AwtComponent::_IsObscured,
- (void *)selfGlobalRef);
+ (void *)selfGlobalRef));
// selfGlobalRef is deleted in _IsObscured
CATCH_BAD_ALLOC_RET(NULL);
--- a/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Desktop.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -92,7 +92,7 @@
JNU_ReleaseStringPlatformChars(env, fileOrUri_j, fileOrUri_c);
JNU_ReleaseStringPlatformChars(env, verb_j, verb_c);
- if ((int)retval <= 32) {
+ if ((int)((intptr_t)retval) <= 32) {
// ShellExecute failed.
LPTSTR buffer = NULL;
int len = ::FormatMessage(
--- a/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Frame.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -1607,7 +1607,7 @@
DWORD fThread = ::GetWindowThreadProcessId(fHWnd, NULL);
if (fThread != AwtToolkit::GetInstance().MainThread()) {
// check if this thread has been already blocked
- BlockedThreadStruct *blockedThread = (BlockedThreadStruct *)sm_BlockedThreads.get((void *)fThread);
+ BlockedThreadStruct *blockedThread = (BlockedThreadStruct *)sm_BlockedThreads.get((void *)((intptr_t)fThread));
if (blocked) {
if (blockedThread == NULL) {
blockedThread = new BlockedThreadStruct;
@@ -1616,7 +1616,7 @@
0, fThread);
blockedThread->mouseHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)AwtDialog::MouseHookProc_NonTT,
0, fThread);
- sm_BlockedThreads.put((void *)fThread, blockedThread);
+ sm_BlockedThreads.put((void *)((intptr_t)fThread), blockedThread);
} else {
blockedThread->framesCount++;
}
@@ -1628,7 +1628,7 @@
if ((blockedThread->framesCount) == 1) {
::UnhookWindowsHookEx(blockedThread->modalHook);
::UnhookWindowsHookEx(blockedThread->mouseHook);
- sm_BlockedThreads.remove((void *)fThread);
+ sm_BlockedThreads.remove((void *)((intptr_t)fThread));
delete blockedThread;
} else {
blockedThread->framesCount--;
--- a/src/java.desktop/windows/native/libawt/windows/awt_List.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_List.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -823,9 +823,9 @@
jobject selfGlobalRef = env->NewGlobalRef(self);
- return (jint)AwtToolkit::GetInstance().SyncCall(
+ return (jint)((intptr_t)AwtToolkit::GetInstance().SyncCall(
(void *(*)(void *))AwtList::_GetMaxWidth,
- (void *)selfGlobalRef);
+ (void *)selfGlobalRef));
// selfGlobalRef is deleted in _GetMaxWidth
CATCH_BAD_ALLOC_RET(0);
@@ -1011,8 +1011,8 @@
ses->list = env->NewGlobalRef(self);
ses->index = index;
- return (jboolean)AwtToolkit::GetInstance().SyncCall(
- (void *(*)(void *))AwtList::_IsSelected, ses);
+ return (jboolean)((intptr_t)AwtToolkit::GetInstance().SyncCall(
+ (void *(*)(void *))AwtList::_IsSelected, ses));
// global ref and ses are deleted in _IsSelected
CATCH_BAD_ALLOC_RET(FALSE);
--- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -1106,7 +1106,7 @@
if (comp != NULL)
{
comp->SetInputMethod(self, useNativeCompWindow);
- comp->ImmAssociateContext((HIMC)context);
+ comp->ImmAssociateContext((HIMC)((intptr_t)context));
}
if (peer != NULL) {
@@ -3139,7 +3139,7 @@
(m_touchKbrdExeFilePath != NULL)) {
HINSTANCE retVal = ::ShellExecute(NULL, _T("open"),
m_touchKbrdExeFilePath, NULL, NULL, SW_SHOW);
- if ((int)retVal <= 32) {
+ if ((int)((intptr_t)retVal) <= 32) {
DTRACE_PRINTLN1("AwtToolkit::ShowTouchKeyboard: Failed"
", retVal='%d'", (int)retVal);
}
--- a/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Window.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -3915,8 +3915,8 @@
rfs->component = selfGlobalRef;
rfs->isMouseEventCause = isMouseEventCause;
- return (jboolean)AwtToolkit::GetInstance().SyncCall(
- (void*(*)(void*))AwtWindow::_RequestWindowFocus, rfs);
+ return (jboolean)((intptr_t)AwtToolkit::GetInstance().SyncCall(
+ (void*(*)(void*))AwtWindow::_RequestWindowFocus, rfs));
// global refs and rfs are deleted in _RequestWindowFocus
CATCH_BAD_ALLOC_RET(JNI_FALSE);
--- a/src/jdk.accessibility/windows/native/jaccessinspector/jaccessinspector.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/jdk.accessibility/windows/native/jaccessinspector/jaccessinspector.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -1526,7 +1526,8 @@
size_t messageNumber = g_MessageHistory.GetCurrentMessageIndex() + 1;
char text [32] = {0};
if ( 0 != messageCount ) {
- ::_snprintf(text, sizeof(text), "%d of %d", messageNumber, messageCount);
+ ::_snprintf(text, sizeof(text), "%d of %d", (int)messageNumber,
+ (int) messageCount);
}
return ::SetWindowText(dlgItem, text);
}
--- a/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp Fri Mar 23 18:01:52 2018 +0000
+++ b/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalker.cpp Fri Mar 23 18:44:47 2018 +0000
@@ -527,7 +527,7 @@
tvi.mask = TVIF_PARAM | TVIF_TEXT;
tvi.pszText = (char *) s; // Accessible name and role
tvi.cchTextMax = (int)strlen(s);
- tvi.lParam = (long) newNode; // Accessibility information
+ tvi.lParam = (LPARAM) newNode; // Accessibility information
TVINSERTSTRUCT tvis;
tvis.hParent = treeNodeParent;
@@ -544,13 +544,13 @@
char s[LINE_BUFSIZE];
sprintf( s,
"ERROR calling GetAccessibleContextInfo; vmID = %X, context = %p",
- vmID, context );
+ vmID, (void*)context );
TVITEM tvi;
tvi.mask = TVIF_PARAM | TVIF_TEXT; // text and lParam are only valid parts
tvi.pszText = (char *) s;
tvi.cchTextMax = (int)strlen(s);
- tvi.lParam = (long) newNode;
+ tvi.lParam = (LPARAM) newNode;
TVINSERTSTRUCT tvis;
tvis.hParent = treeNodeParent;
--- a/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c Fri Mar 23 18:01:52 2018 +0000
+++ b/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -231,7 +231,7 @@
int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
int i;
- for (i=0; i<table_size; i++) {
+ for (i = 0; i < table_size; i++) {
if (err == error_messages[i].err) {
return error_messages[i].msg;
}
@@ -293,7 +293,7 @@
*/
arg_count = (*env)->GetArrayLength(env, args);
- for (i=0; i<arg_count; i++) {
+ for (i = 0; i < arg_count; i++) {
jobject obj = (*env)->GetObjectArrayElement(env, args, i);
if (obj != NULL) {
cstr = JNU_GetStringPlatformChars(env, obj, &isCopy);
@@ -314,6 +314,15 @@
return -1;
}
}
+ } else {
+ char* newbuf = (char*)realloc(buf, size + 1);
+ if (newbuf == NULL) {
+ free(buf);
+ JNU_ThrowOutOfMemoryError(env, "realloc failed");
+ return -1;
+ }
+ buf = newbuf;
+ buf[size++] = 0;
}
if ((*env)->ExceptionOccurred(env)) {
free(buf);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Fri Mar 23 18:44:47 2018 +0000
@@ -828,7 +828,7 @@
return buf.toList();
}
- boolean checkDenotable(Type t) {
+ public boolean checkDenotable(Type t) {
return denotableChecker.visit(t, null);
}
// where
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Mar 23 18:01:52 2018 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Mar 23 18:44:47 2018 +0000
@@ -43,6 +43,7 @@
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types.UniqueType;
+import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.file.PathFileObject;
import com.sun.tools.javac.jvm.Pool.DynamicMethod;
import com.sun.tools.javac.jvm.Pool.Method;
@@ -101,6 +102,8 @@
/** Type utilities. */
private Types types;
+ private Check check;
+
/**
* If true, class files will be written in module-specific subdirectories
* of the CLASS_OUTPUT location.
@@ -178,6 +181,7 @@
target = Target.instance(context);
source = Source.instance(context);
types = Types.instance(context);
+ check = Check.instance(context);
fileManager = context.get(JavaFileManager.class);
signatureGen = new CWSignatureGenerator(types);
@@ -1294,10 +1298,10 @@
//where
private boolean needsLocalVariableTypeEntry(Type t) {
//a local variable needs a type-entry if its type T is generic
- //(i.e. |T| != T) and if it's not an intersection type (not supported
- //in signature attribute grammar)
- return (!types.isSameType(t, types.erasure(t)) &&
- !t.isCompound());
+ //(i.e. |T| != T) and if it's not an non-denotable type (non-denotable
+ // types are not supported in signature attribute grammar!)
+ return !types.isSameType(t, types.erasure(t)) &&
+ check.checkDenotable(t);
}
void writeStackMap(Code code) {
--- a/test/hotspot/jtreg/ProblemList.txt Fri Mar 23 18:01:52 2018 +0000
+++ b/test/hotspot/jtreg/ProblemList.txt Fri Mar 23 18:44:47 2018 +0000
@@ -44,6 +44,7 @@
compiler/codecache/stress/OverloadCompileQueueTest.java 8166554 generic-all
compiler/codegen/Test6896617.java 8193479 generic-all
compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8140405 generic-all
+compiler/jvmci/compilerToVM/GetExceptionTableTest.java 8200135 generic-all
compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java 8158860 generic-all
compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java 8163894 generic-all
compiler/tiered/LevelTransitionTest.java 8067651 generic-all
--- a/test/jdk/java/awt/Frame/UnfocusableMaximizedFrameResizablity/UnfocusableMaximizedFrameResizablity.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/awt/Frame/UnfocusableMaximizedFrameResizablity/UnfocusableMaximizedFrameResizablity.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -24,389 +24,97 @@
/*
@test
@key headful
- @bug 4980161
+ @bug 4980161 7158623
@summary Setting focusable window state to false makes the maximized frame resizable
- @author anthony.petrov@...: area=awt.toplevel
- @library ../../regtesthelpers
- @build Util
+ @compile UnfocusableMaximizedFrameResizablity.java
@run main UnfocusableMaximizedFrameResizablity
*/
-/**
- * UnfocusableMaximizedFrameResizablity.java
- *
- * summary: Tests whether a maximized unfocusable frame connot be resized by the user
- */
+import java.awt.Toolkit;
+import java.awt.Frame;
+import java.awt.Rectangle;
+import java.awt.AWTException;
+import java.awt.event.InputEvent;
+import java.awt.Robot;
-import java.awt.*;
-import java.awt.event.*;
-import test.java.awt.regtesthelpers.Util;
-
-public class UnfocusableMaximizedFrameResizablity
-{
-
- //*** test-writer defined static variables go here ***
-
+public class UnfocusableMaximizedFrameResizablity {
- private static void init()
- {
- //*** Create instructions for the user here ***
+ private static Frame frame;
+ private static Robot robot;
+ private static boolean isProgInterruption = false;
+ private static Thread mainThread = null;
+ private static int sleepTime = 300000;
- String[] instructions =
- {
- "This is an AUTOMATIC test, simply wait until it is done.",
- "The result (passed or failed) will be shown in the",
- "message window below."
- };
- Sysout.createDialog( );
- Sysout.printInstructions( instructions );
+ private static void createAndShowFrame() {
+ //The MAXIMIZED_BOTH state is not supported by the toolkit. Nothing to test.
if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
- System.out.println("The MAXIMIZED_BOTH state is not supported by the toolkit. Nothing to test.");
- pass();
return;
}
- // Create the maximized unfocusable frame
- final Frame f = new Frame("Unfocusable frame");
- f.setMaximizedBounds(new Rectangle(0, 0, 300, 300));
- f.setSize(200, 200);
- f.setVisible(true);
- f.setExtendedState(Frame.MAXIMIZED_BOTH);
- f.setFocusableWindowState(false);
+ frame = new Frame("Unfocusable frame");
+ frame.setMaximizedBounds(new Rectangle(0, 0, 300, 300));
+ frame.setSize(200, 200);
+ frame.setVisible(true);
+ frame.setExtendedState(Frame.MAXIMIZED_BOTH);
+ frame.setFocusableWindowState(false);
- Robot robot = Util.createRobot();
- robot.setAutoDelay(20);
-
- Util.waitForIdle(robot);
+ try {
+ robot = new Robot();
+ } catch (AWTException e) {
+ throw new RuntimeException("Robot creation failed");
+ }
+ robot.delay(2000);
// The initial bounds of the frame
- final Rectangle bounds = f.getBounds();
- System.out.println("Initial frame bounds: " + bounds);
+ final Rectangle bounds = frame.getBounds();
// Let's move the mouse pointer to the bottom-right coner of the frame (the "size-grip")
robot.mouseMove(bounds.x + bounds.width - 2, bounds.y + bounds.height - 2);
+ robot.waitForIdle();
// ... and start resizing
- robot.mousePress( InputEvent.BUTTON1_MASK );
- Util.waitForIdle(robot);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ robot.waitForIdle();
robot.mouseMove(bounds.x + bounds.width + 20, bounds.y + bounds.height + 15);
- Util.waitForIdle(robot);
- robot.mouseRelease( InputEvent.BUTTON1_MASK );
- Util.waitForIdle(robot);
+ robot.waitForIdle();
+
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ robot.waitForIdle();
// The bounds of the frame after the attempt of resizing is made
- final Rectangle finalBounds = f.getBounds();
- System.out.println("Final frame bounds: " + finalBounds);
+ final Rectangle finalBounds = frame.getBounds();
if (!finalBounds.equals(bounds)) {
- fail("The maximized unfocusable frame can be resized.");
- return;
+ cleanup();
+ throw new RuntimeException("The maximized unfocusable frame can be resized.");
}
-
- UnfocusableMaximizedFrameResizablity.pass();
-
- }//End init()
-
-
-
- /*****************************************************
- * Standard Test Machinery Section
- * DO NOT modify anything in this section -- it's a
- * standard chunk of code which has all of the
- * synchronisation necessary for the test harness.
- * By keeping it the same in all tests, it is easier
- * to read and understand someone else's test, as
- * well as insuring that all tests behave correctly
- * with the test harness.
- * There is a section following this for test-
- * classes
- ******************************************************/
- private static boolean theTestPassed = false;
- private static boolean testGeneratedInterrupt = false;
- private static String failureMessage = "";
-
- private static Thread mainThread = null;
-
- private static int sleepTime = 300000;
+ cleanup();
+ }
- // Not sure about what happens if multiple of this test are
- // instantiated in the same VM. Being static (and using
- // static vars), it aint gonna work. Not worrying about
- // it for now.
- public static void main( String args[] ) throws InterruptedException
- {
- mainThread = Thread.currentThread();
- try
- {
- init();
- }
- catch( TestPassedException e )
- {
- //The test passed, so just return from main and harness will
- // interepret this return as a pass
- return;
- }
- //At this point, neither test pass nor test fail has been
- // called -- either would have thrown an exception and ended the
- // test, so we know we have multiple threads.
+ private static void cleanup() {
+ frame.dispose();
+ isProgInterruption = true;
+ mainThread.interrupt();
+ }
+
+ public static void main(String args[]) throws InterruptedException {
- //Test involves other threads, so sleep and wait for them to
- // called pass() or fail()
- try
- {
- Thread.sleep( sleepTime );
- //Timed out, so fail the test
- throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
- }
- catch (InterruptedException e)
- {
- //The test harness may have interrupted the test. If so, rethrow the exception
- // so that the harness gets it and deals with it.
- if( ! testGeneratedInterrupt ) throw e;
+ mainThread = Thread.currentThread();
- //reset flag in case hit this code more than once for some reason (just safety)
- testGeneratedInterrupt = false;
-
- if ( theTestPassed == false )
- {
- throw new RuntimeException( failureMessage );
+ try {
+ createAndShowFrame();
+ mainThread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ if (!isProgInterruption) {
+ throw e;
}
}
- }//main
-
- public static synchronized void setTimeoutTo( int seconds )
- {
- sleepTime = seconds * 1000;
- }
-
- public static synchronized void pass()
- {
- Sysout.println( "The test passed." );
- Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
- //first check if this is executing in main thread
- if ( mainThread == Thread.currentThread() )
- {
- //Still in the main thread, so set the flag just for kicks,
- // and throw a test passed exception which will be caught
- // and end the test.
- theTestPassed = true;
- throw new TestPassedException();
+ if (!isProgInterruption) {
+ throw new RuntimeException("Timed out after " + sleepTime / 1000
+ + " seconds");
}
- theTestPassed = true;
- testGeneratedInterrupt = true;
- mainThread.interrupt();
- }//pass()
-
- public static synchronized void fail()
- {
- //test writer didn't specify why test failed, so give generic
- fail( "it just plain failed! :-)" );
}
-
- public static synchronized void fail( String whyFailed )
- {
- Sysout.println( "The test failed: " + whyFailed );
- Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
- //check if this called from main thread
- if ( mainThread == Thread.currentThread() )
- {
- //If main thread, fail now 'cause not sleeping
- throw new RuntimeException( whyFailed );
- }
- theTestPassed = false;
- testGeneratedInterrupt = true;
- failureMessage = whyFailed;
- mainThread.interrupt();
- }//fail()
-
-}// class UnfocusableMaximizedFrameResizablity
-
-//This exception is used to exit from any level of call nesting
-// when it's determined that the test has passed, and immediately
-// end the test.
-class TestPassedException extends RuntimeException
-{
}
-//*********** End Standard Test Machinery Section **********
-
-
-//************ Begin classes defined for the test ****************
-
-// if want to make listeners, here is the recommended place for them, then instantiate
-// them in init()
-
-/* Example of a class which may be written as part of a test
-class NewClass implements anInterface
- {
- static int newVar = 0;
-
- public void eventDispatched(AWTEvent e)
- {
- //Counting events to see if we get enough
- eventCount++;
-
- if( eventCount == 20 )
- {
- //got enough events, so pass
-
- UnfocusableMaximizedFrameResizablity.pass();
- }
- else if( tries == 20 )
- {
- //tried too many times without getting enough events so fail
-
- UnfocusableMaximizedFrameResizablity.fail();
- }
-
- }// eventDispatched()
-
- }// NewClass class
-
-*/
-
-
-//************** End classes defined for the test *******************
-
-
-
-
-/****************************************************
- Standard Test Machinery
- DO NOT modify anything below -- it's a standard
- chunk of code whose purpose is to make user
- interaction uniform, and thereby make it simpler
- to read and understand someone else's test.
- ****************************************************/
-
-/**
- This is part of the standard test machinery.
- It creates a dialog (with the instructions), and is the interface
- for sending text messages to the user.
- To print the instructions, send an array of strings to Sysout.createDialog
- WithInstructions method. Put one line of instructions per array entry.
- To display a message for the tester to see, simply call Sysout.println
- with the string to be displayed.
- This mimics System.out.println but works within the test harness as well
- as standalone.
- */
-
-class Sysout
-{
- private static TestDialog dialog;
-
- public static void createDialogWithInstructions( String[] instructions )
- {
- dialog = new TestDialog( new Frame(), "Instructions" );
- dialog.printInstructions( instructions );
- dialog.setVisible(true);
- println( "Any messages for the tester will display here." );
- }
-
- public static void createDialog( )
- {
- dialog = new TestDialog( new Frame(), "Instructions" );
- String[] defInstr = { "Instructions will appear here. ", "" } ;
- dialog.printInstructions( defInstr );
- dialog.setVisible(true);
- println( "Any messages for the tester will display here." );
- }
-
-
- public static void printInstructions( String[] instructions )
- {
- dialog.printInstructions( instructions );
- }
-
-
- public static void println( String messageIn )
- {
- dialog.displayMessage( messageIn );
- System.out.println(messageIn);
- }
-
-}// Sysout class
-
-/**
- This is part of the standard test machinery. It provides a place for the
- test instructions to be displayed, and a place for interactive messages
- to the user to be displayed.
- To have the test instructions displayed, see Sysout.
- To have a message to the user be displayed, see Sysout.
- Do not call anything in this dialog directly.
- */
-class TestDialog extends Dialog
-{
-
- TextArea instructionsText;
- TextArea messageText;
- int maxStringLength = 80;
-
- //DO NOT call this directly, go through Sysout
- public TestDialog( Frame frame, String name )
- {
- super( frame, name );
- int scrollBoth = TextArea.SCROLLBARS_BOTH;
- instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
- add( "North", instructionsText );
-
- messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
- add("Center", messageText);
-
- pack();
-
- setVisible(true);
- }// TestDialog()
-
- //DO NOT call this directly, go through Sysout
- public void printInstructions( String[] instructions )
- {
- //Clear out any current instructions
- instructionsText.setText( "" );
-
- //Go down array of instruction strings
-
- String printStr, remainingStr;
- for( int i=0; i < instructions.length; i++ )
- {
- //chop up each into pieces maxSringLength long
- remainingStr = instructions[ i ];
- while( remainingStr.length() > 0 )
- {
- //if longer than max then chop off first max chars to print
- if( remainingStr.length() >= maxStringLength )
- {
- //Try to chop on a word boundary
- int posOfSpace = remainingStr.
- lastIndexOf( ' ', maxStringLength - 1 );
-
- if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
-
- printStr = remainingStr.substring( 0, posOfSpace + 1 );
- remainingStr = remainingStr.substring( posOfSpace + 1 );
- }
- //else just print
- else
- {
- printStr = remainingStr;
- remainingStr = "";
- }
-
- instructionsText.append( printStr + "\n" );
-
- }// while
-
- }// for
-
- }//printInstructions()
-
- //DO NOT call this directly, go through Sysout
- public void displayMessage( String messageIn )
- {
- messageText.append( messageIn + "\n" );
- System.out.println(messageIn);
- }
-
-}// TestDialog class
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/event/SequencedEvent/SequencedEventTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8152974
+ * @key headful
+ * @summary AWT hang occurrs when sequenced events arrive out of sequence
+ * @run main SequencedEventTest
+ */
+import sun.awt.AppContext;
+import sun.awt.SunToolkit;
+
+import java.awt.Robot;
+import java.awt.Point;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.AWTEvent;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.InputEvent;
+import java.lang.reflect.Constructor;
+import java.util.concurrent.CountDownLatch;
+
+import javax.swing.JFrame;
+import javax.swing.JButton;
+import javax.swing.SwingUtilities;
+import javax.swing.JTextArea;
+
+public class SequencedEventTest extends JFrame implements ActionListener {
+ private JButton spamMeButton;
+ private static Robot robot;
+ private static SequencedEventTest window;
+ private static AppContext context;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(() -> {
+ window = new SequencedEventTest();
+ window.setVisible(true);
+ });
+
+ robot = new Robot();
+ robot.waitForIdle();
+
+ Point pt = window.spamMeButton.getLocationOnScreen();
+ Dimension d = window.spamMeButton.getSize();
+
+ robot.mouseMove(pt.x + d.width / 2, pt.y + d.height / 2);
+ robot.waitForIdle();
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ /*
+ *Cannot have robot.waitForIdle() here since it will block the test forever,
+ * in the case of failure and the test will timeout.
+ */
+
+ try {
+ /*
+ * Wait for 2 seconds, and then see if all the sequenced events are dispatched.
+ */
+ Thread.sleep(2000);
+ AWTEvent ev = Toolkit.getDefaultToolkit().getSystemEventQueue().
+ peekEvent(java.awt.event.FocusEvent.FOCUS_LAST + 1);
+
+ if (ev != null)
+ throw new RuntimeException("Test case failed!");
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Test case failed." + e.getMessage());
+ }
+
+ /*
+ * In the case of failure, the cleanup job cannot be executed, since it
+ * will block the test.
+ */
+ System.out.println("Test case succeeded.");
+ context.dispose();
+ SwingUtilities.invokeAndWait(() -> window.dispose());
+ }
+
+ public SequencedEventTest() {
+ super("Test Window");
+
+ setLayout(new FlowLayout());
+ JTextArea textBlock = new JTextArea("Lorem ipsum dolor sit amet...");
+ add(textBlock);
+
+ spamMeButton = new JButton("Press me!");
+ spamMeButton.addActionListener(this);
+ add(spamMeButton);
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ pack();
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if(e.getSource() == spamMeButton) {
+ AWTEvent eventOne = getSequencedEvent();
+ AWTEvent eventFour = getSequencedEvent();
+ ThreadGroup tg = new ThreadGroup("TestThreadGroup" );
+ CountDownLatch latch = new CountDownLatch(1);
+ Thread t = new Thread(tg, () -> {
+ context = SunToolkit.createNewAppContext();
+ AWTEvent eventTwo = getSequencedEvent();
+ AWTEvent eventThree = getSequencedEvent();
+
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(eventThree);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new ActionEvent(this, 0, null));
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new ActionEvent(this, 1, null));
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(eventTwo);
+
+ latch.countDown();
+ });
+
+ t.start();
+ try {
+ latch.await();
+ }catch (InterruptedException ex) {
+ throw new RuntimeException("Test case failed.");
+ }
+
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(eventFour);
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new ActionEvent(this, 2, null));
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new ActionEvent(this, 3, null));
+ Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(eventOne);
+
+ try {
+ t.join();
+ } catch (InterruptedException ex) {
+ throw new RuntimeException("Test case failed.");
+ }
+ }
+ }
+
+ private AWTEvent getSequencedEvent()
+ {
+ AWTEvent wrapMe = new AWTEvent(this, AWTEvent.RESERVED_ID_MAX) {};
+
+ try {
+ /*
+ * SequencedEvent is a package private class, which cannot be instantiated
+ * by importing. So use reflection to create an instance.
+ */
+ Class<? extends AWTEvent> seqClass = (Class<? extends AWTEvent>) Class.forName("java.awt.SequencedEvent");
+ Constructor<? extends AWTEvent> seqConst = seqClass.getConstructor(AWTEvent.class);
+ seqConst.setAccessible(true);;
+ return seqConst.newInstance(wrapMe);
+ } catch (Throwable err) {
+ throw new RuntimeException("Unable to instantiate SequencedEvent",err);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/io/ByteArrayInputStream/ReadAllReadNTransferTo.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Random;
+import jdk.test.lib.RandomFactory;
+
+/* @test
+ * @library /test/lib
+ * @build jdk.test.lib.RandomFactory
+ * @run main ReadAllReadNTransferTo
+ * @bug 8180451
+ * @summary Verify ByteArrayInputStream readAllBytes, readNBytes, and transferTo
+ * @key randomness
+ */
+public class ReadAllReadNTransferTo {
+ private static final int SIZE = 0x4d4d;
+
+ private static Random random = RandomFactory.getRandom();
+
+ public static void main(String... args) throws IOException {
+ byte[] buf = new byte[SIZE];
+ random.nextBytes(buf);
+ int position = random.nextInt(SIZE/2);
+ int size = random.nextInt(SIZE - position);
+
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(buf, position, size);
+ int off = random.nextInt(size / 2);
+ int len = random.nextInt(size - off);
+
+ byte[] bN = new byte[off + len];
+ if (bais.readNBytes(bN, off, len) != len) {
+ throw new RuntimeException("readNBytes return value");
+ }
+ if (!Arrays.equals(bN, off, off + len,
+ buf, position, position + len)) {
+ throw new RuntimeException("readNBytes content");
+ }
+
+ byte[] bAll = bais.readAllBytes();
+ Objects.requireNonNull(bAll, "readAllBytes return value");
+ if (bAll.length != size - len) {
+ throw new RuntimeException("readAllBytes return value length");
+ }
+ if (!Arrays.equals(bAll, 0, bAll.length,
+ buf, position + len, position + len + bAll.length)) {
+ throw new RuntimeException("readAllBytes content");
+ }
+
+ // XXX transferTo()
+ bais = new ByteArrayInputStream(buf);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(buf.length);
+ if (bais.transferTo(baos) != buf.length) {
+ throw new RuntimeException("transferTo return value length");
+ }
+ if (!Arrays.equals(buf, baos.toByteArray())) {
+ throw new RuntimeException("transferTo content");
+ }
+ }
+}
--- a/test/jdk/java/nio/Buffer/EqualsCompareTest.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/nio/Buffer/EqualsCompareTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -45,7 +45,7 @@
/*
* @test
- * @bug 8193085
+ * @bug 8193085 8199773
* @summary tests for buffer equals and compare
* @run testng EqualsCompareTest
*/
@@ -120,8 +120,9 @@
abstract T construct(int length, ByteOrder bo);
@SuppressWarnings("unchecked")
- T slice(T a, int from, int to) {
- return (T) a.position(from).limit(to).slice();
+ T slice(T a, int from, int to, boolean dupOtherwiseSlice) {
+ a = (T) a.position(from).limit(to);
+ return (T) (dupOtherwiseSlice ? a.duplicate() : a.slice());
}
@SuppressWarnings("unchecked")
@@ -607,60 +608,62 @@
BiFunction<BT, Integer, B> bConstructor) {
int n = arraySizeFor(bt.elementType);
- for (int s : ranges(0, n)) {
- B a = aConstructor.apply(bt, s);
- B b = bConstructor.apply(bt, s);
+ for (boolean dupOtherwiseSlice : new boolean[]{ false, true }) {
+ for (int s : ranges(0, n)) {
+ B a = aConstructor.apply(bt, s);
+ B b = bConstructor.apply(bt, s);
- for (int aFrom : ranges(0, s)) {
- for (int aTo : ranges(aFrom, s)) {
- int aLength = aTo - aFrom;
+ for (int aFrom : ranges(0, s)) {
+ for (int aTo : ranges(aFrom, s)) {
+ int aLength = aTo - aFrom;
- B as = aLength != s
- ? bt.slice(a, aFrom, aTo)
- : a;
+ B as = aLength != s
+ ? bt.slice(a, aFrom, aTo, dupOtherwiseSlice)
+ : a;
- for (int bFrom : ranges(0, s)) {
- for (int bTo : ranges(bFrom, s)) {
- int bLength = bTo - bFrom;
+ for (int bFrom : ranges(0, s)) {
+ for (int bTo : ranges(bFrom, s)) {
+ int bLength = bTo - bFrom;
+
+ B bs = bLength != s
+ ? bt.slice(b, bFrom, bTo, dupOtherwiseSlice)
+ : b;
- B bs = bLength != s
- ? bt.slice(b, bFrom, bTo)
- : b;
+ boolean eq = bt.pairWiseEquals(as, bs);
+ Assert.assertEquals(bt.equals(as, bs), eq);
+ Assert.assertEquals(bt.equals(bs, as), eq);
+ if (eq) {
+ Assert.assertEquals(bt.compare(as, bs), 0);
+ Assert.assertEquals(bt.compare(bs, as), 0);
+ }
+ else {
+ int aCb = bt.compare(as, bs);
+ int bCa = bt.compare(bs, as);
+ int v = Integer.signum(aCb) * Integer.signum(bCa);
+ Assert.assertTrue(v == -1);
+ }
+ }
+ }
- boolean eq = bt.pairWiseEquals(as, bs);
- Assert.assertEquals(bt.equals(as, bs), eq);
- Assert.assertEquals(bt.equals(bs, as), eq);
- if (eq) {
- Assert.assertEquals(bt.compare(as, bs), 0);
- Assert.assertEquals(bt.compare(bs, as), 0);
- }
- else {
- int aCb = bt.compare(as, bs);
- int bCa = bt.compare(bs, as);
- int v = Integer.signum(aCb) * Integer.signum(bCa);
+ if (aLength > 0 && !a.isReadOnly()) {
+ for (int i = aFrom; i < aTo; i++) {
+ B c = aConstructor.apply(bt, a.capacity());
+ B cs = aLength != s
+ ? bt.slice(c, aFrom, aTo, dupOtherwiseSlice)
+ : c;
+
+ // Create common prefix with a length of i - aFrom
+ bt.set(c, i, -1);
+
+ Assert.assertFalse(bt.equals(c, a));
+
+ int cCa = bt.compare(cs, as);
+ int aCc = bt.compare(as, cs);
+ int v = Integer.signum(cCa) * Integer.signum(aCc);
Assert.assertTrue(v == -1);
}
}
}
-
- if (aLength > 0 && !a.isReadOnly()) {
- for (int i = aFrom; i < aTo; i++) {
- B c = aConstructor.apply(bt, a.capacity());
- B cs = aLength != s
- ? bt.slice(c, aFrom, aTo)
- : c;
-
- // Create common prefix with a length of i - aFrom
- bt.set(c, i, -1);
-
- Assert.assertFalse(bt.equals(c, a));
-
- int cCa = bt.compare(cs, as);
- int aCc = bt.compare(as, cs);
- int v = Integer.signum(cCa) * Integer.signum(aCc);
- Assert.assertTrue(v == -1);
- }
- }
}
}
}
--- a/test/jdk/java/nio/channels/DatagramChannel/Connect.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/nio/channels/DatagramChannel/Connect.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -102,7 +102,7 @@
try {
dc.send(bb, bogus);
throw new RuntimeException("Allowed bogus send while connected");
- } catch (IllegalArgumentException iae) {
+ } catch (AlreadyConnectedException ace) {
// Correct behavior
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/channels/DatagramChannel/ConnectExceptions.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 8198753
+ * @summary Test DatagramChannel connect exceptions
+ * @library ..
+ * @run testng ConnectExceptions
+ */
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class ConnectExceptions {
+ static DatagramChannel sndChannel;
+ static DatagramChannel rcvChannel;
+ static InetSocketAddress sender;
+ static InetSocketAddress receiver;
+
+ @BeforeTest
+ public static void setup() throws Exception {
+ sndChannel = DatagramChannel.open();
+ sndChannel.bind(null);
+ InetAddress address = InetAddress.getLocalHost();
+ if (address.isLoopbackAddress()) {
+ address = InetAddress.getLoopbackAddress();
+ }
+ sender = new InetSocketAddress(address,
+ sndChannel.socket().getLocalPort());
+
+ rcvChannel = DatagramChannel.open();
+ rcvChannel.bind(null);
+ receiver = new InetSocketAddress(address,
+ rcvChannel.socket().getLocalPort());
+ }
+
+ @Test(expectedExceptions = UnsupportedAddressTypeException.class)
+ public static void unsupportedAddressTypeException() throws Exception {
+ rcvChannel.connect(sender);
+ sndChannel.connect(new SocketAddress() {});
+ }
+
+ @Test(expectedExceptions = UnresolvedAddressException.class)
+ public static void unresolvedAddressException() throws Exception {
+ String host = TestUtil.UNRESOLVABLE_HOST;
+ InetSocketAddress unresolvable = new InetSocketAddress (host, 37);
+ sndChannel.connect(unresolvable);
+ }
+
+ @Test(expectedExceptions = AlreadyConnectedException.class)
+ public static void alreadyConnectedException() throws Exception {
+ sndChannel.connect(receiver);
+ InetSocketAddress random = new InetSocketAddress(0);
+ sndChannel.connect(random);
+ }
+
+ @AfterTest
+ public static void cleanup() throws Exception {
+ rcvChannel.close();
+ sndChannel.close();
+ }
+}
--- a/test/jdk/java/nio/channels/DatagramChannel/ConnectedSend.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/nio/channels/DatagramChannel/ConnectedSend.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -24,6 +24,8 @@
/* @test
* @bug 4849277 7183800
* @summary Test DatagramChannel send while connected
+ * @library ..
+ * @run testng ConnectedSend
* @author Mike McCloskey
*/
@@ -32,20 +34,16 @@
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
public class ConnectedSend {
-
- public static void main(String[] args) throws Exception {
- test1();
- test2();
- }
-
// Check if DatagramChannel.send while connected can include
// address without throwing
- private static void test1() throws Exception {
-
+ @Test
+ public static void sendToConnectedAddress() throws Exception {
DatagramChannel sndChannel = DatagramChannel.open();
- sndChannel.socket().bind(null);
+ sndChannel.bind(null);
InetAddress address = InetAddress.getLocalHost();
if (address.isLoopbackAddress()) {
address = InetAddress.getLoopbackAddress();
@@ -55,7 +53,7 @@
sndChannel.socket().getLocalPort());
DatagramChannel rcvChannel = DatagramChannel.open();
- rcvChannel.socket().bind(null);
+ rcvChannel.bind(null);
InetSocketAddress receiver = new InetSocketAddress(
address,
rcvChannel.socket().getLocalPort());
@@ -71,8 +69,7 @@
rcvChannel.receive(bb);
bb.flip();
CharBuffer cb = Charset.forName("US-ASCII").newDecoder().decode(bb);
- if (!cb.toString().startsWith("h"))
- throw new RuntimeException("Test failed");
+ assertTrue(cb.toString().startsWith("h"), "Unexpected message content");
rcvChannel.close();
sndChannel.close();
@@ -81,9 +78,10 @@
// Check if the datagramsocket adaptor can send with a packet
// that has not been initialized with an address; the legacy
// datagram socket will send in this case
- private static void test2() throws Exception {
+ @Test
+ public static void sendAddressedPacket() throws Exception {
DatagramChannel sndChannel = DatagramChannel.open();
- sndChannel.socket().bind(null);
+ sndChannel.bind(null);
InetAddress address = InetAddress.getLocalHost();
if (address.isLoopbackAddress()) {
address = InetAddress.getLoopbackAddress();
@@ -93,7 +91,7 @@
sndChannel.socket().getLocalPort());
DatagramChannel rcvChannel = DatagramChannel.open();
- rcvChannel.socket().bind(null);
+ rcvChannel.bind(null);
InetSocketAddress receiver = new InetSocketAddress(
address,
rcvChannel.socket().getLocalPort());
@@ -109,13 +107,12 @@
rcvChannel.receive(bb);
bb.flip();
CharBuffer cb = Charset.forName("US-ASCII").newDecoder().decode(bb);
- if (!cb.toString().startsWith("h"))
- throw new RuntimeException("Test failed");
+ assertTrue(cb.toString().startsWith("h"), "Unexpected message content");
// Check that the pkt got set with the target address;
// This is legacy behavior
- if (!pkt.getSocketAddress().equals(receiver))
- throw new RuntimeException("Test failed");
+ assertEquals(pkt.getSocketAddress(), receiver,
+ "Unexpected address set on packet");
rcvChannel.close();
sndChannel.close();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/channels/DatagramChannel/SendExceptions.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 4675045 8198753
+ * @summary Test DatagramChannel send exceptions
+ * @library ..
+ * @run testng SendExceptions
+ */
+
+import java.io.*;
+import java.net.*;
+import java.nio.*;
+import java.nio.channels.*;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class SendExceptions {
+ static DatagramChannel sndChannel;
+ static DatagramChannel rcvChannel;
+ static InetSocketAddress sender;
+ static InetSocketAddress receiver;
+ static ByteBuffer buf = ByteBuffer.allocate(17);
+
+ @BeforeTest
+ public static void setup() throws Exception {
+ sndChannel = DatagramChannel.open();
+ sndChannel.bind(null);
+ InetAddress address = InetAddress.getLocalHost();
+ if (address.isLoopbackAddress()) {
+ address = InetAddress.getLoopbackAddress();
+ }
+ sender = new InetSocketAddress(address,
+ sndChannel.socket().getLocalPort());
+
+ rcvChannel = DatagramChannel.open();
+ rcvChannel.bind(null);
+ receiver = new InetSocketAddress(address,
+ rcvChannel.socket().getLocalPort());
+ }
+
+ @Test(expectedExceptions = UnsupportedAddressTypeException.class)
+ public static void unsupportedAddressTypeException() throws Exception {
+ rcvChannel.connect(sender);
+ sndChannel.send(buf, new SocketAddress() {});
+ }
+
+ @Test(expectedExceptions = UnresolvedAddressException.class)
+ public static void unresolvedAddressException() throws Exception {
+ String host = TestUtil.UNRESOLVABLE_HOST;
+ InetSocketAddress unresolvable = new InetSocketAddress (host, 37);
+ sndChannel.send(buf, unresolvable);
+ }
+
+ @Test(expectedExceptions = AlreadyConnectedException.class)
+ public static void alreadyConnectedException() throws Exception {
+ sndChannel.connect(receiver);
+ InetSocketAddress random = new InetSocketAddress(0);
+ sndChannel.send(buf, random);
+ }
+
+ @AfterTest
+ public static void cleanup() throws Exception {
+ rcvChannel.close();
+ sndChannel.close();
+ }
+}
--- a/test/jdk/java/nio/channels/DatagramChannel/SendToUnresolved.java Fri Mar 23 18:01:52 2018 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2002, 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.
- *
- * 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.
- */
-
-/* @test
- * @bug 4675045
- * @summary Test DatagramChannel send to unresolved address
- * @library ..
- */
-
-import java.io.*;
-import java.net.*;
-import java.nio.*;
-import java.nio.channels.*;
-
-public class SendToUnresolved {
- public static void main(String [] argv) throws Exception {
- String host = TestUtil.UNRESOLVABLE_HOST;
- DatagramChannel dc = DatagramChannel.open();
- ByteBuffer bb = ByteBuffer.allocate(4);
- InetSocketAddress sa = new InetSocketAddress (host, 37);
- InetAddress inetaddr = sa.getAddress();
- try {
- dc.send(bb, sa);
- throw new RuntimeException("Expected exception not thrown");
- } catch (IOException | UnresolvedAddressException e) {
- // Correct result
- }
- dc.close();
- }
-}
--- a/test/jdk/java/nio/channels/Selector/CloseWhenKeyIdle.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/nio/channels/Selector/CloseWhenKeyIdle.java Fri Mar 23 18:44:47 2018 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -62,22 +62,6 @@
public static void main(String[] args) throws Exception {
- // Skip test on pre-2.6 kernels until the poll SelectorProvider
- // is updated
- String osname = System.getProperty("os.name");
- if (osname.equals("Linux")) {
- String[] ver = System.getProperty("os.version").split("\\.", 0);
- if (ver.length >=2 ) {
- int major = Integer.parseInt(ver[0]);
- int minor = Integer.parseInt(ver[1]);
- if (major < 2 || (major == 2 && minor < 6)) {
- System.out.println("Test passing on pre-2.6 kernel");
- return;
- }
- }
- }
-
-
// establish loopback connection
ServerSocketChannel ssc = ServerSocketChannel.open();
--- a/test/jdk/java/util/Collection/MOAT.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/util/Collection/MOAT.java Fri Mar 23 18:44:47 2018 +0000
@@ -26,7 +26,7 @@
* @bug 6207984 6272521 6192552 6269713 6197726 6260652 5073546 4137464
* 4155650 4216399 4294891 6282555 6318622 6355327 6383475 6420753
* 6431845 4802633 6570566 6570575 6570631 6570924 6691185 6691215
- * 4802647 7123424 8024709
+ * 4802647 7123424 8024709 8193128
* @summary Run many tests on many Collection and Map implementations
* @author Martin Buchholz
* @modules java.base/java.util:open
@@ -212,8 +212,11 @@
// Immutable List
testEmptyList(List.of());
+ testEmptyList(List.of().subList(0,0));
testListMutatorsAlwaysThrow(List.of());
+ testListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
testEmptyListMutatorsAlwaysThrow(List.of());
+ testEmptyListMutatorsAlwaysThrow(List.<Integer>of().subList(0,0));
for (List<Integer> list : Arrays.asList(
List.<Integer>of(),
List.of(1),
@@ -230,6 +233,17 @@
testCollection(list);
testImmutableList(list);
testListMutatorsAlwaysThrow(list);
+ if (list.size() >= 1) {
+ // test subLists
+ List<Integer> headList = list.subList(0, list.size() - 1);
+ List<Integer> tailList = list.subList(1, list.size());
+ testCollection(headList);
+ testCollection(tailList);
+ testImmutableList(headList);
+ testImmutableList(tailList);
+ testListMutatorsAlwaysThrow(headList);
+ testListMutatorsAlwaysThrow(tailList);
+ }
}
List<Integer> listCopy = List.copyOf(Arrays.asList(1, 2, 3));
@@ -243,6 +257,44 @@
testImmutableList(listCollected);
testListMutatorsAlwaysThrow(listCollected);
+ // List indexOf / lastIndexOf
+
+ // 0 element
+ System.out.println("testListIndexOf size 0");
+ testListIndexOf(-1, -1);
+
+ System.out.println("testListIndexOf size 1");
+ testListIndexOf(-1, -1, 0);
+ testListIndexOf(0, 0, 1);
+
+ System.out.println("testListIndexOf size 2");
+ testListIndexOf(-1, -1, 0, 0);
+ testListIndexOf(0, 0, 1, 0);
+ testListIndexOf(0, 1, 1, 1);
+ testListIndexOf(1, 1, 0, 1);
+
+
+ System.out.println("testListIndexOf size 3");
+ testListIndexOf(-1, -1, 0, 0, 0);
+ testListIndexOf(0, 0, 1, 0, 0);
+ testListIndexOf(0, 1, 1, 1, 0);
+ testListIndexOf(1, 2, 0, 1, 1);
+ testListIndexOf(2, 2, 0, 0, 1);
+
+ System.out.println("testListIndexOf size N");
+ testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0);
+ testListIndexOf(2, 6, 0, 0, 1, 0, 1, 0, 1);
+ testListIndexOf(4, 4, 0, 0, 0, 0, 1, 0, 0);
+ testListIndexOf(0, 6, 1, 1, 1, 1, 1, 1, 1);
+ testListIndexOf(0, 7, 1, 1, 1, 1, 1, 1, 1, 1);
+ testListIndexOf(0, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+ testListIndexOf(0, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+ testListIndexOf(0, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+ testListIndexOf(0, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+ testListIndexOf(0, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
+ testListIndexOf(12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+ testListIndexOf(-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
// Immutable Set
testEmptySet(Set.of());
testCollMutatorsAlwaysThrow(Set.of());
@@ -963,6 +1015,37 @@
equal(it.next(), 4);
}
+ // for any array of integer values, check that the result of lastIndexOf(1)
+ // and indexOf(1) match assumptions for all types of List<Integer> we can
+ // construct
+ private static void testListIndexOf(final int index,
+ final int lastIndex,
+ final Integer ... values) {
+ if (values.length == 0) {
+ checkListIndexOf(emptyList(), index, lastIndex);
+ } else if (values.length == 1) {
+ checkListIndexOf(singletonList(values[0]), index, lastIndex);
+ checkListIndexOf(nCopies(25, values[0]), index, lastIndex == 0 ? 24 : -1);
+ }
+ List<Integer> l = List.of(values);
+ checkListIndexOf(l, index, lastIndex);
+ checkListIndexOf(Arrays.asList(values), index, lastIndex);
+ checkListIndexOf(new ArrayList(l), index, lastIndex);
+ checkListIndexOf(new LinkedList(l), index, lastIndex);
+ checkListIndexOf(new Vector(l), index, lastIndex);
+ checkListIndexOf(new CopyOnWriteArrayList(l), index, lastIndex);
+ }
+
+ private static void checkListIndexOf(final List<Integer> list,
+ final int index,
+ final int lastIndex) {
+ String msg = list.getClass().toString();
+ equal(list.indexOf(1), index, msg);
+ equal(list.lastIndexOf(1), lastIndex, msg);
+ equal(list.subList(0, list.size()).indexOf(1), index, msg);
+ equal(list.subList(0, list.size()).lastIndexOf(1), lastIndex, msg);
+ }
+
private static void testList(final List<Integer> l) {
//----------------------------------------------------------------
// 4802633: (coll) AbstractList.addAll(-1,emptyCollection)
@@ -1629,6 +1712,9 @@
static void equal(Object x, Object y) {
if (x == null ? y == null : x.equals(y)) pass();
else {System.out.println(x + " not equal to " + y); fail();}}
+ static void equal(Object x, Object y, String msg) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else {System.out.println(x + " not equal to " + y + " : " + msg); fail();}}
static void equal2(Object x, Object y) {equal(x, y); equal(y, x);}
public static void main(String[] args) throws Throwable {
try { realMain(args); } catch (Throwable t) { unexpected(t); }
--- a/test/jdk/java/util/Collection/SetFactories.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/util/Collection/SetFactories.java Fri Mar 23 18:44:47 2018 +0000
@@ -266,6 +266,11 @@
Set.of((Object[])null);
}
+ @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+ public void containsNullShouldThrowNPE(Set<String> act, Set<String> exp) {
+ act.contains(null);
+ }
+
@Test(dataProvider="all")
public void serialEquality(Set<String> act, Set<String> exp) {
// assume that act.equals(exp) tested elsewhere
--- a/test/jdk/java/util/List/ListFactories.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/util/List/ListFactories.java Fri Mar 23 18:44:47 2018 +0000
@@ -26,6 +26,7 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -72,7 +73,7 @@
@DataProvider(name="empty")
public Iterator<Object[]> empty() {
return Collections.singletonList(
- a(List.of(), Collections.emptyList())
+ a(List.of(), asList())
).iterator();
}
@@ -104,11 +105,50 @@
).iterator();
}
+ @DataProvider(name="sublists")
+ public Iterator<Object[]> sublists() {
+ return asList(
+ a(List.<String>of().subList(0,0),
+ asList()),
+ a(List.of("a").subList(0,0),
+ asList("a").subList(0,0)),
+ a(List.of("a", "b").subList(0,1),
+ asList("a", "b").subList(0,1)),
+ a(List.of("a", "b", "c").subList(1,3),
+ asList("a", "b", "c").subList(1,3)),
+ a(List.of("a", "b", "c", "d").subList(0,4),
+ asList("a", "b", "c", "d").subList(0,4)),
+ a(List.of("a", "b", "c", "d", "e").subList(0,3),
+ asList("a", "b", "c", "d", "e").subList(0,3)),
+ a(List.of("a", "b", "c", "d", "e", "f").subList(3, 5),
+ asList("a", "b", "c", "d", "e", "f").subList(3, 5)),
+ a(List.of("a", "b", "c", "d", "e", "f", "g").subList(0, 7),
+ asList("a", "b", "c", "d", "e", "f", "g").subList(0, 7)),
+ a(List.of("a", "b", "c", "d", "e", "f", "g", "h").subList(0, 0),
+ asList("a", "b", "c", "d", "e", "f", "g", "h").subList(0, 0)),
+ a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i").subList(4, 5),
+ asList("a", "b", "c", "d", "e", "f", "g", "h", "i").subList(4, 5)),
+ a(List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j").subList(1,10),
+ asList("a", "b", "c", "d", "e", "f", "g", "h", "i", "j").subList(1,10)),
+ a(List.of(stringArray).subList(5, NUM_STRINGS),
+ asList(Arrays.copyOfRange(stringArray, 5, NUM_STRINGS)))
+ ).iterator();
+ }
+
@DataProvider(name="all")
public Iterator<Object[]> all() {
List<Object[]> all = new ArrayList<>();
empty().forEachRemaining(all::add);
nonempty().forEachRemaining(all::add);
+ sublists().forEachRemaining(all::add);
+ return all.iterator();
+ }
+
+ @DataProvider(name="nonsublists")
+ public Iterator<Object[]> nonsublists() {
+ List<Object[]> all = new ArrayList<>();
+ empty().forEachRemaining(all::add);
+ nonempty().forEachRemaining(all::add);
return all.iterator();
}
@@ -212,7 +252,29 @@
assertEquals(list, Arrays.asList(stringArray));
}
- @Test(dataProvider="all")
+ @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+ public void containsNullShouldThrowNPE(List<String> act, List<String> exp) {
+ act.contains(null);
+ }
+
+ @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+ public void indexOfNullShouldThrowNPE(List<String> act, List<String> exp) {
+ act.indexOf(null);
+ }
+
+ @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+ public void lastIndexOfNullShouldThrowNPE(List<String> act, List<String> exp) {
+ act.lastIndexOf(null);
+ }
+
+ // List.of().subList views should not be Serializable
+ @Test(dataProvider="sublists")
+ public void isNotSerializable(List<String> act, List<String> exp) {
+ assertFalse(act instanceof Serializable);
+ }
+
+ // ... but List.of() should be
+ @Test(dataProvider="nonsublists")
public void serialEquality(List<String> act, List<String> exp) {
// assume that act.equals(exp) tested elsewhere
List<String> copy = serialClone(act);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/Locale/LocaleCmdOverrides.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 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
+ * 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.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.List;
+
+/*
+ * @test
+ * @modules java.management
+ * @summary verify that overriddes on the command line affect *.display and *.format properties
+ * @run main/othervm
+ * LocaleCmdOverrides
+ * @run main/othervm -Duser.language=XX
+ * -Duser.country=X1
+ * -Duser.script=X2
+ * -Duser.variant=X3
+ * LocaleCmdOverrides
+ * @run main/othervm -Duser.language=XX -Duser.language.display=YY
+ * -Duser.country=X1 -Duser.country.display=Y1
+ * -Duser.script=X2 -Duser.script.display=Y2
+ * -Duser.variant=X3 -Duser.variant.display=Y3
+ * LocaleCmdOverrides
+ * @run main/othervm -Duser.language=XX -Duser.language.display=YY -Duser.language.format=ZZ
+ * -Duser.country=X1 -Duser.country.display=Y1 -Duser.country.format=Z1
+ * -Duser.script=X2 -Duser.script.display=Y2 -Duser.script.format=Z2
+ * -Duser.variant=X3 -Duser.variant.display=Y3 -Duser.variant.format=Z3
+ * LocaleCmdOverrides
+ * @run main/othervm -Duser.language=XX -Duser.language.format=ZZ
+ * -Duser.country=X1 -Duser.country.format=Z1
+ * -Duser.script=X2 -Duser.script.format=Z2
+ * -Duser.variant=X3 -Duser.variant.format=Z3
+ * LocaleCmdOverrides
+ * @run main/othervm -Duser.language=XX -Duser.language.display=XX
+ * -Duser.country=X1 -Duser.country.display=X1
+ * -Duser.script=X2 -Duser.script.display=X2
+ * -Duser.variant=X3 -Duser.variant.display=X3
+ * LocaleCmdOverrides
+ * @run main/othervm -Duser.language=XX -Duser.language.display=XX -Duser.language.format=XX
+ * -Duser.country=X1 -Duser.country.display=X1 -Duser.country.format=X1
+ * -Duser.script=X2 -Duser.script.display=X2 -Duser.script.format=X2
+ * -Duser.variant=X3 -Duser.variant.display=X3 -Duser.variant.format=X3
+ * LocaleCmdOverrides
+ * @run main/othervm -Duser.language=XX -Duser.language.format=X1
+ * -Duser.country.format=X1
+ * -Duser.script.format=X2
+ * -Duser.variant.format=X3
+ * LocaleCmdOverrides
+ */
+public class LocaleCmdOverrides {
+
+ // Language, country, script, variant
+
+ public static void main(String[] args) {
+ Map<String, String> props = commandLineDefines();
+ System.out.printf("props: %s%n", props);
+ test("user.language", props);
+ test("user.country", props);
+ test("user.script", props);
+ test("user.variant", props);
+ }
+
+ /*
+ * Check each of the properties for a given basename.
+ */
+ static void test(String baseName, Map<String, String> args) {
+ validateArg(baseName,"", args);
+ validateArg(baseName,".display", args);
+ validateArg(baseName,".format", args);
+ }
+
+ // If an argument is -D defined, the corresponding property must be equal
+ static void validateArg(String name, String ext, Map<String, String> args) {
+ String extName = name.concat(ext);
+ String arg = args.get(extName);
+ String prop = System.getProperty(extName);
+ if (arg == null && prop == null) {
+ System.out.printf("No values for %s%n", extName);
+ } else {
+ System.out.printf("validateArg %s: arg: %s, prop: %s%n", extName, arg, prop);
+ }
+
+ if (arg != null) {
+ if (!Objects.equals(arg, prop)) {
+ throw new RuntimeException(extName + ": -D value should match property: "
+ + arg + " != " + prop);
+ }
+ } else if (prop != null) {
+ // no command line arg for extName and some value for prop
+ // Check that if a property is not overridden then it is not equal to the base
+ if (ext != null && !ext.isEmpty()) {
+ String value = System.getProperty(name);
+ if (Objects.equals(value, prop)) {
+ throw new RuntimeException(extName + " property should not be equals to "
+ + name + " property: " + prop);
+ }
+ }
+ }
+ }
+
+ /**
+ * Extract the -D arguments from the command line and return a map of key, value.
+ * @return a map of key, values defined by -D on the command line.
+ */
+ static HashMap<String, String> commandLineDefines() {
+ HashMap<String, String> props = new HashMap<>();
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ List<String> args = runtime.getInputArguments();
+ System.out.printf("args: %s%n", args);
+ for (String arg : args) {
+ if (arg.startsWith("-Duser.")) {
+ String[] kv = arg.substring(2).split("=");
+ switch (kv.length) {
+ case 1:
+ props.put(kv[0], "");
+ break;
+ case 2:
+ props.put(kv[0], kv[1]);
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal property syntax: " + arg);
+ }
+ }
+ }
+ return props;
+ }
+}
--- a/test/jdk/java/util/Map/MapFactories.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/jdk/java/util/Map/MapFactories.java Fri Mar 23 18:44:47 2018 +0000
@@ -376,6 +376,16 @@
Map.ofEntries((Map.Entry<?,?>[])null);
}
+ @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+ public void containsValueNullShouldThrowNPE(Map<Integer,String> act, Map<Integer,String> exp) {
+ act.containsValue(null);
+ }
+
+ @Test(dataProvider="all", expectedExceptions=NullPointerException.class)
+ public void containsKeyNullShouldThrowNPE(Map<Integer,String> act, Map<Integer,String> exp) {
+ act.containsKey(null);
+ }
+
@Test(dataProvider="all")
public void serialEquality(Map<Integer, String> act, Map<Integer, String> exp) {
// assume that act.equals(exp) tested elsewhere
Binary file test/jdk/javax/imageio/plugins/bmp/DIB_size-56_ARGB_16bits.bmp has changed
Binary file test/jdk/javax/imageio/plugins/bmp/DIB_size-56_RGB_16bits.bmp has changed
Binary file test/jdk/javax/imageio/plugins/bmp/DIB_size-56_XRGB_32bits.bmp has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/imageio/plugins/bmp/ReadBITMAPV3INFOHEADERTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 7031957
+ * @summary Test verifies whether BMPImageReader is capable of reading
+ * images with DIB header type BITMAPV3INFOHEADER.
+ * @run main ReadBITMAPV3INFOHEADERTest
+ */
+
+import javax.imageio.ImageIO;
+import java.io.File;
+import java.io.IOException;
+
+public class ReadBITMAPV3INFOHEADERTest {
+ public static void main(String[] args) throws IOException {
+ String dir = System.getProperty("test.src");
+ String sep = System.getProperty("file.separator");
+ /*
+ * Try reading BITMAPV3INFOHEADER type BMP images and check whether
+ * read fails. If read fails we throw Exception.
+ */
+ ImageIO.read(new File(dir + sep + "DIB_size-56_ARGB_16bits.bmp"));
+ ImageIO.read(new File(dir + sep + "DIB_size-56_RGB_16bits.bmp"));
+ ImageIO.read(new File(dir + sep + "DIB_size-56_XRGB_32bits.bmp"));
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/imageio/plugins/gif/GIFCharCellDimensionTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6686236
+ * @summary Checks whether GIF native metadata format returns appropriate max
+ * value that could be set for characterCellWidth and
+ * characterCellHeight attributes of PlainTextExtension node. Besides,
+ * the test also checks whether IIOInvalidTreeException is thrown when
+ * incorrect value is set on these two attributes.
+ * @run main GIFCharCellDimensionTest
+ */
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriter;
+import javax.imageio.ImageTypeSpecifier;
+import javax.imageio.metadata.IIOInvalidTreeException;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataNode;
+import javax.imageio.metadata.IIOMetadataFormat;
+import java.util.Iterator;
+import java.awt.image.BufferedImage;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
+
+public class GIFCharCellDimensionTest {
+ // GIF image metadata and native metadata format.
+ private static IIOMetadata imageMetadata = null;
+ private static IIOMetadataFormat metadataFormat = null;
+ private static String formatName = null;
+
+ private static void initializeTest() {
+ // Initialize the test case by querying GIF image writer for default
+ // image metadata and native metadata format.
+ ImageWriter gifWriter = null;
+ Iterator<ImageWriter> iterGifWriter = null;
+ BufferedImage bufImage = null;
+ ImageTypeSpecifier imageType = null;
+
+ try {
+ iterGifWriter = ImageIO.getImageWritersBySuffix("GIF");
+ if (iterGifWriter.hasNext()) {
+ gifWriter = iterGifWriter.next();
+ bufImage = new BufferedImage(32, 32, TYPE_4BYTE_ABGR);
+
+ // Get GIF image metadata
+ imageMetadata = gifWriter.getDefaultImageMetadata(
+ ImageTypeSpecifier.createFromRenderedImage(bufImage),
+ gifWriter.getDefaultWriteParam());
+ if (imageMetadata == null) {
+ reportException("Test Failed. Could not get image" +
+ " metadata.");
+ }
+
+ // Get GIF native metadata format.
+ formatName = imageMetadata.getNativeMetadataFormatName();
+ metadataFormat = imageMetadata.getMetadataFormat(formatName);
+ if (metadataFormat == null) {
+ reportException("Test Failed. Could not get native" +
+ " metadata format.");
+ }
+ } else {
+ reportException("Test Failed. No GIF image writer found.");
+ }
+ } finally {
+ gifWriter.dispose();
+ }
+ }
+
+ private static IIOMetadataNode createPlainTextExtensionNode(String value) {
+ // Create a PlainTextExtensionNode with required values
+ IIOMetadataNode rootNode = null;
+
+ if (imageMetadata != null && formatName != null) {
+ IIOMetadataNode plainTextNode = null;
+
+ rootNode = new IIOMetadataNode(formatName);
+ plainTextNode = new IIOMetadataNode("PlainTextExtension");
+ plainTextNode.setAttribute("textGridLeft", "0");
+ plainTextNode.setAttribute("textGridTop", "0");
+ plainTextNode.setAttribute("textGridWidth", "32");
+ plainTextNode.setAttribute("textGridHeight", "32");
+ // Set required values for cell width and cell height
+ plainTextNode.setAttribute("characterCellWidth", value);
+ plainTextNode.setAttribute("characterCellHeight", value);
+ plainTextNode.setAttribute("textForegroundColor", "0");
+ plainTextNode.setAttribute("textBackgroundColor", "1");
+ rootNode.appendChild(plainTextNode);
+ } else {
+ reportException("Test Failed. Un-initialized image metadata.");
+ }
+
+ return rootNode;
+ }
+
+ private static void testCharacterCellDimensions() {
+ if (imageMetadata != null && metadataFormat != null) {
+ // Get max permissible value that could be set on characterCellWidth
+ // and characterCellHeight attributes of plain text node.
+ String cellWidth = metadataFormat.getAttributeMaxValue(
+ "PlainTextExtension",
+ "characterCellWidth");
+ String cellHeight = metadataFormat.getAttributeMaxValue(
+ "PlainTextExtension",
+ "characterCellHeight");
+
+ // Test fails if the max permissible value is larger than 255
+ int maxCharCellWidth = Integer.parseInt(cellWidth);
+ int maxCharCellHeight = Integer.parseInt(cellHeight);
+ if (maxCharCellWidth > 255 || maxCharCellHeight > 255) {
+ reportException("Test Failed. Invalid max range for" +
+ " character cell width or character cell height.");
+ }
+
+ try {
+ // Merge a plain text node with incorrect value set on
+ // characterCellWidth and characterCellHeight attributes.
+ IIOMetadataNode root = createPlainTextExtensionNode("256");
+ imageMetadata.setFromTree(formatName, root);
+ } catch (IIOInvalidTreeException exception) {
+ // No-op. Expected exception was thrown.
+ }
+ } else {
+ reportException("Test Failed. Un-initialized image metadata or" +
+ " metadata format.");
+ }
+ }
+
+ private static void reportException(String message) {
+ // Report an exception with the required message.
+ throw new RuntimeException(message);
+ }
+
+ public static void main(String[] args) {
+ // Initialize the test
+ initializeTest();
+
+ // Test plain text extension node.
+ testCharacterCellDimensions();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JEditorPane/8195095/ImageViewTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @key headful
+ * @bug 8195095
+ * @summary Tests if Images are scaled correctly in JEditorPane.
+ * @run main ImageViewTest
+ */
+import java.awt.Robot;
+import java.awt.Point;
+import java.awt.Color;
+import java.awt.Insets;
+
+import javax.swing.JEditorPane;
+import javax.swing.SwingUtilities;
+import javax.swing.JFrame;
+import javax.swing.WindowConstants;
+
+public class ImageViewTest {
+
+ private static final int WIDTH = 200;
+ private static final int HEIGHT = 200;
+ private static JFrame f;
+
+ private static JEditorPane editorPane1;
+ private static JEditorPane editorPane2;
+ private static JEditorPane editorPane3;
+ private static JEditorPane editorPane4;
+
+ private static void test(Robot r, JEditorPane editorPane) throws Exception {
+
+ SwingUtilities.invokeAndWait(() -> {
+ f = new JFrame();
+ editorPane.setEditable(false);
+ f.add(editorPane);
+ f.setSize(220,240);
+ f.setLocationRelativeTo(null);
+
+ f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ f.setVisible(true);
+ });
+
+ r.waitForIdle();
+ r.delay(500);
+
+ SwingUtilities.invokeAndWait(() -> {
+ Insets insets = editorPane.getInsets();
+ Point loc = editorPane.getLocationOnScreen();
+
+ final Color blue = Color.BLUE;
+ final int offset = 10;
+
+ Color center = r.getPixelColor(loc.x + insets.left + WIDTH / 2,
+ loc.y + insets.top + HEIGHT / 2);
+ Color left = r.getPixelColor(loc.x + insets.left + offset,
+ loc.y + insets.top + HEIGHT / 2);
+ Color right = r.getPixelColor(loc.x + insets.left + WIDTH - offset,
+ loc.y + insets.top + HEIGHT / 2);
+ Color bottom = r.getPixelColor(loc.x + insets.left + WIDTH / 2,
+ loc.y + insets.top + HEIGHT - offset);
+ Color top = r.getPixelColor(loc.x + insets.left + WIDTH / 2,
+ loc.y + insets.top + offset);
+
+ f.dispose();
+
+ System.out.println("center color: " + center);
+ System.out.println("left color: " + left);
+ System.out.println("right color: " + right);
+ System.out.println("bottom color: " + bottom);
+ System.out.println("top color: " + top);
+ System.out.println();
+
+ if (!(blue.equals(center) && blue.equals(left) && blue.equals(right) &&
+ blue.equals(top) && blue.equals(bottom))) {
+ throw new RuntimeException("Test failed: Image not scaled correctly");
+ }
+ });
+
+ r.waitForIdle();
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ final String ABSOLUTE_FILE_PATH = ImageViewTest.class.getResource("circle.png").getPath();
+
+ System.out.println(ABSOLUTE_FILE_PATH);
+
+ Robot r = new Robot();
+
+ SwingUtilities.invokeAndWait(() -> {
+ editorPane1 = new JEditorPane("text/html",
+ "<img height=\"200\" src=\"file:///" + ABSOLUTE_FILE_PATH + "\"");
+
+ editorPane2 = new JEditorPane("text/html",
+ "<img width=\"200\" src=\"file:///" + ABSOLUTE_FILE_PATH + "\"");
+
+ editorPane3 = new JEditorPane("text/html",
+ "<img width=\"200\" height=\"200\" src=\"file:///" + ABSOLUTE_FILE_PATH + "\"");
+
+ editorPane4 = new JEditorPane("text/html",
+ "<img src=\"file:///" + ABSOLUTE_FILE_PATH + "\"");
+
+ });
+
+ r.waitForIdle();
+
+ System.out.println("Test with only height set to 200");
+ test(r, editorPane1);
+
+ System.out.println("Test with only width set to 200");
+ test(r, editorPane2);
+
+ System.out.println("Test with none of them set");
+ test(r, editorPane3);
+
+ System.out.println("Test with both of them set to 200");
+ test(r, editorPane4);
+
+ System.out.println("Test Passed.");
+ }
+}
Binary file test/jdk/javax/swing/JEditorPane/8195095/circle.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JList/GetSelectedValueTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+/*
+ * @test
+ * @key headful
+ * @bug 7108280
+ * @summary Verifies that getSelectedValue works fine without crash when
+ * the setSelectionInterval was called with indices outside the
+ * range of data present in DataModel
+ * @run main GetSelectedValueTest
+ */
+
+import javax.swing.SwingUtilities;
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+import javax.swing.ListSelectionModel;
+import java.util.Objects;
+
+public class GetSelectedValueTest {
+ public static void main(String[] args) throws Exception {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ // Create a JList with 2 elements
+ DefaultListModel dlm = new DefaultListModel();
+ JList list = new JList<String>(dlm);
+ list.setSelectionMode(
+ ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ dlm.addElement("1");
+ dlm.addElement("2");
+
+ // Set the selection interval from 0-2 (3 elements instead
+ // of 2). The getSelectedValue should return the first
+ // selected element
+ list.setSelectionInterval(0, 2);
+ checkSelectedIndex(list, "1");
+
+ //here the smallest selection index is bigger than number of
+ // elements in list. This should return null.
+ list.setSelectionInterval(4, 5);
+ checkSelectedIndex(list,null);
+ }
+ });
+ }
+
+ static void checkSelectedIndex(JList list, Object value)
+ throws RuntimeException {
+ Object selectedObject = list.getSelectedValue();
+ if (!Objects.equals(value, selectedObject)) {
+ System.out.println("Expected: " + value);
+ System.out.println("Actual: " + selectedObject);
+ throw new RuntimeException("Wrong selection");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JList/GetSelectedValuesListTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+/*
+ * @test
+ * @key headful
+ * @bug 7108280
+ * @summary Verifies that getSelectedValuesList works fine without crash when
+ * the setSelectionInterval was called with indices outside the
+ * range of data present in DataModel
+ * @run main GetSelectedValuesListTest
+ */
+
+import javax.swing.SwingUtilities;
+import javax.swing.DefaultListModel;
+import javax.swing.JList;
+import javax.swing.ListSelectionModel;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+
+public class GetSelectedValuesListTest {
+ public static void main(String[] args) throws Exception {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ // Create a JList with 2 elements
+ DefaultListModel dlm = new DefaultListModel();
+ JList list = new JList<String>(dlm);
+ list.setSelectionMode(
+ ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ dlm.addElement("1");
+ dlm.addElement("2");
+
+ // Set the selection interval from 0-2 (3 elements instead
+ // of 2). The getSelectedValuesList should return the list of
+ // objects present in the list in the given interval
+ list.setSelectionInterval(0, 2);
+ checkSelection(list, List.of("1", "2"));
+
+ //here the selection interval is set greater than number of
+ // elements in list. This should return empty list
+ list.setSelectionInterval(4, 10);
+ checkSelection(list, Collections.emptyList());
+
+ // This will set the selection interval from 0 to 2 index.
+ // The getSelectedValuesList should return the list of
+ // objects present in the list in the given interval
+ list.getSelectionModel().setSelectionInterval(0, 2);
+ checkSelection(list, List.of("1", "2"));
+ }
+ });
+ }
+
+ static void checkSelection(JList list, List<String> selectionList)
+ throws RuntimeException
+ {
+ List<String> listSelection = list.getSelectedValuesList();
+ if (!listSelection.equals(selectionList)) {
+ System.out.println("Expected: " + selectionList);
+ System.out.println("Actual: " + listSelection);
+ throw new RuntimeException("Wrong selection from " +
+ "getSelectedValuesList");
+ }
+
+ Object[] arraySelection = list.getSelectedValues();
+ if (!Arrays.equals(arraySelection, selectionList.toArray())) {
+ System.out.println("Expected: " + selectionList);
+ System.out.println("Actual: " + Arrays.asList(arraySelection));
+ throw new RuntimeException("Wrong selection from " +
+ "getSelectedValues");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/SwingSet/src/TableDemoTest.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+import static com.sun.swingset3.demos.table.TableDemo.COLUMN1_NAME;
+import static com.sun.swingset3.demos.table.TableDemo.COLUMN2_NAME;
+import static com.sun.swingset3.demos.table.TableDemo.COLUMN3_NAME;
+import static com.sun.swingset3.demos.table.TableDemo.COLUMN4_NAME;
+import static com.sun.swingset3.demos.table.TableDemo.DEMO_TITLE;
+import static com.sun.swingset3.demos.table.TableDemo.ROW_HEIGHT;
+import static org.jemmy2ext.JemmyExt.EXACT_STRING_COMPARATOR;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JTable;
+
+import org.jtregext.GuiTestListener;
+import org.netbeans.jemmy.ClassReference;
+import org.netbeans.jemmy.operators.JCheckBoxOperator;
+import org.netbeans.jemmy.operators.JFrameOperator;
+import org.netbeans.jemmy.operators.JTableHeaderOperator;
+import org.netbeans.jemmy.operators.JTableOperator;
+import org.netbeans.jemmy.operators.JTextFieldOperator;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+import com.sun.swingset3.demos.table.OscarCandidate;
+import com.sun.swingset3.demos.table.OscarTableModel;
+import com.sun.swingset3.demos.table.TableDemo;
+
+/*
+ * @test
+ * @key headful
+ * @summary Verifies SwingSet3 TableDemo page by checking different properties
+ * of the JTable like number of row, number of columns and actions like
+ * selection of cell, sorting based on column, filtering based on text and
+ * moving of the column
+ *
+ * @library /sanity/client/lib/jemmy/src
+ * @library /sanity/client/lib/Extensions/src
+ * @library /sanity/client/lib/SwingSet3/src
+ * @modules java.desktop
+ * java.logging
+ * @build org.jemmy2ext.JemmyExt
+ * @build com.sun.swingset3.demos.table.TableDemo
+ * @run testng TableDemoTest
+ */
+@Listeners(GuiTestListener.class)
+public class TableDemoTest {
+
+ private final static int MAX_ROW_COUNT = 524;
+ private final static int MAX_COL_COUNT = 4;
+
+ private final static String FILTER_TEXT = "Sunrise";
+ private final static String FILTER_RESET_TEXT = "";
+
+ private final static int [] SELECT_ROW_INDICES ={10, 11, 18};
+
+ private final static int MOVE_COL_START_INDEX = 1;
+ private final static int MOVE_COL_END_INDEX = 2;
+ private final static String MOVE_COL_VAL_TEXT1 = "Sunrise";
+ private final static String MOVE_COL_VAL_TEXT2 = "Most Unique Artistic Picture";
+ private final static int MOVE_COL_VAL_ROW = 0;
+
+ private final static int SORT_COL = 1;
+ private final static int[] SORT_VAL_ROWS =new int[] {0, 250, 523};
+ private final static String[][] ASC_PRE_SORT_ROW_VAL = new String[][] {
+ {"1928", "Best Actor", "The Way of All Flesh", "[Emil Jannings]"},
+ {"1933", "Best Director", "Cavalcade", "[Frank Lloyd]"},
+ {"1936", "Best Engineering Effects", "My Man Godfrey", "[Eric Hatch, Morris Ryskind]"}};
+ private final static String[][] ASC_POST_SORT_ROW_VAL = new String[][] {
+ {"1928", "Best Actor", "The Way of All Flesh", "[Emil Jannings]"},
+ {"1936", "Best Director", "My Man Godfrey", "[Gregory La Cava]"},
+ {"1928", "Most Unique Artistic Picture", "The Crowd", "[]"}};
+ private final static String[][] DESC_POST_SORT_ROW_VAL = new String[][] {
+ {"1928", "Most Unique Artistic Picture", "Sunrise", "[]"},
+ {"1934", "Best Engineering Effects", "Viva Villa!", "[Ben Hecht]"},
+ {"1936", "Best Actor", "San Francisco", "[Spencer Tracy]"}};
+
+ /**
+ * Tests the different properties of JTable like number of rows, number
+ * of columns and actions like selection of cell, sorting based on column,
+ * filtering based on text and moving of the column.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void test() throws Exception {
+
+ new ClassReference(TableDemo.class.getCanonicalName()).startApplication();
+
+ JFrameOperator frameOperator = new JFrameOperator(DEMO_TITLE);
+ frameOperator.setComparator(EXACT_STRING_COMPARATOR);
+ frameOperator.setVerification(true);
+ JTableOperator tableOperator = new JTableOperator(frameOperator);
+ JTableHeaderOperator tableHeaderOperator = new JTableHeaderOperator(frameOperator);
+
+ checkTableBasicProperties(tableOperator);
+ checkCellSelection(tableOperator);
+ checkSortTable(tableOperator, tableHeaderOperator);
+ checkMoveColumn(tableOperator, tableHeaderOperator);
+ checkFilterTable(frameOperator, tableOperator);
+ }
+
+ /**
+ * Verifies the table basic properties number of columns, rows and row height
+ *
+ * @param tableOperator
+ */
+ private void checkTableBasicProperties(JTableOperator tableOperator) {
+ tableOperator.waitStateOnQueue(comp
+ -> MAX_COL_COUNT == ((JTable)comp).getColumnCount());
+ waitRowCount(tableOperator, MAX_ROW_COUNT);
+ tableOperator.waitStateOnQueue(comp
+ -> ROW_HEIGHT == ((JTable)comp).getRowHeight());
+ }
+
+ /**
+ * Selects one table cell and verifies the selected cell's row number and column number
+ *
+ * @param tableOperator
+ */
+ private void checkCellSelection(JTableOperator tableOperator) {
+ int noOfColumns = tableOperator.getColumnCount();
+ for (int i = 0; i < SELECT_ROW_INDICES.length; i++) {
+ int rowIndex = SELECT_ROW_INDICES[i];
+ for (int j = 0; j < noOfColumns; j++) {
+ int colIndex = j;
+ tableOperator.clickOnCell(rowIndex, colIndex);
+ tableOperator.waitStateOnQueue(comp
+ -> rowIndex == ((JTable)comp).getSelectedRow() &&
+ colIndex == ((JTable)comp).getSelectedColumn());
+ }
+ }
+ }
+
+ /**
+ * Filter table based on specific text and winners check box, and verifies row count
+ *
+ * @param frameOperator
+ * @param tableOperator
+ */
+ private void checkFilterTable(JFrameOperator frameOperator,
+ JTableOperator tableOperator) {
+
+ int [] filterRowCount = getFilteredCount(tableOperator, FILTER_TEXT);
+ JTextFieldOperator filterField = new JTextFieldOperator(frameOperator);
+ JCheckBoxOperator winnersCheckbox = new JCheckBoxOperator(frameOperator);
+
+ // Filtering based on FILTER_TEXT
+ filterField.setText(FILTER_TEXT);
+ waitRowCount(tableOperator, filterRowCount[0]);
+
+ // Filtering based on WinnersCheckbox
+ winnersCheckbox.setSelected(true);
+ waitRowCount(tableOperator, filterRowCount[1]);
+
+ // Resets the winners check box
+ winnersCheckbox.setSelected(false);
+ waitRowCount(tableOperator, filterRowCount[0]);
+
+ // Resets the filter text field
+ filterField.setText(FILTER_RESET_TEXT);
+ waitRowCount(tableOperator, MAX_ROW_COUNT);
+
+ }
+
+ private int[] getFilteredCount(JTableOperator tableOperator, String filterText){
+ OscarTableModel tableModel = (OscarTableModel)tableOperator.getModel();
+ int noOfRows = tableModel.getRowCount();
+ int filteredRowCount = 0;
+ int filteredWinnersRowCount = 0;
+ for (int i = 0; i < noOfRows; i++) {
+ OscarCandidate candidate = tableModel.getCandidate(i);
+ if(isMovieOrPersonsContainsText(candidate, filterText)){
+ filteredRowCount++;
+ if(candidate.isWinner()) {
+ filteredWinnersRowCount++;
+ }
+ }
+ }
+ return new int[] {filteredRowCount, filteredWinnersRowCount};
+ }
+
+ private boolean isMovieOrPersonsContainsText(
+ OscarCandidate candidate, String filterText){
+ String movie = candidate.getMovieTitle();
+ if(movie != null && movie.contains(filterText)) {
+ return true;
+ } else {
+ List<String> persons = candidate.getPersons();
+ for (String person : persons) {
+ if(person != null && person.contains(filterText)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Moves to swap the columns, move again to reset back, verify column name
+ * and cell values in both the scenarios.
+ *
+ * @param tableOperator
+ * @param tableHeaderOperator
+ */
+ private void checkMoveColumn(JTableOperator tableOperator,
+ JTableHeaderOperator tableHeaderOperator) {
+
+ String[] columnNames = {COLUMN1_NAME, COLUMN3_NAME, COLUMN2_NAME, COLUMN4_NAME};
+ // Moving the column from 'start index' to 'end index'
+ moveColumn(tableOperator, tableHeaderOperator, columnNames,
+ MOVE_COL_START_INDEX, MOVE_COL_END_INDEX);
+
+ // Resets the columns to original position(from 'end index' to 'start index')
+ columnNames[1] = COLUMN2_NAME;
+ columnNames[2] = COLUMN3_NAME;
+ moveColumn(tableOperator, tableHeaderOperator, columnNames,
+ MOVE_COL_END_INDEX, MOVE_COL_START_INDEX);
+ }
+
+ /**
+ * Moves to swap the columns, verify column name and cell values.
+ *
+ * @param tableOperator
+ * @param tableHeaderOperator
+ * @param columnNames
+ * @param moveCol
+ * @param moveToCol
+ */
+ private void moveColumn(JTableOperator tableOperator, JTableHeaderOperator tableHeaderOperator,
+ String[] columnNames, int moveCol, int moveToCol){
+
+ tableHeaderOperator.moveColumn(moveCol, moveToCol);
+ checkColumnNames(tableOperator, columnNames);
+ tableOperator.waitCell(MOVE_COL_VAL_TEXT1, MOVE_COL_VAL_ROW, moveCol);
+ tableOperator.waitCell(MOVE_COL_VAL_TEXT2, MOVE_COL_VAL_ROW, moveToCol);
+ }
+
+ private void checkColumnNames(JTableOperator tableOperator, String[] columnNames) {
+ for (int i = 0; i < tableOperator.getColumnCount(); i++) {
+ int columnIndex = i;
+ tableOperator.waitStateOnQueue(comp -> columnNames[columnIndex].equals(
+ ((JTable)comp).getColumnModel().getColumn(columnIndex).getHeaderValue()));
+ }
+ }
+
+ /**
+ * Sorts the table based on one particular column in ascending and descending order,
+ * and verifies cell values
+ *
+ * @param tableOperator
+ * @param tableHeaderOperator
+ */
+ private void checkSortTable(JTableOperator tableOperator,
+ JTableHeaderOperator tableHeaderOperator) {
+
+ // Verifying the row values before sort
+ checkTableRows(tableOperator, ASC_PRE_SORT_ROW_VAL);
+
+ // Getting all award category values before stating the sort
+ // to prepare the expected result
+ ArrayList<String> awardCats = new ArrayList<>();
+ for (int i = 0; i < tableOperator.getRowCount(); i++) {
+ awardCats.add((String) tableOperator.getValueAt(i, SORT_COL));
+ }
+ // Sorting awardCats(expected result) in ascending order
+ awardCats.sort((s1, s2) -> s1.compareTo(s2));
+
+ // Sorting table based on column 'Award Category' in ascending order
+ sortTable(tableOperator, tableHeaderOperator, awardCats,
+ ASC_POST_SORT_ROW_VAL);
+
+ // Sorting awardCats(expected result) in descending order
+ awardCats.sort((s1, s2) -> s2.compareTo(s1));
+ // Sorting table based on column 'Award Category' in descending order
+ sortTable(tableOperator, tableHeaderOperator, awardCats,
+ DESC_POST_SORT_ROW_VAL);
+
+ }
+
+ private void checkColumnSorted(JTableOperator tableOperator,
+ ArrayList<String> awardCatExp){
+ ArrayList<String> awardCatActual = new ArrayList<>();
+ for (int i = 0; i < tableOperator.getRowCount(); i++) {
+ awardCatActual.add((String) tableOperator.getValueAt(i, SORT_COL));
+ }
+ tableOperator.waitStateOnQueue(comp -> awardCatExp.equals(awardCatActual));
+ }
+
+ private void checkTableRows(JTableOperator tableOperator, String[][] rowValues) {
+ for (int i = 0; i < SORT_VAL_ROWS.length; i++) {
+ tableOperator.waitCell(rowValues[i][0], SORT_VAL_ROWS[i], 0);
+ tableOperator.waitCell(rowValues[i][1], SORT_VAL_ROWS[i], 1);
+ tableOperator.waitCell(rowValues[i][2], SORT_VAL_ROWS[i], 2);
+ tableOperator.waitCell(rowValues[i][3], SORT_VAL_ROWS[i], 3);
+ }
+ }
+
+ /**
+ * Sorts the table based on one particular column and verifies cell values
+ *
+ * @param tableOperator
+ * @param tableHeaderOperator
+ * @param awardCatExp
+ * @param rowValues
+ */
+ private void sortTable(JTableOperator tableOperator, JTableHeaderOperator tableHeaderOperator,
+ ArrayList<String> awardCatExp, String[][] rowValues) {
+
+ tableHeaderOperator.selectColumn(SORT_COL);
+ checkColumnSorted(tableOperator, awardCatExp);
+ // Verifying the row values after sort
+ checkTableRows(tableOperator, rowValues);
+ }
+
+ /**
+ * Waits the number of rows on table equal to the count specified
+ *
+ * @param tableOperator
+ * @param count
+ */
+ private void waitRowCount(JTableOperator tableOperator, int count) {
+ tableOperator.waitStateOnQueue(comp
+ -> count == ((JTable)comp).getRowCount());
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/HyperlinkCellRenderer.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.swing.Action;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+import javax.swing.table.TableCellRenderer;
+
+import com.sun.swingset3.demos.JHyperlink;
+
+/**
+ * Table renderer which renders cell value as hyperlink with optional rollover underline.
+ *
+ * @author aim
+ */
+public class HyperlinkCellRenderer extends JHyperlink implements TableCellRenderer {
+ private JTable table;
+ private final ArrayList<Integer> columnModelIndeces = new ArrayList<Integer>();
+
+ private Color rowColors[];
+ private Color foreground;
+ private Color visitedForeground;
+ private Border focusBorder;
+ private Border noFocusBorder;
+
+ private boolean underlineOnRollover = true;
+
+ private transient int hitColumnIndex = -1;
+ private transient int hitRowIndex = -1;
+
+ private HashMap<Object, int[]> visitedCache;
+
+ public HyperlinkCellRenderer(Action action, boolean underlineOnRollover) {
+ setAction(action);
+ setHorizontalAlignment(JHyperlink.LEFT);
+ rowColors = new Color[1];
+ rowColors[0] = UIManager.getColor("Table.background");
+ this.underlineOnRollover = underlineOnRollover;
+ applyDefaults();
+ }
+
+ public void setRowColors(Color[] colors) {
+ this.rowColors = colors;
+ }
+
+ public void updateUI() {
+ super.updateUI();
+ applyDefaults();
+ }
+
+ protected void applyDefaults() {
+ setOpaque(true);
+ setBorderPainted(false);
+ foreground = UIManager.getColor("Hyperlink.foreground");
+ visitedForeground = UIManager.getColor("Hyperlink.visitedForeground");
+
+ // Make sure border used on non-focussed cells is same size as focussed border
+ focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
+ if (focusBorder != null) {
+ Insets insets = focusBorder.getBorderInsets(this);
+ noFocusBorder = new EmptyBorder(insets.top, insets.left, insets.bottom, insets.right);
+ } else {
+ focusBorder = noFocusBorder = new EmptyBorder(1, 1, 1, 1);
+ }
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column) {
+ if (this.table == null) {
+ this.table = table;
+ HyperlinkMouseListener hyperlinkListener = new HyperlinkMouseListener();
+ table.addMouseMotionListener(hyperlinkListener);
+ table.addMouseListener(hyperlinkListener);
+ }
+ int columnModelIndex = table.getColumnModel().getColumn(column).getModelIndex();
+ if (!columnModelIndeces.contains(columnModelIndex)) {
+ columnModelIndeces.add(columnModelIndex);
+ }
+
+ if (value instanceof Link) {
+ Link link = (Link) value;
+ setText(link.getDisplayText());
+ setToolTipText(link.getDescription());
+ } else {
+ setText(value != null ? value.toString() : "");
+ }
+ setVisited(isCellLinkVisited(value, row, column));
+ setDrawUnderline(!underlineOnRollover ||
+ (row == hitRowIndex && column == hitColumnIndex));
+
+ if (!isSelected) {
+ setBackground(rowColors[row % rowColors.length]);
+ //setForeground(isCellLinkVisited(value, row, column)?
+ // visitedForeground : foreground);
+ setForeground(foreground);
+ setVisitedForeground(visitedForeground);
+ } else {
+ setBackground(table.getSelectionBackground());
+ setForeground(table.getSelectionForeground());
+ setVisitedForeground(table.getSelectionForeground());
+ }
+ //setBorder(hasFocus? focusBorder : noFocusBorder);
+ //System.out.println("border insets="+getBorder().getBorderInsets(this));
+
+ return this;
+ }
+
+ protected void setCellLinkVisited(Object value, int row, int column) {
+ if (!isCellLinkVisited(value, row, column)) {
+ if (value instanceof Link) {
+ ((Link) value).setVisited(true);
+ } else {
+ if (visitedCache == null) {
+ visitedCache = new HashMap<Object, int[]>();
+ }
+ int position[] = new int[2];
+ position[0] = table.convertRowIndexToModel(row);
+ position[1] = table.convertColumnIndexToModel(column);
+ visitedCache.put(value, position);
+ }
+ }
+ }
+
+ protected boolean isCellLinkVisited(Object value, int row, int column) {
+ if (value instanceof Link) {
+ return ((Link) value).isVisited();
+ }
+ if (visitedCache != null) {
+ int position[] = visitedCache.get(value);
+ if (position != null) {
+ return position[0] == table.convertRowIndexToModel(row) &&
+ position[1] == table.convertColumnIndexToModel(column);
+ }
+ }
+ return false;
+ }
+
+ public int getActiveHyperlinkRow() {
+ return hitRowIndex;
+ }
+
+ public int getActiveHyperlinkColumn() {
+ return hitColumnIndex;
+ }
+
+ // overridden because the AbstractButton's version forces the source of the event
+ // to be the AbstractButton and we want a little more freedom to configure the
+ // event
+ @Override
+ protected void fireActionPerformed(ActionEvent event) {
+ // Guaranteed to return a non-null array
+ Object[] listeners = listenerList.getListenerList();
+
+ // Process the listeners last to first, notifying
+ // those that are interested in this event
+ for (int i = listeners.length - 2; i >= 0; i -= 2) {
+ if (listeners[i] == ActionListener.class) {
+ ((ActionListener) listeners[i + 1]).actionPerformed(event);
+ }
+ }
+ }
+
+ public void invalidate() {
+ }
+
+ public void validate() {
+ }
+
+ public void revalidate() {
+ }
+
+ public void repaint(long tm, int x, int y, int width, int height) {
+ }
+
+ public void repaint(Rectangle r) {
+ }
+
+ public void repaint() {
+ }
+
+ private class HyperlinkMouseListener extends MouseAdapter {
+ private transient Rectangle cellRect;
+ private final transient Rectangle iconRect = new Rectangle();
+ private final transient Rectangle textRect = new Rectangle();
+ private transient Cursor tableCursor;
+
+ @Override
+ public void mouseMoved(MouseEvent event) {
+ // This should only be called if underlineOnRollover is true
+ JTable table = (JTable) event.getSource();
+
+ // Locate the table cell under the event location
+ int oldHitColumnIndex = hitColumnIndex;
+ int oldHitRowIndex = hitRowIndex;
+
+ checkIfPointInsideHyperlink(event.getPoint());
+
+ if (hitRowIndex != oldHitRowIndex ||
+ hitColumnIndex != oldHitColumnIndex) {
+ if (hitRowIndex != -1) {
+ if (tableCursor == null) {
+ tableCursor = table.getCursor();
+ }
+ table.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ } else {
+ table.setCursor(tableCursor);
+ }
+
+ // repaint the cells affected by rollover
+ Rectangle repaintRect;
+ if (hitRowIndex != -1 && hitColumnIndex != -1) {
+ // we need to repaint new cell with rollover underline
+ // cellRect already contains rect of hit cell
+ if (oldHitRowIndex != -1 && oldHitColumnIndex != -1) {
+ // we also need to repaint previously underlined hyperlink cell
+ // to remove the underline
+ repaintRect = cellRect.union(
+ table.getCellRect(oldHitRowIndex, oldHitColumnIndex, false));
+ } else {
+ // we don't have a previously underlined hyperlink, so just repaint new one'
+ repaintRect = table.getCellRect(hitRowIndex, hitColumnIndex, false);
+ }
+ } else {
+ // we just need to repaint previously underlined hyperlink cell
+ //to remove the underline
+ repaintRect = table.getCellRect(oldHitRowIndex, oldHitColumnIndex, false);
+ }
+ table.repaint(repaintRect);
+ }
+
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent event) {
+ if (checkIfPointInsideHyperlink(event.getPoint())) {
+
+ ActionEvent actionEvent = new ActionEvent(new Integer(hitRowIndex),
+ ActionEvent.ACTION_PERFORMED,
+ "hyperlink");
+
+ HyperlinkCellRenderer.this.fireActionPerformed(actionEvent);
+
+ setCellLinkVisited(table.getValueAt(hitRowIndex, hitColumnIndex),
+ hitRowIndex, hitColumnIndex);
+
+ }
+ }
+
+ protected boolean checkIfPointInsideHyperlink(Point p) {
+ hitColumnIndex = table.columnAtPoint(p);
+ hitRowIndex = table.rowAtPoint(p);
+
+ if (hitColumnIndex != -1 && hitRowIndex != -1 &&
+ columnModelIndeces.contains(table.getColumnModel().
+ getColumn(hitColumnIndex).getModelIndex())) {
+ // We know point is within a hyperlink column, however we do further hit testing
+ // to see if point is within the text bounds on the hyperlink
+ TableCellRenderer renderer = table.getCellRenderer(hitRowIndex, hitColumnIndex);
+ JHyperlink hyperlink = (JHyperlink) table.prepareRenderer(renderer, hitRowIndex, hitColumnIndex);
+
+ // Convert the event to the renderer's coordinate system
+ cellRect = table.getCellRect(hitRowIndex, hitColumnIndex, false);
+ hyperlink.setSize(cellRect.width, cellRect.height);
+ p.translate(-cellRect.x, -cellRect.y);
+ cellRect.x = cellRect.y = 0;
+ iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
+ textRect.x = textRect.y = textRect.width = textRect.height = 0;
+ SwingUtilities.layoutCompoundLabel(
+ hyperlink.getFontMetrics(hyperlink.getFont()),
+ hyperlink.getText(), hyperlink.getIcon(),
+ hyperlink.getVerticalAlignment(),
+ hyperlink.getHorizontalAlignment(),
+ hyperlink.getVerticalTextPosition(),
+ hyperlink.getHorizontalTextPosition(),
+ cellRect, iconRect, textRect, hyperlink.getIconTextGap());
+
+ if (textRect.contains(p)) {
+ // point is within hyperlink text bounds
+ return true;
+ }
+ }
+ // point is not within a hyperlink's text bounds
+ hitRowIndex = -1;
+ hitColumnIndex = -1;
+ return false;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/IMDBLink.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+
+/**
+ * Class used to support converting a movie title string into an IMDB URI
+ * corresponding to that movie's IMDB entry. Since IMDB encodes entries with
+ * an alpha-numeric key (rather than title), we have to use Yahoo search on the
+ * title and then screenscrape the search results to find the IMDB key.
+ *
+ * @author aim
+ */
+public class IMDBLink {
+
+ private IMDBLink() {
+ }
+
+ /**
+ * @param movieTitle the title of the movie
+ * @param year the year the movie was nominated for the oscar
+ * @return String containing URI for movie's IMDB entry or null if URI could not be found
+ */
+ public static String getMovieURIString(String movieTitle, int year) throws IOException {
+ ArrayList<String> matches = new ArrayList<String>();
+ URL url;
+ BufferedReader reader;
+
+ // btw, google rejects the request with a 403 return code!
+ // URL url = new URL("http://www.google.com/search?q=Dazed+and+confused");
+ // Thank you, yahoo, for granting our search request :-)
+ try {
+ String urlKey = URLEncoder.encode(movieTitle, "UTF-8");
+ url = new URL("http://search.yahoo.com/search?ei=utf-8&fr=sfp&p=imdb+" +
+ urlKey + "&iscqry=");
+ } catch (Exception ex) {
+ System.err.println(ex);
+
+ return null;
+ }
+
+ URLConnection conn = url.openConnection();
+ conn.connect();
+
+ // Get the response from Yahoo search query
+ reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+
+ // Parse response a find each imdb/titleString result
+ String line;
+ String imdbString = ".imdb.com";
+ String titleStrings[] = {"/title", "/Title"};
+
+ while ((line = reader.readLine()) != null) {
+ for (String titleString : titleStrings) {
+ String scrapeKey = imdbString + titleString;
+ int index = line.indexOf(scrapeKey);
+ if (index != -1) {
+ // The IMDB key looks something like "tt0032138"
+ // so we look for the 9 characters after the scrape key
+ // to construct the full IMDB URI.
+ // e.g. http://www.imdb.com/title/tt0032138
+ int len = scrapeKey.length();
+ String imdbURL = "http://www" +
+ line.substring(index, index + len) +
+ line.substring(index + len, index + len + 10);
+
+ if (!matches.contains(imdbURL)) {
+ matches.add(imdbURL);
+ }
+ }
+ }
+ }
+ reader.close();
+
+ // Since imdb contains entries for multiple movies of the same titleString,
+ // use the year to find the right entry
+ if (matches.size() > 1) {
+ for (String matchURL : matches) {
+ if (verifyYear(matchURL, year)) {
+ return matchURL;
+ }
+ }
+ }
+ return matches.isEmpty()? null : matches.get(0);
+ }
+
+
+ private static boolean verifyYear(String imdbURL, int movieYear) throws IOException {
+ boolean yearMatches = false;
+
+ URLConnection conn = new URL(imdbURL).openConnection();
+ conn.connect();
+
+ // Get the response
+ BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ int index = line.indexOf("</title>");
+ if (index != -1) {
+ // looking for "<title>movie title (YEAR)</title>"
+ try {
+ int year = Integer.parseInt(line.substring(index - 5, index - 1));
+ // Movie may have been made the year prior to oscar award
+ yearMatches = year == movieYear || year == movieYear - 1;
+
+ } catch (NumberFormatException ex) {
+ // ignore title lines that have other formatting
+ }
+ break; // only interested in analyzing the one line
+ }
+ }
+ reader.close();
+
+ return yearMatches;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/Link.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.net.URI;
+
+/**
+ * Class representing the state of a hyperlink
+ * This class may be used in conjunction with HyperlinkCellRenderer,
+ * but it is not required.
+ *
+ * @author aim
+ */
+public class Link {
+ protected String displayText;
+ private URI uri;
+ private String description;
+ private boolean visited;
+
+ /**
+ * Creates a new instance of Link
+ */
+ public Link(String text) {
+ setDisplayText(text);
+ }
+
+ public Link(String text, URI uri) {
+ this(text);
+ setUri(uri);
+ }
+
+ public String getDisplayText() {
+ return displayText;
+ }
+
+ public void setDisplayText(String text) {
+ this.displayText = text;
+ }
+
+ public URI getUri() {
+ return uri;
+ }
+
+ public void setUri(URI uri) {
+ this.uri = uri;
+ }
+
+ public String getDescription() {
+ return description != null ? description :
+ uri != null ? uri.getPath() : null;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isVisited() {
+ return visited;
+ }
+
+ public void setVisited(boolean visited) {
+ this.visited = visited;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/OscarCandidate.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author aim
+ */
+public class OscarCandidate {
+
+ private String category;
+ private Integer year;
+ private boolean winner = false;
+ private String movie;
+ private URI imdbURI;
+ private final ArrayList<String> persons = new ArrayList<String>();
+
+ /**
+ * Creates a new instance of OscarCandidate
+ */
+ public OscarCandidate(String category) {
+ this.category = category;
+ }
+
+ public String getCategory() {
+ return category;
+ }
+
+ public void setCategory(String category) {
+ this.category = category;
+ }
+
+ public Integer getYear() {
+ return year;
+ }
+
+ public void setYear(Integer year) {
+ this.year = year;
+ }
+
+ public boolean isWinner() {
+ return winner;
+ }
+
+ public void setWinner(boolean winner) {
+ this.winner = winner;
+ }
+
+ public String getMovieTitle() {
+ return movie;
+ }
+
+ public void setMovieTitle(String movie) {
+ this.movie = movie;
+ }
+
+ public URI getIMDBMovieURI() {
+ return imdbURI;
+ }
+
+ public void setIMDBMovieURI(URI uri) {
+ this.imdbURI = uri;
+ }
+
+ public List<String> getPersons() {
+ return persons;
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/OscarCellRenderers.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.swing.Action;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.UIManager;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableModel;
+
+/**
+ *
+ * @author aim
+ */
+public class OscarCellRenderers {
+
+ //<snip>Render table rows with alternating colors
+ public static class RowRenderer extends DefaultTableCellRenderer {
+ private Color rowColors[];
+
+ public RowRenderer() {
+ // initialize default colors from look-and-feel
+ rowColors = new Color[1];
+ rowColors[0] = UIManager.getColor("Table.background");
+ }
+
+ public RowRenderer(Color colors[]) {
+ super();
+ setRowColors(colors);
+ }
+
+ public void setRowColors(Color colors[]) {
+ rowColors = colors;
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column) {
+ super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ setText(value != null ? value.toString() : "unknown");
+ if (!isSelected) {
+ setBackground(rowColors[row % rowColors.length]);
+ }
+ return this;
+ }
+
+ public boolean isOpaque() {
+ return true;
+ }
+ }
+ //<snip>
+
+ //<snip>Render "year" table column with font representing style of decade
+ // currently only used on OS X because fonts are Mac centric.
+
+ public static class YearRenderer extends RowRenderer {
+ private HashMap<String, Font> eraFonts;
+
+ public YearRenderer() {
+ setHorizontalAlignment(JLabel.CENTER);
+
+ if (System.getProperty("os.name").equals("Mac OS X")) {
+ eraFonts = new HashMap<String, Font>();
+ eraFonts.put("192"/*1920's*/, new Font("Jazz LET", Font.PLAIN, 12));
+ eraFonts.put("193"/*1930's*/, new Font("Mona Lisa Solid ITC TT", Font.BOLD, 18));
+ eraFonts.put("194"/*1940's*/, new Font("American Typewriter", Font.BOLD, 12));
+ eraFonts.put("195"/*1950's*/, new Font("Britannic Bold", Font.PLAIN, 12));
+ eraFonts.put("196"/*1960's*/, new Font("Cooper Black", Font.PLAIN, 14));
+ eraFonts.put("197"/*1970's*/, new Font("Syncro LET", Font.PLAIN, 14));
+ eraFonts.put("198"/*1980's*/, new Font("Mistral", Font.PLAIN, 18));
+ eraFonts.put("199"/*1990's*/, new Font("Papyrus", Font.BOLD, 14));
+ eraFonts.put("200"/*2000's*/, new Font("Calisto MT", Font.PLAIN, 14));
+ }
+ }
+
+ public YearRenderer(Color colors[]) {
+ this();
+ setRowColors(colors);
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column) {
+
+ super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+ String year = table.getValueAt(row,
+ table.convertColumnIndexToView(OscarTableModel.YEAR_COLUMN)).toString();
+ if (eraFonts != null && year != null && year.length() == 4) {
+ String era = year.substring(0, 3);
+ Font eraFont = eraFonts.get(era);
+ setFont(eraFont);
+ }
+ return this;
+ }
+ }
+ //</snip>
+
+ //<snip>Render "nominee" table column with special icon for winners
+
+ public static class NomineeRenderer extends RowRenderer {
+ private final ImageIcon winnerIcon;
+ private final ImageIcon nomineeIcon; // nice way of saying "loser" :)
+
+ public NomineeRenderer() {
+ winnerIcon = new ImageIcon(
+ getClass().getResource("resources/images/goldstar.png"));
+ nomineeIcon = new ImageIcon(
+ getClass().getResource("resources/images/nominee.png"));
+ setHorizontalTextPosition(JLabel.TRAILING);
+ }
+
+ public NomineeRenderer(Color colors[]) {
+ this();
+ setRowColors(colors);
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column) {
+
+ super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+ TableModel model = table.getModel();
+ boolean winner = ((Boolean) model.getValueAt(table.convertRowIndexToModel(row),
+ OscarTableModel.WINNER_COLUMN)).booleanValue();
+
+ List<String> persons = (List<String>) value;
+ String text = persons != null && !persons.isEmpty() ? persons.get(0) : "name unknown";
+ if (persons != null && persons.size() > 1) {
+ int personCount = persons.size();
+ setText(text + " + more...");
+ StringBuffer winners = new StringBuffer("");
+ for (int i = 0; i < personCount; i++) {
+ String person = persons.get(i);
+ winners.append(" " + person + (i < personCount - 1 ? ", " : ""));
+ }
+ setToolTipText((winner ? "Winners:" : "Nominees:") + winners);
+ } else {
+ setText(text);
+ setToolTipText(winner ? "Winner!" : "Nominee");
+ }
+
+ setIcon(winner ? winnerIcon : nomineeIcon);
+
+ return this;
+ }
+ }
+ //</snip>
+
+ public static class MovieRenderer extends HyperlinkCellRenderer {
+ public MovieRenderer(Action action, boolean underlineOnRollover, Color rowColors[]) {
+ super(action, underlineOnRollover);
+ setRowColors(rowColors);
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column) {
+ super.getTableCellRendererComponent(table, value, isSelected,
+ hasFocus, row, column);
+ if (value != null) {
+ setToolTipText("http://www.imdb.com/" + "\"" + value + "\"");
+ }
+ return this;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/OscarDataParser.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.logging.Level;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public abstract class OscarDataParser extends DefaultHandler {
+ private static final String[] CATEGORIES_IN = {
+ "actor", "actress", "bestPicture",
+ "actorSupporting", "actressSupporting", "artDirection",
+ "assistantDirector", "director", "cinematography",
+ "costumeDesign", "danceDirection", "docFeature",
+ "docShort", "filmEditing", "foreignFilm",
+ "makeup", "musicScore", "musicSong",
+ "screenplayAdapted", "screenplayOriginal", "shortAnimation",
+ "shortLiveAction", "sound", "soundEditing",
+ "specialEffects", "visualEffects", "writing",
+ "engEffects", "uniqueArtisticPicture"
+ };
+
+ private static final String[] CATEGORIES_OUT = {
+ "Best Actor", "Best Actress", "Best Picture",
+ "Best Supporting Actor", "Best Supporting Actress", "Best Art Direction",
+ "Best Assistant Director", "Best Director", "Best Cinematography",
+ "Best Costume Design", "Best Dance Direction", "Best Feature Documentary",
+ "Best Short Documentary", "Best Film Editing", "Best Foreign Film",
+ "Best Makeup", "Best Musical Score", "Best Song",
+ "Best Adapted Screenplay", "Best Original Screenplay", "Best Animation Short",
+ "Best Live Action Short", "Best Sound", "Best Sound Editing",
+ "Best Special Effects", "Best Visual Effects", "Best Engineering Effects",
+ "Best Writing", "Most Unique Artistic Picture"
+ };
+
+
+ private String tempVal;
+
+ //to maintain context
+ private OscarCandidate tempOscarCandidate;
+
+ private int count = 0;
+
+ public int getCount() {
+ return count;
+ }
+
+ public void parseDocument(URL oscarURL) {
+ //get a factory
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+
+ try {
+ //get a new instance of parser
+ SAXParser sp = spf.newSAXParser();
+
+ //parse the file and also register this class for call backs
+ InputStream is = new BufferedInputStream(oscarURL.openStream());
+ sp.parse(is, this);
+ System.out.println("done parsing count="+count);
+ is.close();
+
+ } catch (SAXException se) {
+ se.printStackTrace();
+ } catch (ParserConfigurationException pce) {
+ pce.printStackTrace();
+ } catch (IOException ie) {
+ ie.printStackTrace();
+ }
+ }
+
+ //Event Handlers
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ //reset
+ tempVal = "";
+ for (int i = 0; i < CATEGORIES_IN.length; i++) {
+ if (qName.equalsIgnoreCase(CATEGORIES_IN[i])) {
+ tempOscarCandidate = new OscarCandidate(CATEGORIES_OUT[i]);
+ tempOscarCandidate.setYear(Integer.parseInt(attributes.getValue("year")));
+ if (CATEGORIES_IN[i].equals("screenplayOriginal") &&
+ tempOscarCandidate.getYear() == 2007) {
+ }
+ return;
+ }
+ }
+ }
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ tempVal = new String(ch, start, length);
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (qName.equalsIgnoreCase("won")) {
+ tempOscarCandidate.setWinner(true);
+ } else if (qName.equalsIgnoreCase("lost")) {
+ tempOscarCandidate.setWinner(false);
+ } else if (qName.equalsIgnoreCase("movie")) {
+ tempOscarCandidate.setMovieTitle(tempVal);
+ } else if (qName.equalsIgnoreCase("person")) {
+ tempOscarCandidate.getPersons().add(tempVal);
+ } else {
+ // find category
+ for (String category : CATEGORIES_IN) {
+ if (qName.equalsIgnoreCase(category)) {
+ //add it to the list
+ count++;
+ addCandidate(tempOscarCandidate);
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void error(SAXParseException ex) throws SAXException {
+ TableDemo.logger.log(Level.SEVERE, "error parsing oscar data ", ex);
+ }
+
+ @Override
+ public void fatalError(SAXParseException ex) throws SAXException {
+ TableDemo.logger.log(Level.SEVERE, "fatal error parsing oscar data ", ex);
+ }
+
+ @Override
+ public void warning(SAXParseException ex) {
+ TableDemo.logger.log(Level.WARNING, "warning occurred while parsing oscar data ", ex);
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ TableDemo.logger.log(Level.FINER, "parsed to end of oscar data.");
+ }
+
+ protected abstract void addCandidate(OscarCandidate candidate);
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/OscarTableModel.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+/**
+ * Data model for oscar candidate data: a list of OscarCandidate beans.
+ *
+ * @author aim
+ */
+
+public class OscarTableModel extends AbstractTableModel {
+ public static final int CATEGORY_COLUMN = 0;
+ public static final int YEAR_COLUMN = 1;
+ public static final int WINNER_COLUMN = 2;
+ public static final int MOVIE_COLUMN = 3;
+ public static final int PERSONS_COLUMN = 4;
+ public static final int COLUMN_COUNT = 5;
+
+ private final List<OscarCandidate> candidates = new ArrayList<OscarCandidate>();
+
+ public void add(List<OscarCandidate> newCandidates) {
+ int first = candidates.size();
+ int last = first + newCandidates.size() - 1;
+ candidates.addAll(newCandidates);
+ fireTableRowsInserted(first, last);
+ }
+
+ public void add(OscarCandidate candidate) {
+ int index = candidates.size();
+ candidates.add(candidate);
+ fireTableRowsInserted(index, index);
+ }
+
+ public int getRowCount() {
+ return candidates.size();
+ }
+
+ public int getColumnCount() {
+ return COLUMN_COUNT;
+ }
+
+ @Override
+ public Class getColumnClass(int column) {
+ return getValueAt(0, column).getClass();
+ }
+
+ public OscarCandidate getCandidate(int row) {
+ return candidates.get(row);
+ }
+
+ public Object getValueAt(int row, int column) {
+ OscarCandidate oscarCandidate = candidates.get(row);
+ switch (column) {
+ case CATEGORY_COLUMN:
+ return oscarCandidate.getCategory();
+ case YEAR_COLUMN:
+ return oscarCandidate.getYear();
+ case MOVIE_COLUMN:
+ return oscarCandidate.getMovieTitle();
+ case WINNER_COLUMN:
+ return oscarCandidate.isWinner() ? Boolean.TRUE : Boolean.FALSE;
+ case PERSONS_COLUMN:
+ return oscarCandidate.getPersons();
+ }
+ return null;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/TableDemo.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+package com.sun.swingset3.demos.table;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+import javax.swing.AbstractAction;
+import javax.swing.Box;
+import javax.swing.JCheckBox;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+import javax.swing.RowFilter;
+import javax.swing.UIManager;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableColumnModel;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableCellRenderer;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+import javax.swing.table.TableRowSorter;
+import javax.swing.text.Document;
+
+import com.sun.swingset3.DemoProperties;
+import com.sun.swingset3.demos.DemoUtilities;
+
+/**
+ *
+ * @author aim
+ */
+@DemoProperties(
+ value = "JTable Demo",
+ category = "Data",
+ description = "Demonstrates use of Swing's data grid component, JTable, including asynchronous loading and sorting/filtering.",
+ sourceFiles = {
+ "com/sun/swingset3/demos/table/TableDemo.java",
+ "com/sun/swingset3/demos/table/HyperlinkCellRenderer.java",
+ "com/sun/swingset3/demos/table/IMDBLink.java",
+ "com/sun/swingset3/demos/table/Link.java",
+ "com/sun/swingset3/demos/table/OscarCandidate.java",
+ "com/sun/swingset3/demos/table/OscarCellRenderers.java",
+ "com/sun/swingset3/demos/table/OscarDataParser.java",
+ "com/sun/swingset3/demos/table/OscarTableModel.java",
+ "com/sun/swingset3/demos/DemoUtilities.java",
+ "com/sun/swingset3/demos/JHyperlink.java",
+ "com/sun/swingset3/demos/table/resources/bestpicture",
+ //"com/sun/swingset3/demos/table/resources/oscars.xml", file too large!!
+ "com/sun/swingset3/demos/table/resources/TableDemo.properties",
+ "com/sun/swingset3/demos/table/resources/images/goldstar.png",
+ "com/sun/swingset3/demos/table/resources/images/nominee.png",
+ "com/sun/swingset3/demos/table/resources/images/TableDemo.gif"
+ }
+)
+public class TableDemo extends JPanel {
+ static final Logger logger = Logger.getLogger(TableDemo.class.getName());
+ public static final String DEMO_TITLE = TableDemo.class.getAnnotation(DemoProperties.class).value();
+ public static final int ROW_HEIGHT = 26;
+ public static final String COLUMN1_NAME = "Year";
+ public static final String COLUMN2_NAME = "Award Category";
+ public static final String COLUMN3_NAME = "Movie Title";
+ public static final String COLUMN4_NAME = "Nominees";
+
+ private OscarTableModel oscarModel;
+
+ private JPanel controlPanel;
+ private JTable oscarTable;
+ private JCheckBox winnersCheckbox;
+ private JTextField filterField;
+ private Box statusBarLeft;
+ private JLabel actionStatus;
+ private JLabel tableStatus;
+
+ private Color[] rowColors;
+ private String statusLabelString;
+ private String searchLabelString;
+
+ private boolean showOnlyWinners = false;
+ private String filterString = null;
+
+ private TableRowSorter sorter;
+ private RowFilter<OscarTableModel, Integer> winnerFilter;
+ private RowFilter<OscarTableModel, Integer> searchFilter;
+
+ // Resource bundle for internationalized and accessible text
+ private ResourceBundle bundle = null;
+
+ public TableDemo() {
+ initModel();
+ initComponents();
+ initSortingFiltering();
+ }
+
+ protected void initModel() {
+ oscarModel = new OscarTableModel();
+ }
+
+ protected void initComponents() {
+ setLayout(new BorderLayout());
+
+ controlPanel = createControlPanel();
+ add(controlPanel, BorderLayout.NORTH);
+
+ //<snip>Create JTable
+ oscarTable = new JTable(oscarModel);
+ //</snip>
+
+ //</snip>Set JTable display properties
+ oscarTable.setColumnModel(createColumnModel());
+ oscarTable.setAutoCreateRowSorter(true);
+ oscarTable.setRowHeight(ROW_HEIGHT);
+ oscarTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
+ oscarTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ oscarTable.setIntercellSpacing(new Dimension(0, 0));
+ //</snip>
+
+ //<snip>Initialize preferred size for table's viewable area
+ Dimension viewSize = new Dimension();
+ viewSize.width = oscarTable.getColumnModel().getTotalColumnWidth();
+ viewSize.height = 10 * oscarTable.getRowHeight();
+ oscarTable.setPreferredScrollableViewportSize(viewSize);
+ //</snip>
+
+ //<snip>Customize height and alignment of table header
+ JTableHeader header = oscarTable.getTableHeader();
+ header.setPreferredSize(new Dimension(30, 26));
+ TableCellRenderer headerRenderer = header.getDefaultRenderer();
+ if (headerRenderer instanceof JLabel) {
+ ((JLabel) headerRenderer).setHorizontalAlignment(JLabel.CENTER);
+ }
+ //</snip>
+
+ JScrollPane scrollpane = new JScrollPane(oscarTable);
+ add(scrollpane, BorderLayout.CENTER);
+
+ add(createStatusBar(), BorderLayout.SOUTH);
+
+ }
+
+ protected JPanel createControlPanel() {
+ JPanel controlPanel = new JPanel();
+ GridBagLayout gridbag = new GridBagLayout();
+ GridBagConstraints c = new GridBagConstraints();
+ controlPanel.setLayout(gridbag);
+
+ c.gridx = 0;
+ c.gridy = 1;
+ c.gridheight = 1;
+ c.insets = new Insets(20, 10, 0, 10);
+ c.anchor = GridBagConstraints.SOUTHWEST;
+ JLabel searchLabel = new JLabel(getString("TableDemo.searchLabel",
+ "Search Titles and Recipients"));
+ controlPanel.add(searchLabel, c);
+
+ c.gridx = 0;
+ c.gridy = 2;
+ c.weightx = 1.0;
+ c.insets.top = 0;
+ c.insets.bottom = 12;
+ c.anchor = GridBagConstraints.SOUTHWEST;
+ //c.fill = GridBagConstraints.HORIZONTAL;
+ filterField = new JTextField(24);
+ filterField.getDocument().addDocumentListener(new SearchFilterListener());
+ controlPanel.add(filterField, c);
+
+ c.gridx = 1;
+ c.gridy = 2;
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ //c.insets.right = 24;
+ //c.insets.left = 12;
+ c.weightx = 0.0;
+ c.anchor = GridBagConstraints.EAST;
+ c.fill = GridBagConstraints.NONE;
+ winnersCheckbox = new JCheckBox(getString("TableDemo.winnersLabel",
+ "Show Only Winners"));
+ winnersCheckbox.addChangeListener(new ShowWinnersListener());
+ controlPanel.add(winnersCheckbox, c);
+
+ return controlPanel;
+ }
+
+ protected Container createStatusBar() {
+ statusLabelString = getString("TableDemo.rowCountLabel",
+ "Showing ");
+ searchLabelString = getString("TableDemo.searchCountLabel",
+ "Search found ");
+
+ Box statusBar = Box.createHorizontalBox();
+
+ // Left status area
+ statusBar.add(Box.createRigidArea(new Dimension(10, 22)));
+ statusBarLeft = Box.createHorizontalBox();
+ statusBar.add(statusBarLeft);
+ actionStatus = new JLabel(getString("TableDemo.noDataStatusLabel",
+ "No data loaded"));
+ actionStatus.setHorizontalAlignment(JLabel.LEADING);
+ statusBarLeft.add(actionStatus);
+
+ // Middle (should stretch)
+ statusBar.add(Box.createHorizontalGlue());
+ statusBar.add(Box.createHorizontalGlue());
+ statusBar.add(Box.createVerticalGlue());
+
+ // Right status area
+ tableStatus = new JLabel(statusLabelString + "0");
+ statusBar.add(tableStatus);
+ statusBar.add(Box.createHorizontalStrut(12));
+
+ //<snip>Track number of rows currently displayed
+ oscarModel.addTableModelListener(new TableModelListener() {
+ public void tableChanged(TableModelEvent e) {
+ // Get rowCount from *table*, not model, as the view row count
+ // may be different from the model row count due to filtering
+ tableStatus.setText((hasFilterString() ? searchLabelString : statusLabelString) +
+ oscarTable.getRowCount());
+ }
+ });
+ //</snip>
+
+ return statusBar;
+ }
+
+ private Color[] getTableRowColors() {
+ if (rowColors == null) {
+ rowColors = new Color[2];
+ rowColors[0] = UIManager.getColor("Table.background");
+ rowColors[1] = new Color((int) (rowColors[0].getRed() * .9),
+ (int) (rowColors[0].getGreen() * .9),
+ (int) (rowColors[0].getBlue() * .9));
+ }
+ return rowColors;
+ }
+
+ // returns appropriate string from resource bundle
+ protected String getString(String key, String fallback) {
+ String value = fallback;
+ if (bundle == null) {
+ String bundleName = getClass().getPackage().getName() + ".resources." + getClass().getSimpleName();
+ bundle = ResourceBundle.getBundle(bundleName);
+ }
+ try {
+ value = bundle != null ? bundle.getString(key) : key;
+
+ } catch (MissingResourceException ex) {
+ logger.log(Level.WARNING, "couldn't find resource value for: " + key, ex);
+ }
+ return value;
+ }
+
+ public void start() {
+ if (oscarModel.getRowCount() == 0) {
+ loadData("resources/oscars.xml");
+ }
+ }
+
+ //<snip>Initialize table columns
+ protected TableColumnModel createColumnModel() {
+ DefaultTableColumnModel columnModel = new DefaultTableColumnModel();
+
+ TableCellRenderer cellRenderer = new OscarCellRenderers.RowRenderer(getTableRowColors());
+
+ TableColumn column = new TableColumn();
+ column.setModelIndex(OscarTableModel.YEAR_COLUMN);
+ column.setHeaderValue(COLUMN1_NAME);
+ column.setPreferredWidth(26);
+ column.setCellRenderer(new OscarCellRenderers.YearRenderer(getTableRowColors()));
+ columnModel.addColumn(column);
+
+ column = new TableColumn();
+ column.setModelIndex(OscarTableModel.CATEGORY_COLUMN);
+ column.setHeaderValue(COLUMN2_NAME);
+ column.setPreferredWidth(100);
+ column.setCellRenderer(cellRenderer);
+ columnModel.addColumn(column);
+
+ column = new TableColumn();
+ column.setModelIndex(OscarTableModel.MOVIE_COLUMN);
+ column.setHeaderValue(COLUMN3_NAME);
+ column.setPreferredWidth(180);
+ column.setCellRenderer(cellRenderer);
+ columnModel.addColumn(column);
+
+ column = new TableColumn();
+ column.setModelIndex(OscarTableModel.PERSONS_COLUMN);
+ column.setHeaderValue(COLUMN4_NAME);
+ column.setPreferredWidth(120);
+ column.setCellRenderer(new OscarCellRenderers.NomineeRenderer(getTableRowColors()));
+ columnModel.addColumn(column);
+
+ return columnModel;
+ }
+ //</snip>
+
+ protected void initSortingFiltering() {
+ //<snip>Setup filtering for winners
+ sorter = new TableRowSorter(oscarModel);
+ oscarTable.setRowSorter(sorter);
+ winnerFilter = new RowFilter<OscarTableModel, Integer>() {
+ public boolean include(Entry<? extends OscarTableModel, ? extends Integer> entry) {
+ OscarTableModel oscarModel = entry.getModel();
+ OscarCandidate candidate = oscarModel.getCandidate(entry.getIdentifier().intValue());
+ if (candidate.isWinner()) {
+ // Returning true indicates this row should be shown.
+ return true;
+ }
+ // loser
+ return false;
+ }
+ };
+ //</snip>
+
+ //<snip>Setup search filter
+ searchFilter = new RowFilter<OscarTableModel, Integer>() {
+ public boolean include(Entry<? extends OscarTableModel, ? extends Integer> entry) {
+ OscarTableModel oscarModel = entry.getModel();
+ OscarCandidate candidate = oscarModel.getCandidate(entry.getIdentifier().intValue());
+ boolean matches = false;
+ Pattern p = Pattern.compile(filterString + ".*", Pattern.CASE_INSENSITIVE);
+
+ String movie = candidate.getMovieTitle();
+ if (movie != null) {
+ if (movie.startsWith("The ")) {
+ movie = movie.replace("The ", "");
+ } else if (movie.startsWith("A ")) {
+ movie = movie.replace("A ", "");
+ }
+ // Returning true indicates this row should be shown.
+ matches = p.matcher(movie).matches();
+ }
+ List<String> persons = candidate.getPersons();
+ for (String person : persons) {
+ if (p.matcher(person).matches()) {
+ matches = true;
+ }
+ }
+ return matches;
+ }
+ };
+ //</snip>
+ }
+
+ public void setShowOnlyWinners(boolean showOnlyWinners) {
+ boolean oldShowOnlyWinners = this.showOnlyWinners;
+ this.showOnlyWinners = showOnlyWinners;
+ configureFilters();
+ tableStatus.setText(statusLabelString + oscarTable.getRowCount());
+ firePropertyChange("showOnlyWinners", oldShowOnlyWinners, showOnlyWinners);
+ }
+
+ public boolean getShowOnlyWinners() {
+ return showOnlyWinners;
+ }
+
+ public void setFilterString(String filterString) {
+ String oldFilterString = this.filterString;
+ this.filterString = filterString;
+ configureFilters();
+ firePropertyChange("filterString", oldFilterString, filterString);
+ }
+
+ protected boolean hasFilterString() {
+ return filterString != null && !filterString.equals("");
+ }
+
+ protected void configureFilters() {
+ if (showOnlyWinners && hasFilterString()) {
+ List<RowFilter<OscarTableModel, Integer>> filters =
+ new ArrayList<RowFilter<OscarTableModel, Integer>>(2);
+ filters.add(winnerFilter);
+ filters.add(searchFilter);
+ RowFilter<OscarTableModel, Integer> comboFilter = RowFilter.andFilter(filters);
+ sorter.setRowFilter(comboFilter);
+ } else if (showOnlyWinners) {
+ sorter.setRowFilter(winnerFilter);
+ } else if (hasFilterString()) {
+ sorter.setRowFilter(searchFilter);
+ } else {
+ sorter.setRowFilter(null);
+ }
+ tableStatus.setText((hasFilterString() ? searchLabelString : statusLabelString)
+ + oscarTable.getRowCount());
+
+ }
+
+ private class ShowWinnersListener implements ChangeListener {
+ public void stateChanged(ChangeEvent event) {
+ setShowOnlyWinners(winnersCheckbox.isSelected());
+ }
+ }
+
+ //<snip>Setup search filter
+ protected class SearchFilterListener implements DocumentListener {
+ protected void changeFilter(DocumentEvent event) {
+ Document document = event.getDocument();
+ try {
+ setFilterString(document.getText(0, document.getLength()));
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ System.err.println(ex);
+ }
+ }
+
+ public void changedUpdate(DocumentEvent e) {
+ changeFilter(e);
+ }
+
+ public void insertUpdate(DocumentEvent e) {
+ changeFilter(e);
+ }
+
+ public void removeUpdate(DocumentEvent e) {
+ changeFilter(e);
+ }
+ }
+ //</snip>
+
+ //<snip>Use SwingWorker to asynchronously load the data
+
+ public void loadData(String dataPath) {
+ // create SwingWorker which will load the data on a separate thread
+ OscarDataLoader loader = new OscarDataLoader(
+ TableDemo.class.getResource(dataPath), oscarModel);
+
+ actionStatus.setText(getString("TableDemo.loadingStatusLabel",
+ "Loading data: "));
+
+ // display progress bar while data loads
+ final JProgressBar progressBar = new JProgressBar();
+ statusBarLeft.add(progressBar);
+ loader.addPropertyChangeListener(new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ if (event.getPropertyName().equals("progress")) {
+ int progress = ((Integer) event.getNewValue()).intValue();
+ progressBar.setValue(progress);
+
+ if (progress == 100) {
+ statusBarLeft.remove(progressBar);
+ actionStatus.setText("");
+ revalidate();
+ }
+ }
+ }
+ });
+ loader.execute();
+
+ }
+ //</snip>
+
+ protected void showMessage(String title, String message) {
+ JOptionPane.showMessageDialog(this, message, title, JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ //<snip>Use SwingWorker to asynchronously load the data
+ private class OscarDataLoader extends javax.swing.SwingWorker<List<OscarCandidate>, OscarCandidate> {
+ private final URL oscarData;
+ private final OscarTableModel oscarModel;
+ private final List<OscarCandidate> candidates = new ArrayList<OscarCandidate>();
+ private JLabel credits;
+
+ private OscarDataLoader(URL oscarURL, OscarTableModel oscarTableModel) {
+ this.oscarData = oscarURL;
+ this.oscarModel = oscarTableModel;
+ }
+
+ @Override
+ public List<OscarCandidate> doInBackground() {
+ OscarDataParser parser = new OscarDataParser() {
+ @Override
+ protected void addCandidate(OscarCandidate candidate) {
+ candidates.add(candidate);
+ if (candidates.size() % 3 == 0) {
+ try { // slow it down so we can see progress :-)
+ Thread.sleep(1);
+ } catch (Exception ex) {
+ }
+ }
+ publish(candidate);
+ setProgress(100 * candidates.size() / 524);
+ }
+ };
+ parser.parseDocument(oscarData);
+ return candidates;
+ }
+
+ // for OS X older Java 6
+ /*
+ protected void process(List<OscarCandidate>... moreCandidates) {
+ for(List<OscarCandidate> newCandidates: moreCandidates) {
+ oscarModel.add(newCandidates);
+ }
+ }*/
+
+ //@Override
+
+ protected void process(List<OscarCandidate> moreCandidates) {
+ if (credits == null) {
+ showCredits();
+ }
+ oscarModel.add(moreCandidates);
+ }
+
+ // For older Java 6 on OS X
+ protected void process(OscarCandidate... moreCandidates) {
+ for (OscarCandidate candidate : moreCandidates) {
+ oscarModel.add(candidate);
+ }
+ }
+
+ private void showCredits() {
+ credits = new JLabel(getString("TableDemo.credits",
+ "<html><p align=\"center\">Academy Award data<br>courtesy of Howard Katz</p></html>"));
+ credits.setFont(UIManager.getFont("Table.font").deriveFont(24f));
+ credits.setHorizontalAlignment(JLabel.CENTER);
+ credits.setBorder(new CompoundBorder(new TitledBorder(""),
+ new EmptyBorder(20,20,20,20)));
+ }
+ @Override
+ protected void done() {
+ setProgress(100);
+ }
+
+ }
+ //</snip>
+
+ private class IMDBLinkAction extends AbstractAction {
+
+ public void actionPerformed(ActionEvent event) {
+ int row = ((Integer) event.getSource()).intValue();
+ OscarCandidate candidate = oscarModel.getCandidate(oscarTable.convertRowIndexToModel(row));
+
+ try {
+ URI imdbURI = candidate.getIMDBMovieURI();
+ if (imdbURI == null) {
+ String imdbString = IMDBLink.getMovieURIString(candidate.getMovieTitle(),
+ candidate.getYear());
+ if (imdbString != null) {
+ imdbURI = new URI(imdbString);
+ candidate.setIMDBMovieURI(imdbURI);
+ }
+ }
+ if (imdbURI != null) {
+ DemoUtilities.browse(imdbURI);
+ } else {
+ showMessage("IMDB Link",
+ getString("TableDemo.imdbLinkNotFound",
+ "Unable to locate IMDB URL for") + "\n" +
+ candidate.getMovieTitle());
+ }
+
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+
+ javax.swing.SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ JFrame frame = new JFrame("JTable Demo");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ TableDemo demo = new TableDemo();
+ frame.add(demo);
+ frame.setSize(700, 400);
+ frame.setVisible(true);
+ demo.start();
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,22 @@
+# Table Demo Properties
+
+TableDemo.accessible_description=Advanced Table Demo
+TableDemo.name=Advanced Table Demo
+TableDemo.title=Academy Awards Results
+TableDemo.credits=<html><p align="center">Academy Award data<br>courtesy of Howard Katz</p></html>
+
+TableDemo.searchLabel=Search Titles and Recipients
+TableDemo.winnersLabel=Show Only Winners
+
+TableDemo.noDataStatusLabel=No data loaded
+TableDemo.loadingStatusLabel=Loading data:
+TableDemo.rowCountLabel=Showing
+TableDemo.searchCountLabel=Search found
+
+TableDemo.yearColumnTitle=Year
+TableDemo.categoryColumnTitle=Award Category
+TableDemo.movieTitleColumnTitle=Movie Title
+TableDemo.nomineesColumnTitle=Nominee(s)
+
+TableDemo.imdbLinkNotFound=Unable to locate IMDB URL for
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/bestpicture Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,397 @@
+
+1927/28 (1st)
+OUTSTANDING PICTURE
+*
+Paramount Famous Lasky -- Wings
+
+1928/29 (2nd)
+OUTSTANDING PICTURE
+*
+Metro-Goldwyn-Mayer -- The Broadway Melody
+[NOTE: THIS IS NOT AN OFFICIAL NOMINATION. There were no announcements of nominations, no certificates of nomination or honorable mention, and only the winners (*) were revealed during the awards banquet on April 3, 1930.]
+
+1929/30 (3rd)
+OUTSTANDING PRODUCTION
+*
+All Quiet on the Western Front -- Universal
+
+1930/31 (4th)
+OUTSTANDING PRODUCTION
+*
+Cimarron -- RKO Radio
+
+1931/32 (5th)
+OUTSTANDING PRODUCTION
+*
+Grand Hotel -- Metro-Goldwyn-Mayer
+
+1932/33 (6th)
+OUTSTANDING PRODUCTION
+*
+Cavalcade -- Fox
+
+1934 (7th)
+OUTSTANDING PRODUCTION
+*
+It Happened One Night -- Columbia
+
+1935 (8th)
+OUTSTANDING PRODUCTION
+*
+Mutiny on the Bounty -- Metro-Goldwyn-Mayer
+
+1936 (9th)
+OUTSTANDING PRODUCTION
+*
+The Great Ziegfeld -- Metro-Goldwyn-Mayer
+
+1937 (10th)
+OUTSTANDING PRODUCTION
+*
+The Life of Emile Zola -- Warner Bros.
+
+1938 (11th)
+OUTSTANDING PRODUCTION
+*
+You Can't Take It with You -- Columbia
+
+1939 (12th)
+OUTSTANDING PRODUCTION
+*
+Gone with the Wind -- Selznick International Pictures
+
+1940 (13th)
+OUTSTANDING PRODUCTION
+*
+Rebecca -- Selznick International Pictures
+
+1941 (14th)
+OUTSTANDING MOTION PICTURE
+*
+How Green Was My Valley -- 20th Century-Fox
+
+1942 (15th)
+OUTSTANDING MOTION PICTURE
+*
+Mrs. Miniver -- Metro-Goldwyn-Mayer
+
+1943 (16th)
+OUTSTANDING MOTION PICTURE
+*
+Casablanca -- Warner Bros.
+
+1944 (17th)
+BEST MOTION PICTURE
+*
+Going My Way -- Paramount
+
+1945 (18th)
+BEST MOTION PICTURE
+*
+The Lost Weekend -- Paramount
+
+1946 (19th)
+BEST MOTION PICTURE
+*
+The Best Years of Our Lives -- Samuel Goldwyn Productions
+
+1947 (20th)
+BEST MOTION PICTURE
+*
+Gentleman's Agreement -- 20th Century-Fox
+
+1948 (21st)
+BEST MOTION PICTURE
+*
+Hamlet -- J. Arthur Rank-Two Cities Films
+
+1949 (22nd)
+BEST MOTION PICTURE
+*
+All the King's Men -- Robert Rossen Productions
+
+1950 (23rd)
+BEST MOTION PICTURE
+*
+All about Eve -- 20th Century-Fox
+
+1951 (24th)
+BEST MOTION PICTURE
+*
+An American in Paris -- Arthur Freed, Producer
+
+1952 (25th)
+BEST MOTION PICTURE
+*
+The Greatest Show on Earth -- Cecil B. DeMille, Producer
+
+1953 (26th)
+BEST MOTION PICTURE
+*
+From Here to Eternity -- Buddy Adler, Producer
+
+1954 (27th)
+BEST MOTION PICTURE
+*
+On the Waterfront -- Sam Spiegel, Producer
+
+1955 (28th)
+BEST MOTION PICTURE
+*
+Marty -- Harold Hecht, Producer
+
+1956 (29th)
+BEST MOTION PICTURE
+*
+Around the World in 80 Days -- Michael Todd, Producer
+
+1957 (30th)
+BEST MOTION PICTURE
+*
+The Bridge on the River Kwai -- Sam Spiegel, Producer
+
+1958 (31st)
+BEST MOTION PICTURE
+*
+Gigi -- Arthur Freed, Producer
+
+1959 (32nd)
+BEST MOTION PICTURE
+*
+Ben-Hur -- Sam Zimbalist, Producer
+
+1960 (33rd)
+BEST MOTION PICTURE
+*
+The Apartment -- Billy Wilder, Producer
+
+1961 (34th)
+BEST MOTION PICTURE
+*
+West Side Story -- Robert Wise, Producer
+
+1962 (35th)
+BEST PICTURE
+*
+Lawrence of Arabia -- Sam Spiegel, Producer
+
+1963 (36th)
+BEST PICTURE
+*
+Tom Jones -- Tony Richardson, Producer
+
+1964 (37th)
+BEST PICTURE
+*
+My Fair Lady -- Jack L. Warner, Producer
+
+1965 (38th)
+BEST PICTURE
+*
+The Sound of Music -- Robert Wise, Producer
+
+1966 (39th)
+BEST PICTURE
+*
+A Man for All Seasons -- Fred Zinnemann, Producer
+
+1967 (40th)
+BEST PICTURE
+*
+In the Heat of the Night -- Walter Mirisch, Producer
+
+1968 (41st)
+BEST PICTURE
+*
+Oliver! -- John Woolf, Producer
+
+1969 (42nd)
+BEST PICTURE
+*
+Midnight Cowboy -- Jerome Hellman, Producer
+
+1970 (43rd)
+BEST PICTURE
+*
+Patton -- Frank McCarthy, Producer
+
+1971 (44th)
+BEST PICTURE
+*
+The French Connection -- Philip D'Antoni, Producer
+
+1972 (45th)
+BEST PICTURE
+*
+The Godfather -- Albert S. Ruddy, Producer
+
+1973 (46th)
+BEST PICTURE
+*
+The Sting -- Tony Bill, Michael Phillips and Julia Phillips, Producers
+
+1974 (47th)
+BEST PICTURE
+*
+The Godfather Part II -- Francis Ford Coppola, Producer; Gray Frederickson and Fred Roos, Co-Producers
+
+1975 (48th)
+BEST PICTURE
+*
+One Flew over the Cuckoo's Nest -- Saul Zaentz and Michael Douglas, Producers
+
+1976 (49th)
+BEST PICTURE
+*
+Rocky -- Irwin Winkler and Robert Chartoff, Producers
+
+1977 (50th)
+BEST PICTURE
+*
+Annie Hall -- Charles H. Joffe, Producer
+
+1978 (51st)
+BEST PICTURE
+*
+The Deer Hunter -- Barry Spikings, Michael Deeley, Michael Cimino and John Peverall, Producers
+
+1979 (52nd)
+BEST PICTURE
+*
+Kramer vs. Kramer -- Stanley R. Jaffe, Producer
+
+1980 (53rd)
+BEST PICTURE
+*
+Ordinary People -- Ronald L. Schwary, Producer
+
+1981 (54th)
+BEST PICTURE
+*
+Chariots of Fire -- David Puttnam, Producer
+
+1982 (55th)
+BEST PICTURE
+*
+Gandhi -- Richard Attenborough, Producer
+
+1983 (56th)
+BEST PICTURE
+*
+Terms of Endearment -- James L. Brooks, Producer
+
+1984 (57th)
+BEST PICTURE
+*
+Amadeus -- Saul Zaentz, Producer
+
+1985 (58th)
+BEST PICTURE
+*
+Out of Africa -- Sydney Pollack, Producer
+
+1986 (59th)
+BEST PICTURE
+*
+Platoon -- Arnold Kopelson, Producer
+
+1987 (60th)
+BEST PICTURE
+*
+The Last Emperor -- Jeremy Thomas, Producer
+
+1988 (61st)
+BEST PICTURE
+*
+Rain Man -- Mark Johnson, Producer
+
+1989 (62nd)
+BEST PICTURE
+*
+Driving Miss Daisy -- Richard D. Zanuck and Lili Fini Zanuck, Producers
+
+1990 (63rd)
+BEST PICTURE
+*
+Dances With Wolves -- Jim Wilson and Kevin Costner, Producers
+
+1991 (64th)
+BEST PICTURE
+*
+The Silence of the Lambs -- Edward Saxon, Kenneth Utt and Ron Bozman, Producers
+
+1992 (65th)
+BEST PICTURE
+*
+Unforgiven -- Clint Eastwood, Producer
+
+1993 (66th)
+BEST PICTURE
+*
+Schindler's List -- Steven Spielberg, Gerald R. Molen and Branko Lustig, Producers
+
+1994 (67th)
+BEST PICTURE
+*
+Forrest Gump -- Wendy Finerman, Steve Tisch and Steve Starkey, Producers
+
+1995 (68th)
+BEST PICTURE
+*
+Braveheart -- Mel Gibson, Alan Ladd, Jr. and Bruce Davey, Producers
+
+1996 (69th)
+BEST PICTURE
+*
+The English Patient -- Saul Zaentz, Producer
+
+1997 (70th)
+BEST PICTURE
+*
+Titanic -- James Cameron and Jon Landau, Producers
+
+1998 (71st)
+BEST PICTURE
+*
+Shakespeare in Love -- David Parfitt, Donna Gigliotti, Harvey Weinstein, Edward Zwick and Marc Norman, Producers
+
+1999 (72nd)
+BEST PICTURE
+*
+American Beauty -- Bruce Cohen and Dan Jinks, Producers
+
+2000 (73rd)
+BEST PICTURE
+*
+Gladiator -- Douglas Wick, David Franzoni and Branko Lustig, Producers
+
+2001 (74th)
+BEST PICTURE
+*
+A Beautiful Mind -- Brian Grazer and Ron Howard, Producers
+
+2002 (75th)
+BEST PICTURE
+*
+Chicago -- Martin Richards, Producer
+
+2003 (76th)
+BEST PICTURE
+*
+The Lord of the Rings: The Return of the King -- Barrie M. Osborne, Peter Jackson and Fran Walsh, Producers
+
+2004 (77th)
+BEST PICTURE
+*
+Million Dollar Baby -- Clint Eastwood, Albert S. Ruddy and Tom Rosenberg, Producers
+
+2005 (78th)
+BEST PICTURE
+*
+Crash -- Paul Haggis and Cathy Schulman, Producers
+
+2006 (79th)
+BEST PICTURE
+*
+The Departed -- Graham King, Producer
+© Academy of Motion Picture Arts and Sciences
\ No newline at end of file
Binary file test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/images/TableDemo.gif has changed
Binary file test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/images/goldstar.png has changed
Binary file test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/images/nominee.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/oscars.xml Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,1 @@
+<?xml version="1.0" encoding="UTF-8"?>
<oscars xmlns:osc-results="http://www.fatdog.com/oscar-results"
osc-results:warning="LIMIT [125000 item(s)] exceeded, 1103 node(s) removed"
version="3.69">
<fm>
<p>This data has been marked up in XML and placed into the public domain by Howard Katz,</p>
<p>Fatdog Software Inc., 2006. It may be freely copied and distributed worldwide.</p>
</fm>
<actor year="1928">
<won>
<movie>The Last Command</movie>
<movie>The Way of All Flesh</movie>
<person>Emil Jannings</person></won></actor>
<actor year="1928">
<lost>
<movie>The Noose</movie>
<movie>The Patent Leather Kid</movie>
<person>Richard Barthelmess</person></lost></actor>
<actor year="1928">
<lost>
<movie>The Circus</movie>
<person>Charles Chaplin</person></lost></actor>
<actress year="1928">
<won>
<movie>7th Heaven</movie>
<movie>Street Angel</movie>
<movie>Sunrise</movie>
<person>Janet Gaynor</person></won></actress>
<actress year="1928">
<lost>
<movie>A Ship Comes in</movie>
<person>Louise Dresser</person></lost></actress>
<actress year="1928">
<lost>
<movie>Sadie Thompson</movie>
<person>Gloria Swanson</person></lost></actress>
<artDirection year="1928">
<won>
<movie>The Dove</movie>
<movie>The Tempest</movie>
<person>William Cameron Menzies</person></won></artDirection>
<artDirection year="1928">
<lost>
<movie>7th Heaven</movie>
<person>Harry Oliver</person></lost></artDirection>
<artDirection year="1928">
<lost>
<movie>Sunrise</movie>
<person>Rochus Gliese</person></lost></artDirection>
<bestPicture year="1928" officially="Outstanding Picture">
<won>
<movie>Wings</movie>
<org>Paramount Famous Lasky</org></won></bestPicture>
<bestPicture year="1928" officially="Outstanding Picture">
<lost>
<movie>7th Heaven</movie>
<org>Fox</org></lost></bestPicture>
<bestPicture year="1928" officially="Outstanding Picture">
<lost>
<movie>The Racket</movie>
<org>The Caddo Company</org></lost></bestPicture>
<cinematography year="1928">
<won>
<movie>Sunrise</movie>
<person>Charles Rosher</person>
<person>Karl Struss</person></won></cinematography>
<cinematography year="1928">
<lost>
<movie>The Devil Dancer</movie>
<movie>The Magic Flame</movie>
<movie>Sadie Thompson</movie>
<person>George Barnes</person></lost></cinematography>
<director year="1928" subcat="comedy">
<won>
<movie>Two Arabian Knights</movie>
<person>Lewis Milestone</person></won></director>
<director year="1928" subcat="comedy">
<lost>
<movie>Speedy</movie>
<person>Ted Wilde</person></lost></director>
<director year="1928" subcat="drama">
<won>
<movie>7th Heaven</movie>
<person>Frank Borzage</person></won></director>
<director year="1928" subcat="drama">
<lost>
<movie>The Crowd</movie>
<person>King Vidor</person></lost></director>
<director year="1928" subcat="drama">
<lost>
<movie>Sorrell and Son</movie>
<person>Herbert Brenon</person></lost></director>
<engEffects year="1928" note="archaic">
<won>
<movie>Wings</movie>
<person>Roy Pomeroy</person></won></engEffects>
<engEffects year="1928" note="archaic">
<lost>
<person>Ralph Hammeras</person>
<person>Nugent Slaughter</person></lost></engEffects>
<uniqueArtisticPicture year="1928" note="archaic">
<won>
<movie>Sunrise</movie>
<org>Fox</org></won></uniqueArtisticPicture>
<uniqueArtisticPicture year="1928" note="archaic">
<lost>
<movie>Chang</movie>
<org>Paramount Famous Lasky</org></lost></uniqueArtisticPicture>
<uniqueArtisticPicture year="1928" note="archaic">
<lost>
<movie>The Crowd</movie>
<org>Metro-Goldwyn-Mayer</org></lost></uniqueArtisticPicture>
<writing year="1928" subcat="adaptation">
<won>
<movie>7th Heaven</movie>
<person>Benjamin Glazer</person></won></writing>
<writing year="1928" subcat="adaptation">
<lost>
<movie>Glorious Betsy</movie>
<person>Anthony Coldeway</person></lost></writing>
<writing year="1928" subcat="adaptation">
<lost>
<movie>The Jazz Singer</movie>
<person>Alfred Cohn</person></lost></writing>
<writing year="1928" subcat="original story">
<won>
<movie>Underworld</movie>
<person>Ben Hecht</person></won></writing>
<writing year="1928" subcat="original story">
<lost>
<movie>The Last Command</movie>
<person>Lajos Biro</person></lost></writing>
<writing year="1928" subcat="title">
<won>
<person>Joseph Farnham</person></won></writing>
<writing year="1928" subcat="title">
<lost>
<person>George Marion Jr.</person></lost></writing>
<writing year="1928" subcat="title">
<lost>
<movie>The Private Life of Helen of Troy</movie>
<person>Gerald Duffy</person></lost></writing>
<actor year="1929">
<won>
<movie>In Old Arizona</movie>
<person>Warner Baxter</person></won></actor>
<actor year="1929">
<lost>
<movie>Thunderbolt</movie>
<person>George Bancroft</person></lost></actor>
<actor year="1929">
<lost>
<movie>Alibi</movie>
<person>Chester Morris</person></lost></actor>
<actor year="1929">
<lost>
<movie>The Valiant</movie>
<person>Paul Muni</person></lost></actor>
<actor year="1929">
<lost>
<movie>The Patriot</movie>
<person>Lewis Stone</person></lost></actor>
<actress year="1929">
<won>
<movie>Coquette</movie>
<person>Mary Pickford</person></won></actress>
<actress year="1929">
<lost>
<movie>Madame X</movie>
<person>Ruth Chatterton</person></lost></actress>
<actress year="1929">
<lost>
<movie>The Barker</movie>
<person>Betty Compson</person></lost></actress>
<actress year="1929">
<lost>
<movie>The Letter</movie>
<person>Jeanne Eagels</person></lost></actress>
<actress year="1929">
<lost>
<movie>The Divine Lady</movie>
<person>Corinne Griffith</person></lost></actress>
<actress year="1929">
<lost>
<movie>The Broadway Melody</movie>
<person>Bessie Love</person></lost></actress>
<artDirection year="1929">
<won>
<movie>The Bridge of San Luis Rey</movie>
<person>Cedric Gibbons</person></won></artDirection>
<artDirection year="1929">
<lost>
<movie>Alibi</movie>
<movie>The Awakening</movie>
<person>William Cameron Menzies</person></lost></artDirection>
<artDirection year="1929">
<lost>
<movie>Dynamite</movie>
<person>Mitchell Leisen</person></lost></artDirection>
<artDirection year="1929">
<lost>
<movie>The Patriot</movie>
<person>Hans Dreier</person></lost></artDirection>
<artDirection year="1929">
<lost>
<movie>Street Angel</movie>
<person>Harry Oliver</person></lost></artDirection>
<bestPicture year="1929">
<won>
<movie>The Broadway Melody</movie>
<org>Metro-Goldwyn-Mayer</org></won></bestPicture>
<bestPicture year="1929">
<lost>
<movie>Alibi</movie>
<org>Art Cinema</org></lost></bestPicture>
<bestPicture year="1929">
<lost>
<movie>Hollywood Revue</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1929">
<lost>
<movie>In Old Arizona</movie>
<org>Fox</org></lost></bestPicture>
<bestPicture year="1929">
<lost>
<movie>The Patriot</movie>
<org>Paramount Famous Lasky</org></lost></bestPicture>
<cinematography year="1929">
<won>
<movie>White Shadows in the South Seas</movie>
<person>Clyde De Vinna</person></won></cinematography>
<cinematography year="1929">
<lost>
<movie>The Divine Lady</movie>
<person>John Seitz</person></lost></cinematography>
<cinematography year="1929">
<lost>
<movie>Four Devils</movie>
<movie>Street Angel</movie>
<person>Ernest Palmer</person></lost></cinematography>
<cinematography year="1929">
<lost>
<movie>In Old Arizona</movie>
<person>Arthur Edeson</person></lost></cinematography>
<cinematography year="1929">
<lost>
<movie>Our Dancing Daughters</movie>
<person>George Barnes</person></lost></cinematography>
<director year="1929">
<won>
<movie>The Divine Lady</movie>
<person>Frank Lloyd</person></won></director>
<director year="1929">
<lost>
<movie>The Broadway Melody</movie>
<person>Harry Beaumont</person></lost></director>
<director year="1929">
<lost>
<movie>Drag</movie>
<person>Frank Lloyd</person></lost></director>
<director year="1929">
<lost>
<movie>In Old Arizona</movie>
<person>Irving Cummings</person></lost></director>
<director year="1929">
<lost>
<movie>Madame X</movie>
<person>Lionel Barrymore</person></lost></director>
<director year="1929">
<lost>
<movie>The Patriot</movie>
<person>Ernst Lubitsch</person></lost></director>
<director year="1929">
<lost>
<movie>Weary River</movie>
<person>Frank Lloyd</person></lost></director>
<writing year="1929">
<won>
<movie>The Patriot</movie>
<person>Hans Kraly</person></won></writing>
<writing year="1929">
<lost>
<movie>The Cop</movie>
<person>Elliott Clawson</person></lost></writing>
<writing year="1929">
<lost>
<movie>In Old Arizona</movie>
<person>Tom Barry</person></lost></writing>
<writing year="1929">
<lost>
<movie>The Last of Mrs. Cheyney</movie>
<person>Hans Kraly</person></lost></writing>
<writing year="1929">
<lost>
<movie>The Leatherneck</movie>
<person>Elliott Clawson</person></lost></writing>
<writing year="1929">
<lost>
<movie>Our Dancing Daughters</movie>
<person>Josephine Lovett</person></lost></writing>
<writing year="1929">
<lost>
<movie>Sal of Singapore</movie>
<person>Elliott Clawson</person></lost></writing>
<writing year="1929">
<lost>
<movie>Skyscraper</movie>
<person>Elliott Clawson</person></lost></writing>
<writing year="1929">
<lost>
<movie>The Valiant</movie>
<person>Tom Barry</person></lost></writing>
<writing year="1929">
<lost>
<movie>A Woman of Affairs</movie>
<person>Bess Meredyth</person></lost></writing>
<writing year="1929">
<lost>
<movie>Wonder of Women</movie>
<person>Bess Meredyth</person></lost></writing>
<actor year="1930">
<won>
<movie>Disraeli</movie>
<person>George Arliss</person></won></actor>
<actor year="1930">
<lost>
<movie>The Green Goddess</movie>
<person>George Arliss</person></lost></actor>
<actor year="1930">
<lost>
<movie>The Big House</movie>
<person>Wallace Beery</person></lost></actor>
<actor year="1930">
<lost>
<movie>The Big Pond</movie>
<person>Maurice Chevalier</person></lost></actor>
<actor year="1930">
<lost>
<movie>The Love Parade</movie>
<person>Maurice Chevalier</person></lost></actor>
<actor year="1930">
<lost>
<movie>Bulldog Drummond</movie>
<person>Ronald Colman</person></lost></actor>
<actor year="1930">
<lost>
<movie>Condemned</movie>
<person>Ronald Colman</person></lost></actor>
<actor year="1930">
<lost>
<movie>The Rogue Song</movie>
<person>Lawrence Tibbett</person></lost></actor>
<actress year="1930">
<won>
<movie>The Divorcee</movie>
<person>Norma Shearer</person></won></actress>
<actress year="1930">
<lost>
<movie>The Devil's Holiday</movie>
<person>Nancy Carroll</person></lost></actress>
<actress year="1930">
<lost>
<movie>Sarah and Son</movie>
<person>Ruth Chatterton</person></lost></actress>
<actress year="1930">
<lost>
<movie>Anna Christie</movie>
<person>Greta Garbo</person></lost></actress>
<actress year="1930">
<lost>
<movie>Romance</movie>
<person>Greta Garbo</person></lost></actress>
<actress year="1930">
<lost>
<movie>Their Own Desire</movie>
<person>Norma Shearer</person></lost></actress>
<actress year="1930">
<lost>
<movie>The Trespasser</movie>
<person>Gloria Swanson</person></lost></actress>
<artDirection year="1930">
<won>
<movie>King of Jazz</movie>
<person>Herman Rosse</person></won></artDirection>
<artDirection year="1930">
<lost>
<movie>Bulldog Drummond</movie>
<person>William Cameron Menzies</person></lost></artDirection>
<artDirection year="1930">
<lost>
<movie>The Love Parade</movie>
<person>Hans Dreier</person></lost></artDirection>
<artDirection year="1930">
<lost>
<movie>Sally</movie>
<person>Jack Okey</person></lost></artDirection>
<artDirection year="1930">
<lost>
<movie>The Vagabond King</movie>
<person>Hans Dreier</person></lost></artDirection>
<bestPicture year="1930">
<won>
<movie>All Quiet on the Western Front</movie>
<org>Universal</org></won></bestPicture>
<bestPicture year="1930">
<lost>
<movie>The Big House</movie>
<org>Cosmopolitan</org></lost></bestPicture>
<bestPicture year="1930">
<lost>
<movie>Disraeli</movie>
<org>Warner Bros.</org></lost></bestPicture>
<bestPicture year="1930">
<lost>
<movie>The Divorcee</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1930">
<lost>
<movie>The Love Parade</movie>
<org>Paramount Famous Lasky</org></lost></bestPicture>
<cinematography year="1930">
<won>
<movie>With Byrd at the South Pole</movie>
<person>Joseph T. Rucker</person>
<person>Willard Van Der Veer</person></won></cinematography>
<cinematography year="1930">
<lost>
<movie>All Quiet on the Western Front</movie>
<person>Arthur Edeson</person></lost></cinematography>
<cinematography year="1930">
<lost>
<movie>Anna Christie</movie>
<person>William Daniels</person></lost></cinematography>
<cinematography year="1930">
<lost>
<movie>Hell's Angels</movie>
<person>Gaetano Gaudio)</person>
<person>Harry Perry</person></lost></cinematography>
<cinematography year="1930">
<lost>
<movie>The Love Parade</movie>
<person>Victor Milner</person></lost></cinematography>
<director year="1930">
<won>
<movie>All Quiet on the Western Front</movie>
<person>Lewis Milestone</person></won></director>
<director year="1930">
<lost>
<movie>Anna Christie</movie>
<person>Clarence Brown</person></lost></director>
<director year="1930">
<lost>
<movie>The Divorcee</movie>
<person>Robert Leonard</person></lost></director>
<director year="1930">
<lost>
<movie>Hallelujah</movie>
<person>King Vidor</person></lost></director>
<director year="1930">
<lost>
<movie>The Love Parade</movie>
<person>Ernst Lubitsch</person></lost></director>
<director year="1930">
<lost>
<movie>Romance</movie>
<person>Clarence Brown</person></lost></director>
<sound year="1930">
<won>
<movie>The Big House</movie>
<org>Metro-Goldwyn-Mayer Studio Sound Department</org>
<person>Douglas Shearer</person></won></sound>
<sound year="1930">
<lost>
<movie>The Case of Sergeant Grischa</movie>
<org>RKO Radio Studio Sound Department</org>
<person>John Tribby</person></lost></sound>
<sound year="1930">
<lost>
<movie>The Love Parade</movie>
<org>Paramount Famous Lasky Studio Sound Department</org>
<person>Franklin Hansen</person></lost></sound>
<sound year="1930">
<lost>
<movie>Raffles</movie>
<org>United Artists Studio Sound Department</org>
<person>Oscar Lagerstrom</person></lost></sound>
<sound year="1930">
<lost>
<movie>Song of the Flame</movie>
<org>First National Studio Sound Department</org>
<person>George Groves</person></lost></sound>
<writing year="1930">
<won>
<movie>The Big House</movie>
<person>Frances Marion</person></won></writing>
<writing year="1930">
<lost>
<movie>All Quiet on the Western Front</movie>
<person>George Abbott</person>
<person>Maxwell Anderson</person>
<person>Del Andrews</person></lost></writing>
<writing year="1930">
<lost>
<movie>Disraeli</movie>
<person>Julian Josephson</person></lost></writing>
<writing year="1930">
<lost>
<movie>The Divorcee</movie>
<person>John Meehan</person></lost></writing>
<writing year="1930">
<lost>
<movie>Street of Chance</movie>
<person>Howard Estabrook</person></lost></writing>
<actor year="1931">
<won>
<movie>A Free Soul</movie>
<person>Lionel Barrymore</person></won></actor>
<actor year="1931">
<lost>
<movie>Skippy</movie>
<person>Jackie Cooper</person></lost></actor>
<actor year="1931">
<lost>
<movie>Cimarron</movie>
<person>Richard Dix</person></lost></actor>
<actor year="1931">
<lost>
<movie>The Royal Family of Broadway</movie>
<person>Fredric March</person></lost></actor>
<actor year="1931">
<lost>
<movie>The Front Page</movie>
<person>Adolphe Menjou</person></lost></actor>
<actress year="1931">
<won>
<movie>Min and Bill</movie>
<person>Marie Dressler</person></won></actress>
<actress year="1931">
<lost>
<movie>Morocco</movie>
<person>Marlene Dietrich</person></lost></actress>
<actress year="1931">
<lost>
<movie>Cimarron</movie>
<person>Irene Dunne</person></lost></actress>
<actress year="1931">
<lost>
<movie>Holiday</movie>
<person>Ann Harding</person></lost></actress>
<actress year="1931">
<lost>
<movie>A Free Soul</movie>
<person>Norma Shearer</person></lost></actress>
<artDirection year="1931">
<won>
<movie>Cimarron</movie>
<person>Max Ree</person></won></artDirection>
<artDirection year="1931">
<lost>
<movie>Just Imagine</movie>
<person>Stephen Goosson</person>
<person>Ralph Hammeras</person></lost></artDirection>
<artDirection year="1931">
<lost>
<movie>Morocco</movie>
<person>Hans Dreier</person></lost></artDirection>
<artDirection year="1931">
<lost>
<movie>Svengali</movie>
<person>Anton Grot</person></lost></artDirection>
<artDirection year="1931">
<lost>
<movie>Whoopee!</movie>
<person>Richard Day</person></lost></artDirection>
<bestPicture year="1931">
<won>
<movie>Cimarron</movie>
<org>RKO Radio</org></won></bestPicture>
<bestPicture year="1931">
<lost>
<movie>East Lynne</movie>
<org>Fox</org></lost></bestPicture>
<bestPicture year="1931">
<lost>
<movie>The Front Page</movie>
<org>The Caddo Company</org></lost></bestPicture>
<bestPicture year="1931">
<lost>
<movie>Skippy</movie>
<org>Paramount Publix</org></lost></bestPicture>
<bestPicture year="1931">
<lost>
<movie>Trader Horn</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<cinematography year="1931">
<won>
<movie>Tabu</movie>
<person>Floyd Crosby</person></won></cinematography>
<cinematography year="1931">
<lost>
<movie>Cimarron</movie>
<person>Edward Cronjager</person></lost></cinematography>
<cinematography year="1931">
<lost>
<movie>Morocco</movie>
<person>Lee Garmes</person></lost></cinematography>
<cinematography year="1931">
<lost>
<movie>The Right to Love</movie>
<person>Charles Lang</person></lost></cinematography>
<cinematography year="1931">
<lost>
<movie>Svengali</movie>
<person>Barney "Chick" McGill</person></lost></cinematography>
<director year="1931">
<won>
<movie>Skippy</movie>
<person>Norman Taurog</person></won></director>
<director year="1931">
<lost>
<movie>Cimarron</movie>
<person>Wesley Ruggles</person></lost></director>
<director year="1931">
<lost>
<movie>A Free Soul</movie>
<person>Clarence Brown</person></lost></director>
<director year="1931">
<lost>
<movie>The Front Page</movie>
<person>Lewis Milestone</person></lost></director>
<director year="1931">
<lost>
<movie>Morocco</movie>
<person>Josef Von Sternberg</person></lost></director>
<sound year="1931">
<won>
<org>Samuel Goldwyn - United Artists Studio Sound Department</org></won></sound>
<sound year="1931">
<lost>
<org>Metro-Goldwyn-Mayer Studio Sound Department</org></lost></sound>
<sound year="1931">
<lost>
<org>Paramount Publix Studio Sound Department</org></lost></sound>
<sound year="1931">
<lost>
<org>RKO Radio Studio Sound Department</org></lost></sound>
<writing year="1931" subcat="adaptation">
<won>
<movie>Cimarron</movie>
<person>Howard Estabrook</person></won></writing>
<writing year="1931" subcat="adaptation">
<lost>
<movie>The Criminal Code</movie>
<person>Seton I. Miller</person>
<person>Fred Niblo Jr.</person></lost></writing>
<writing year="1931" subcat="adaptation">
<lost>
<movie>Holiday</movie>
<person>Horace Jackson</person></lost></writing>
<writing year="1931" subcat="adaptation">
<lost>
<movie>Little Caesar</movie>
<person>Francis Faragoh</person>
<person>Robert N. Lee</person></lost></writing>
<writing year="1931" subcat="adaptation">
<lost>
<movie>Skippy</movie>
<person>Joseph L. Mankiewicz</person>
<person>Sam Mintz</person></lost></writing>
<writing year="1931" subcat="original story">
<won>
<movie>The Dawn Patrol</movie>
<person>John Monk Saunders</person></won></writing>
<writing year="1931" subcat="original story">
<lost>
<movie>The Doorway to Hell</movie>
<person>Rowland Brown</person></lost></writing>
<writing year="1931" subcat="original story">
<lost>
<movie>Laughter</movie>
<person>Harry d'Abbadie d'Arrast</person>
<person>Douglas Doty</person>
<person>Donald Ogden Stewart</person></lost></writing>
<writing year="1931" subcat="original story">
<lost>
<movie>The Public Enemy</movie>
<person>John Bright</person>
<person>Kubec Glasmon</person></lost></writing>
<writing year="1931" subcat="original story">
<lost>
<movie>Smart Money</movie>
<person>Lucien Hubbard</person>
<person>Joseph Jackson</person></lost></writing>
<actor year="1932">
<won>
<movie>The Champ</movie>
<person>Wallace Beery</person></won></actor>
<actor year="1932">
<won>
<movie>Dr. Jekyll and Mr. Hyde</movie>
<person>Fredric March</person></won></actor>
<actor year="1932">
<lost>
<movie>The Guardsman</movie>
<person>Alfred Lunt</person></lost></actor>
<actress year="1932">
<won>
<movie>The Sin of Madelon Claudet</movie>
<person>Helen Hayes</person></won></actress>
<actress year="1932">
<lost>
<movie>Emma</movie>
<person>Marie Dressler</person></lost></actress>
<actress year="1932">
<lost>
<movie>The Guardsman</movie>
<person>Lynn Fontanne</person></lost></actress>
<artDirection year="1932">
<won>
<movie>Transatlantic</movie>
<person>Gordon Wiles</person></won></artDirection>
<artDirection year="1932">
<lost>
<movie>Arrowsmith</movie>
<person>Richard Day</person></lost></artDirection>
<artDirection year="1932">
<lost>
<movie>A Nous La Liberte</movie>
<person>Lazare Meerson</person></lost></artDirection>
<bestPicture year="1932">
<won>
<movie>Grand Hotel</movie>
<org>Metro-Goldwyn-Mayer</org></won></bestPicture>
<bestPicture year="1932">
<lost>
<movie>Arrowsmith</movie>
<org>Samuel Goldwyn</org></lost></bestPicture>
<bestPicture year="1932">
<lost>
<movie>Bad Girl</movie>
<org>Fox</org></lost></bestPicture>
<bestPicture year="1932">
<lost>
<movie>The Champ</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1932">
<lost>
<movie>Five Star Final</movie>
<org>First National</org></lost></bestPicture>
<bestPicture year="1932">
<lost>
<movie>One Hour with You</movie>
<org>Paramount Publix</org></lost></bestPicture>
<bestPicture year="1932">
<lost>
<movie>Shanghai Express</movie>
<org>Paramount Publix</org></lost></bestPicture>
<bestPicture year="1932">
<lost>
<movie>The Smiling Lieutenant</movie>
<org>Paramount Publix</org></lost></bestPicture>
<cinematography year="1932">
<won>
<movie>Shanghai Express</movie>
<person>Lee Garmes</person></won></cinematography>
<cinematography year="1932">
<lost>
<movie>Arrowsmith</movie>
<person>Ray June</person></lost></cinematography>
<cinematography year="1932">
<lost>
<movie>Dr. Jekyll and Mr. Hyde</movie>
<person>Karl Struss</person></lost></cinematography>
<director year="1932">
<won>
<movie>Bad Girl</movie>
<person>Frank Borzage</person></won></director>
<director year="1932">
<lost>
<movie>The Champ</movie>
<person>King Vidor</person></lost></director>
<director year="1932">
<lost>
<movie>Shanghai Express</movie>
<person>Josef Von Sternberg</person></lost></director>
<shortAnimation year="1932">
<won>
<movie>Flowers and Trees</movie>
<person>Walt Disney</person></won></shortAnimation>
<shortAnimation year="1932">
<lost>
<movie>It's Got Me Again</movie>
<person>Leon Schlesinger</person></lost></shortAnimation>
<shortAnimation year="1932">
<lost>
<movie>Mickey's Orphans</movie>
<person>Walt Disney</person></lost></shortAnimation>
<shortLiveAction year="1932" subcat="comedy">
<won>
<movie>The Music Box</movie>
<person>Hal Roach</person></won></shortLiveAction>
<shortLiveAction year="1932" subcat="comedy">
<lost>
<movie>The Loud Mouth</movie>
<person>Mack Sennett</person></lost></shortLiveAction>
<shortLiveAction year="1932" subcat="comedy">
<lost>
<movie>Scratch-As-Catch-Can</movie>
<org>RKO Radio</org></lost></shortLiveAction>
<shortLiveAction year="1932" subcat="comedy">
<lost>
<movie>Stout Hearts and Willing Hands</movie>
<org>RKO Radio</org></lost></shortLiveAction>
<shortLiveAction year="1932" subcat="novelty">
<won>
<movie>Wrestling Swordfish</movie>
<person>Mack Sennett</person></won></shortLiveAction>
<shortLiveAction year="1932" subcat="novelty">
<lost>
<movie>Screen Souvenirs</movie>
<org>Paramount Publix</org></lost></shortLiveAction>
<shortLiveAction year="1932" subcat="novelty">
<lost>
<movie>Swing High</movie>
<org>Metro-Goldwyn-Mayer</org></lost></shortLiveAction>
<sound year="1932">
<won>
<org>Metro-Goldwyn-Mayer Studio Sound Department</org></won></sound>
<sound year="1932">
<lost>
<org>Paramount Publix Studio Sound Department</org></lost></sound>
<sound year="1932">
<lost>
<org>RKO Radio Studio Sound Department</org></lost></sound>
<sound year="1932">
<lost>
<org>Warner Bros.-First National Studio Sound Department</org></lost></sound>
<writing year="1932" subcat="adaptation">
<won>
<movie>Bad Girl</movie>
<person>Edwin Burke</person></won></writing>
<writing year="1932" subcat="adaptation">
<lost>
<movie>Arrowsmith</movie>
<person>Sidney Howard</person></lost></writing>
<writing year="1932" subcat="adaptation">
<lost>
<movie>Dr. Jekyll and Mr. Hyde</movie>
<person>Percy Heath</person>
<person>Samuel Hoffenstein</person></lost></writing>
<writing year="1932" subcat="original story">
<won>
<movie>The Champ</movie>
<person>Frances Marion</person></won></writing>
<writing year="1932" subcat="original story">
<lost>
<movie>Lady and Gent</movie>
<person>Grover Jones</person>
<person>William Slavens McNutt</person></lost></writing>
<writing year="1932" subcat="original story">
<lost>
<movie>The Star Witness</movie>
<person>Lucien Hubbard</person></lost></writing>
<writing year="1932" subcat="original story">
<lost>
<movie>What Price Hollywood?</movie>
<person>Jane Murfin</person>
<person>Adela Rogers St. Johns</person></lost></writing>
<actor year="1933">
<won>
<movie>The Private Life of Henry VIII</movie>
<person>Charles Laughton</person></won></actor>
<actor year="1933">
<lost>
<movie>Berkeley Square</movie>
<person>Leslie Howard</person></lost></actor>
<actor year="1933">
<lost>
<movie>I Am a Fugitive from a Chain Gang</movie>
<person>Paul Muni</person></lost></actor>
<actress year="1933">
<won>
<movie>Morning Glory</movie>
<person>Katharine Hepburn</person></won></actress>
<actress year="1933">
<lost>
<movie>Lady for a Day</movie>
<person>May Robson</person></lost></actress>
<actress year="1933">
<lost>
<movie>Cavalcade</movie>
<person>Diana Wynyard</person></lost></actress>
<artDirection year="1933">
<won>
<movie>Cavalcade</movie>
<person>William S. Darling</person></won></artDirection>
<artDirection year="1933">
<lost>
<movie>A Farewell to Arms</movie>
<person>Roland Anderson</person>
<person>Hans Dreier</person></lost></artDirection>
<artDirection year="1933">
<lost>
<movie>When Ladies Meet</movie>
<person>Cedric Gibbons</person></lost></artDirection>
<assistantDirector year="1933" note="archaic">
<won>
<person>Charles Barton</person></won></assistantDirector>
<assistantDirector year="1933" note="archaic">
<won>
<person>Scott Beal</person></won></assistantDirector>
<assistantDirector year="1933" note="archaic">
<won>
<person>Charles Dorian</person></won></assistantDirector>
<assistantDirector year="1933" note="archaic">
<won>
<person>Fred Fox</person></won></assistantDirector>
<assistantDirector year="1933" note="archaic">
<won>
<person>Gordon Hollingshead</person></won></assistantDirector>
<assistantDirector year="1933" note="archaic">
<won>
<person>Dewey Starkey</person></won></assistantDirector>
<assistantDirector year="1933" note="archaic">
<won>
<person>William Tummel</person></won></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Al Alborn</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Sidney S. Brod</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Bunny Dull</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Percy Ikerd</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Arthur Jacobson</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Eddie Killey</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Joe McDonough</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>W. J. Reiter</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Frank X. Shaw</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>Benjamin Silvey</person></lost></assistantDirector>
<assistantDirector year="1933" note="archaic">
<lost>
<person>John S. Waters</person></lost></assistantDirector>
<bestPicture year="1933">
<won>
<movie>Cavalcade</movie>
<org>Fox</org></won></bestPicture>
<bestPicture year="1933">
<lost>
<movie>42nd Street</movie>
<org>Warner Bros.</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>A Farewell to Arms</movie>
<org>Paramount</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>I Am a Fugitive from a Chain Gang</movie>
<org>Warner Bros.</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>Lady for a Day</movie>
<org>Columbia</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>Little Women</movie>
<org>RKO Radio</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>The Private Life of Henry VIII</movie>
<org>London Films</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>She Done Him Wrong</movie>
<org>Paramount</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>Smilin' Through</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1933">
<lost>
<movie>State Fair</movie>
<org>Fox</org></lost></bestPicture>
<cinematography year="1933">
<won>
<movie>A Farewell to Arms</movie>
<person>Charles Bryant Lang Jr.</person></won></cinematography>
<cinematography year="1933">
<lost>
<movie>Reunion in Vienna</movie>
<person>George J. Folsey</person></lost></cinematography>
<cinematography year="1933">
<lost>
<movie>The Sign of the Cross</movie>
<person>Karl Struss</person></lost></cinematography>
<director year="1933">
<won>
<movie>Cavalcade</movie>
<person>Frank Lloyd</person></won></director>
<director year="1933">
<lost>
<movie>Lady for a Day</movie>
<person>Frank Capra</person></lost></director>
<director year="1933">
<lost>
<movie>Little Women</movie>
<person>George Cukor</person></lost></director>
<shortAnimation year="1933">
<won>
<movie>The Three Little Pigs</movie>
<person>Walt Disney</person></won></shortAnimation>
<shortAnimation year="1933">
<lost>
<movie>Building a Building</movie>
<person>Walt Disney</person></lost></shortAnimation>
<shortAnimation year="1933">
<lost>
<movie>The Merry Old Soul</movie>
<person>Walter Lantz</person></lost></shortAnimation>
<shortLiveAction year="1933" subcat="comedy">
<won>
<movie>So This Is Harris</movie>
<person>Louis Brock</person></won></shortLiveAction>
<shortLiveAction year="1933" subcat="comedy">
<lost>
<movie>Mister Mugg</movie>
<person>Warren Doane</person></lost></shortLiveAction>
<shortLiveAction year="1933" subcat="comedy">
<lost>
<movie>A Preferred List</movie>
<person>Louis Brock</person></lost></shortLiveAction>
<shortLiveAction year="1933" subcat="novelty">
<won>
<movie>Krakatoa</movie>
<person>Joe Rock</person></won></shortLiveAction>
<shortLiveAction year="1933" subcat="novelty">
<lost>
<movie>Menu</movie>
<person>Pete Smith</person></lost></shortLiveAction>
<shortLiveAction year="1933" subcat="novelty">
<lost>
<movie>The Sea</movie>
<org>Educational</org></lost></shortLiveAction>
<sound year="1933">
<won>
<movie>A Farewell to Arms</movie>
<org>Paramount Studio Sound Department</org>
<person>Franklin B. Hansen</person></won></sound>
<sound year="1933">
<lost>
<movie>42nd Street</movie>
<org>Warner Bros. Studio Sound Department</org>
<person>Nathan Levinson</person></lost></sound>
<sound year="1933">
<lost>
<movie>Gold Diggers of 1933</movie>
<org>Warner Bros. Studio Sound Department</org>
<person>Nathan Levinson</person></lost></sound>
<sound year="1933">
<lost>
<movie>I Am a Fugitive from a Chain Gang</movie>
<org>Warner Bros. Studio Sound Department</org>
<person>Nathan Levinson</person></lost></sound>
<writing year="1933" subcat="adaptation">
<won>
<movie>Little Women</movie>
<person>Victor Heerman</person>
<person>Sarah Y. Mason</person></won></writing>
<writing year="1933" subcat="adaptation">
<lost>
<movie>Lady for a Day</movie>
<person>Robert Riskin</person></lost></writing>
<writing year="1933" subcat="adaptation">
<lost>
<movie>State Fair</movie>
<person>Paul Green</person>
<person>Sonya Levien</person></lost></writing>
<writing year="1933" subcat="original story">
<won>
<movie>One Way Passage</movie>
<person>Robert Lord</person></won></writing>
<writing year="1933" subcat="original story">
<lost>
<movie>The Prizefighter and the Lady</movie>
<person>Frances Marion</person></lost></writing>
<writing year="1933" subcat="original story">
<lost>
<movie>Rasputin and the Empress</movie>
<person>Charles MacArthur</person></lost></writing>
<actor year="1934">
<won>
<movie>It Happened One Night</movie>
<person>Clark Gable</person></won></actor>
<actor year="1934">
<lost>
<movie>The Affairs of Cellini</movie>
<person>Frank Morgan</person></lost></actor>
<actor year="1934">
<lost>
<movie>The Thin Man</movie>
<person>William Powell</person></lost></actor>
<actress year="1934">
<won>
<movie>It Happened One Night</movie>
<person>Claudette Colbert</person></won></actress>
<actress year="1934">
<lost>
<movie>Of Human Bondage</movie>
<person>Bette Davis</person></lost></actress>
<actress year="1934">
<lost>
<movie>One Night of Love</movie>
<person>Grace Moore</person></lost></actress>
<actress year="1934">
<lost>
<movie>The Barretts of Wimpole Street</movie>
<person>Norma Shearer</person></lost></actress>
<artDirection year="1934">
<won>
<movie>The Merry Widow</movie>
<person>Cedric Gibbons</person>
<person>Frederic Hope</person></won></artDirection>
<artDirection year="1934">
<lost>
<movie>The Affairs of Cellini</movie>
<person>Richard Day</person></lost></artDirection>
<artDirection year="1934">
<lost>
<movie>The Gay Divorcee</movie>
<person>Carroll Clark</person>
<person>Van Nest Polglase</person></lost></artDirection>
<assistantDirector year="1934" note="archaic">
<won>
<movie>Viva Villa!</movie>
<person>John Waters</person></won></assistantDirector>
<assistantDirector year="1934" note="archaic">
<lost>
<movie>Cleopatra</movie>
<person>Cullen Tate</person></lost></assistantDirector>
<assistantDirector year="1934" note="archaic">
<lost>
<movie>Imitation of Life</movie>
<person>Scott Beal</person></lost></assistantDirector>
<bestPicture year="1934">
<won>
<movie>It Happened One Night</movie>
<org>Columbia</org></won></bestPicture>
<bestPicture year="1934">
<lost>
<movie>The Barretts of Wimpole Street</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>Cleopatra</movie>
<org>Paramount</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>Flirtation Walk</movie>
<org>First National</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>The Gay Divorcee</movie>
<org>RKO Radio</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>Here Comes the Navy</movie>
<org>Warner Bros.</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>The House of Rothschild</movie>
<org>20th Century</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>Imitation of Life</movie>
<org>Universal</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>One Night of Love</movie>
<org>Columbia</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>The Thin Man</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>Viva Villa!</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1934">
<lost>
<movie>The White Parade</movie>
<person>Jesse L. Lasky</person></lost></bestPicture>
<cinematography year="1934">
<won>
<movie>Cleopatra</movie>
<person>Victor Milner</person></won></cinematography>
<cinematography year="1934">
<lost>
<movie>The Affairs of Cellini</movie>
<person>Charles Rosher</person></lost></cinematography>
<cinematography year="1934">
<lost>
<movie>Operator 13</movie>
<person>George Folsey</person></lost></cinematography>
<director year="1934">
<won>
<movie>It Happened One Night</movie>
<person>Frank Capra</person></won></director>
<director year="1934">
<lost>
<movie>One Night of Love</movie>
<person>Victor Schertzinger</person></lost></director>
<director year="1934">
<lost>
<movie>The Thin Man</movie>
<person>W. S. Van Dyke</person></lost></director>
<filmEditing year="1934">
<won>
<movie>Eskimo</movie>
<person>Conrad Nervig</person></won></filmEditing>
<filmEditing year="1934">
<lost>
<movie>Cleopatra</movie>
<person>Anne Bauchens</person></lost></filmEditing>
<filmEditing year="1934">
<lost>
<movie>One Night of Love</movie>
<person>Gene Milford</person></lost></filmEditing>
<musicScore year="1934">
<won>
<movie>One Night of Love</movie>
<org>Columbia Studio Music Department</org>
<person>Louis Silvers</person>
<person>Gus Kahn</person>
<person>Victor Schertzinger</person></won></musicScore>
<musicScore year="1934">
<lost>
<movie>The Gay Divorcee</movie>
<org>RKO Radio Studio Music Department</org>
<person>Samuel Hoffenstein</person>
<person>Max Steiner</person>
<person>Kenneth Webb</person></lost></musicScore>
<musicScore year="1934">
<lost>
<movie>The Lost Patrol</movie>
<org>RKO Radio Studio Music Department</org>
<person>Max Steiner</person></lost></musicScore>
<musicScore year="1934">
<lost>
<movie>Captain Blood</movie>
<org>Warner Bros.-First National Studio Music Department</org>
<person>Erich Wolfgang Korngold</person>
<person>Leo Forbstein</person></lost></musicScore>
<musicScore year="1934">
<lost>
<movie>Mutiny on the Bounty</movie>
<org>Metro-Goldwyn-Mayer Studio Music Department</org>
<person>Nat W. Finston</person>
<person>Herbert Stothart</person></lost></musicScore>
<musicScore year="1934">
<lost>
<movie>Peter Ibbetson</movie>
<org>Paramount Studio Music Department</org>
<person>Irvin Talbot</person>
<person>Ernst Toch</person></lost></musicScore>
<musicSong year="1934">
<won>
<title>The Continental</title>
<movie>The Gay Divorcee</movie>
<person>Con Conrad</person>
<person>Herb Magidson</person></won></musicSong>
<musicSong year="1934">
<lost>
<title>Carioca</title>
<movie>Flying Down to Rio</movie>
<person>Edward Eliscu</person>
<person>Gus Kahn</person>
<person>Vincent Youmans</person></lost></musicSong>
<musicSong year="1934">
<lost>
<title>Love in Bloom</title>
<movie>She Loves Me Not</movie>
<person>Ralph Rainger</person>
<person>Leo Robin</person></lost></musicSong>
<shortAnimation year="1934">
<won>
<movie>The Tortoise and the Hare</movie>
<person>Walt Disney</person></won></shortAnimation>
<shortAnimation year="1934">
<lost>
<movie>Holiday Land</movie>
<person>Charles Mintz</person></lost></shortAnimation>
<shortAnimation year="1934">
<lost>
<movie>Jolly Little Elves</movie>
<person>Walter Lantz</person></lost></shortAnimation>
<shortLiveAction year="1934" subcat="comedy">
<won>
<movie>La Cucaracha</movie>
<person>Kenneth Macgowan</person></won></shortLiveAction>
<shortLiveAction year="1934" subcat="comedy">
<lost>
<movie>Men in Black</movie>
<person>Jules White</person></lost></shortLiveAction>
<shortLiveAction year="1934" subcat="comedy">
<lost>
<movie>What, No Men!</movie>
<org>Warner Bros.</org></lost></shortLiveAction>
<shortLiveAction year="1934" subcat="novelty">
<won>
<movie>City of Wax</movie>
<person>Horace Woodard</person>
<person>Stacy Woodard</person></won></shortLiveAction>
<shortLiveAction year="1934" subcat="novelty">
<lost>
<movie>Bosom Friends</movie>
<org>Skibo Productions</org></lost></shortLiveAction>
<shortLiveAction year="1934" subcat="novelty">
<lost>
<movie>Strikes and Spares</movie>
<person>Pete Smith</person></lost></shortLiveAction>
<sound year="1934">
<won>
<movie>One Night of Love</movie>
<org>Columbia Studio Sound Department</org>
<person>John Livadary</person></won></sound>
<sound year="1934">
<lost>
<movie>The Affairs of Cellini</movie>
<org>United Artists Studio Sound Department</org>
<person>Thomas T. Moulton</person></lost></sound>
<sound year="1934">
<lost>
<movie>Cleopatra</movie>
<org>Paramount Studio Sound Department</org>
<person>Franklin B. Hansen</person></lost></sound>
<sound year="1934">
<lost>
<movie>Flirtation Walk</movie>
<org>Warner Bros.-First National Studio Sound Department</org>
<person>Nathan Levinson</person></lost></sound>
<sound year="1934">
<lost>
<movie>The Gay Divorcee</movie>
<org>RKO Radio Studio Sound Department</org>
<person>Carl Dreher</person></lost></sound>
<sound year="1934">
<lost>
<movie>Imitation of Life</movie>
<org>Universal Studio Sound Department</org>
<person>Theodore Soderberg</person></lost></sound>
<sound year="1934">
<lost>
<movie>Viva Villa!</movie>
<org>Metro-Goldwyn-Mayer Studio Sound Department</org>
<person>Douglas Shearer</person></lost></sound>
<sound year="1934">
<lost>
<movie>The White Parade</movie>
<org>Fox Studio Sound Department</org>
<person>E. H. Hansen</person></lost></sound>
<writing year="1934" subcat="adaptation">
<won>
<movie>It Happened One Night</movie>
<person>Robert Riskin</person></won></writing>
<writing year="1934" subcat="adaptation">
<lost>
<movie>The Thin Man</movie>
<person>Frances Goodrich</person>
<person>Albert Hackett</person></lost></writing>
<writing year="1934" subcat="adaptation">
<lost>
<movie>Viva Villa!</movie>
<person>Ben Hecht</person></lost></writing>
<writing year="1934" subcat="original story">
<won>
<movie>Manhattan Melodrama</movie>
<person>Arthur Caesar</person></won></writing>
<writing year="1934" subcat="original story">
<lost>
<movie>Hide-Out</movie>
<person>Mauri Grashin</person></lost></writing>
<writing year="1934" subcat="original story">
<lost>
<movie>The Richest Girl in the World</movie>
<person>Norman Krasna</person></lost></writing>
<actor year="1935">
<won>
<movie>The Informer</movie>
<person>Victor McLaglen</person></won></actor>
<actor year="1935">
<lost>
<movie>Mutiny on the Bounty</movie>
<person>Clark Gable</person></lost></actor>
<actor year="1935">
<lost>
<movie>Mutiny on the Bounty</movie>
<person>Charles Laughton</person></lost></actor>
<actor year="1935">
<lost>
<movie>Black Fury</movie>
<person>Paul Muni</person></lost></actor>
<actor year="1935">
<lost>
<movie>Mutiny on the Bounty</movie>
<person>Franchot Tone</person></lost></actor>
<actress year="1935">
<won>
<movie>Dangerous</movie>
<person>Bette Davis</person></won></actress>
<actress year="1935">
<lost>
<movie>Escape Me Never</movie>
<person>Elisabeth Bergner</person></lost></actress>
<actress year="1935">
<lost>
<movie>Private Worlds</movie>
<person>Claudette Colbert</person></lost></actress>
<actress year="1935">
<lost>
<movie>Alice Adams</movie>
<person>Katharine Hepburn</person></lost></actress>
<actress year="1935">
<lost>
<movie>Becky Sharp</movie>
<person>Miriam Hopkins</person></lost></actress>
<actress year="1935">
<lost>
<movie>The Dark Angel</movie>
<person>Merle Oberon</person></lost></actress>
<artDirection year="1935">
<won>
<movie>The Dark Angel</movie>
<person>Richard Day</person></won></artDirection>
<artDirection year="1935">
<lost>
<movie>The Lives of a Bengal Lancer</movie>
<person>Roland Anderson</person>
<person>Hans Dreier</person></lost></artDirection>
<artDirection year="1935">
<lost>
<movie>Top Hat</movie>
<person>Carroll Clark</person>
<person>Van Nest Polglase</person></lost></artDirection>
<assistantDirector year="1935" note="archaic">
<won>
<movie>The Lives of a Bengal Lancer</movie>
<person>Clem Beauchamp</person>
<person>Paul Wing</person></won></assistantDirector>
<assistantDirector year="1935" note="archaic">
<lost>
<movie>David Copperfield</movie>
<person>Joseph Newman</person></lost></assistantDirector>
<assistantDirector year="1935" note="archaic">
<lost>
<movie>Les Miserables</movie>
<person>Eric Stacey</person></lost></assistantDirector>
<assistantDirector year="1935" note="archaic">
<lost>
<movie>A Midsummer Night's Dream</movie>
<person>Sherry Shourds</person></lost></assistantDirector>
<bestPicture year="1935">
<won>
<movie>Mutiny on the Bounty</movie>
<org>Metro-Goldwyn-Mayer</org></won></bestPicture>
<bestPicture year="1935">
<lost>
<movie>Alice Adams</movie>
<org>RKO Radio</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>Broadway Melody of 1936</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>Captain Blood</movie>
<org>Cosmopolitan</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>David Copperfield</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>The Informer</movie>
<org>RKO Radio</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>Les Miserables</movie>
<org>20th Century</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>The Lives of a Bengal Lancer</movie>
<org>Paramount</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>A Midsummer Night's Dream</movie>
<org>Warner Bros.</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>Naughty Marietta</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>Ruggles of Red Gap</movie>
<org>Paramount</org></lost></bestPicture>
<bestPicture year="1935">
<lost>
<movie>Top Hat</movie>
<org>RKO Radio</org></lost></bestPicture>
<cinematography year="1935">
<won>
<movie>A Midsummer Night's Dream</movie>
<person>Hal Mohr</person></won></cinematography>
<cinematography year="1935">
<lost>
<movie>Barbary Coast</movie>
<person>Ray June</person></lost></cinematography>
<cinematography year="1935">
<lost>
<movie>The Crusades</movie>
<person>Victor Milner</person></lost></cinematography>
<cinematography year="1935">
<lost>
<movie>Les Miserables</movie>
<person>Gregg Toland</person></lost></cinematography>
<danceDirection year="1935" note="archaic">
<won>
<movie>Broadway Melody of 1936</movie>
<movie>Folies Bergere</movie>
<person>Dave Gould</person></won></danceDirection>
<danceDirection year="1935" note="archaic">
<lost>
<movie>All the King's Horses</movie>
<movie>Big Broadcast of 1936</movie>
<person>LeRoy Prinz</person></lost></danceDirection>
<danceDirection year="1935" note="archaic">
<lost>
<movie>Broadway Hostess</movie>
<movie>Go Into Your Dance</movie>
<person>Bobby Connolly</person></lost></danceDirection>
<danceDirection year="1935" note="archaic">
<lost>
<movie>Gold Diggers of 1935</movie>
<person>Busby Berkeley</person></lost></danceDirection>
<danceDirection year="1935" note="archaic">
<lost>
<movie>King of Burlesque</movie>
<person>Sammy Lee</person></lost></danceDirection>
<danceDirection year="1935" note="archaic">
<lost>
<movie>Top Hat</movie>
<person>Hermes Pan</person></lost></danceDirection>
<danceDirection year="1935" note="archaic">
<lost>
<movie>She</movie>
<person>Benjamin Zemach</person></lost></danceDirection>
<director year="1935">
<won>
<movie>The Informer</movie>
<person>John Ford</person></won></director>
<director year="1935">
<lost>
<movie>Captain Blood</movie>
<person>Michael Curtiz</person></lost></director>
<director year="1935">
<lost>
<movie>The Lives of a Bengal Lancer</movie>
<person>Henry Hathaway</person></lost></director>
<director year="1935">
<lost>
<movie>Mutiny on the Bounty</movie>
<person>Frank Lloyd</person></lost></director>
<filmEditing year="1935">
<won>
<movie>A Midsummer Night's Dream</movie>
<person>Ralph Dawson</person></won></filmEditing>
<filmEditing year="1935">
<lost>
<movie>David Copperfield</movie>
<person>Robert J. Kern</person></lost></filmEditing>
<filmEditing year="1935">
<lost>
<movie>The Informer</movie>
<person>George Hively</person></lost></filmEditing>
<filmEditing year="1935">
<lost>
<movie>Les Miserables</movie>
<person>Barbara McLean</person></lost></filmEditing>
<filmEditing year="1935">
<lost>
<movie>The Lives of a Bengal Lancer</movie>
<person>Ellsworth Hoagland</person></lost></filmEditing>
<filmEditing year="1935">
<lost>
<movie>Mutiny on the Bounty</movie>
<person>Margaret Booth</person></lost></filmEditing>
<musicScore year="1935">
<won>
<movie>The Informer</movie>
<org>RKO Radio Studio Music Department</org>
<person>Max Steiner</person></won></musicScore>
<musicSong year="1935">
<won>
<title>Lullaby of Broadway</title>
<movie>Gold Diggers of 1935</movie>
<person>Al Dubin</person>
<person>Harry Warren</person></won></musicSong>
<musicSong year="1935">
<lost>
<title>Cheek to Cheek</title>
<movie>Top Hat</movie>
<person>Irving Berlin</person></lost></musicSong>
<musicSong year="1935">
<lost>
<title>Lovely to Look at</title>
<movie>Roberta</movie>
<person>Dorothy Fields</person>
<person>Jerome Kern</person>
<person>Jimmy McHugh</person></lost></musicSong>
<shortAnimation year="1935">
<won>
<movie>Three Orphan Kittens</movie>
<person>Walt Disney</person></won></shortAnimation>
<shortAnimation year="1935">
<lost>
<movie>The Calico Dragon</movie>
<person>Harman-Ising</person></lost></shortAnimation>
<shortAnimation year="1935">
<lost>
<movie>Who Killed Cock Robin?</movie>
<person>Walt Disney</person></lost></shortAnimation>
<shortLiveAction year="1935" subcat="comedy">
<won>
<movie>How To Sleep</movie>
<person>Jack Chertok</person></won></shortLiveAction>
<shortLiveAction year="1935" subcat="comedy">
<lost>
<movie>Oh, My Nerves</movie>
<person>Jules White</person></lost></shortLiveAction>
<shortLiveAction year="1935" subcat="comedy">
<lost>
<movie>Tit for Tat</movie>
<person>Hal Roach</person></lost></shortLiveAction>
<shortLiveAction year="1935" subcat="novelty">
<won>
<movie>Wings Over Mt. Everest</movie>
<org>Gaumont British and Skibo Productions</org></won></shortLiveAction>
<shortLiveAction year="1935" subcat="novelty">
<lost>
<movie>Audioscopiks</movie>
<person>Pete Smith</person></lost></shortLiveAction>
<shortLiveAction year="1935" subcat="novelty">
<lost>
<movie>Camera Thrills</movie>
<org>Universal</org></lost></shortLiveAction>
<sound year="1935">
<won>
<movie>Naughty Marietta</movie>
<org>Metro-Goldwyn-Mayer Studio Sound Department</org>
<person>Douglas Shearer</person></won></sound>
<sound year="1935">
<lost>
<movie>$1,000 a Minute</movie>
<org>Republic Studio Sound Department</org></lost></sound>
<sound year="1935">
<lost>
<movie>The Bride of Frankenstein</movie>
<org>Universal Studio Sound Department</org>
<person>Gilbert Kurland</person></lost></sound>
<sound year="1935">
<lost>
<movie>Captain Blood</movie>
<org>Warner Bros.-First National Studio Sound Department</org>
<person>Nathan Levinson</person></lost></sound>
<sound year="1935">
<lost>
<movie>The Dark Angel</movie>
<org>United Artists Studio Sound Department</org>
<person>Thomas T. Moulton</person></lost></sound>
<sound year="1935">
<lost>
<movie>I Dream Too Much</movie>
<org>RKO Radio Studio Sound Department</org>
<person>Carl Dreher</person></lost></sound>
<sound year="1935">
<lost>
<movie>The Lives of a Bengal Lancer</movie>
<org>Paramount Studio Sound Department</org>
<person>Franklin B. Hansen</person></lost></sound>
<sound year="1935">
<lost>
<movie>Love Me Forever</movie>
<org>Columbia Studio Sound Department</org>
<person>John Livadary</person></lost></sound>
<sound year="1935">
<lost>
<movie>Thanks a Million</movie>
<org>20th Century-Fox Studio Sound Department</org>
<person>E. H. Hansen</person></lost></sound>
<writing year="1935" subcat="original story">
<won>
<movie>The Scoundrel</movie>
<person>Ben Hecht</person>
<person>Charles MacArthur</person></won></writing>
<writing year="1935" subcat="original story">
<lost>
<movie>Broadway Melody of 1936</movie>
<person>Moss Hart</person></lost></writing>
<writing year="1935" subcat="original story">
<lost>
<movie>G-Men</movie>
<person>Gregory Rogers</person></lost></writing>
<writing year="1935" subcat="original story">
<lost>
<movie>The Gay Deception</movie>
<person>Stephen Avery</person>
<person>Don Hartman</person></lost></writing>
<writing year="1935" subcat="screenplay">
<won>
<movie>The Informer</movie>
<person>Dudley Nichols</person></won></writing>
<writing year="1935" subcat="screenplay">
<lost>
<movie>Captain Blood</movie>
<person>Casey Robinson</person></lost></writing>
<writing year="1935" subcat="screenplay">
<lost>
<movie>The Lives of a Bengal Lancer</movie>
<person>Achmed Abdullah</person>
<person>John L. Balderston</person>
<person>Grover Jones</person>
<person>William Slavens McNutt</person>
<person>Waldemar Young</person></lost></writing>
<writing year="1935" subcat="screenplay">
<lost>
<movie>Mutiny on the Bounty</movie>
<person>Jules Furthman</person>
<person>Talbot Jennings</person>
<person>Carey Wilson</person></lost></writing>
<actor year="1936">
<won>
<movie>The Story of Louis Pasteur</movie>
<person>Paul Muni</person></won></actor>
<actor year="1936">
<lost>
<movie>Mr. Deeds Goes to Town</movie>
<person>Gary Cooper</person></lost></actor>
<actor year="1936">
<lost>
<movie>Dodsworth</movie>
<person>Walter Huston</person></lost></actor>
<actor year="1936">
<lost>
<movie>My Man Godfrey</movie>
<person>William Powell</person></lost></actor>
<actor year="1936">
<lost>
<movie>San Francisco</movie>
<person>Spencer Tracy</person></lost></actor>
<actorSupporting year="1936">
<won>
<movie>Come and Get It</movie>
<person>Walter Brennan</person></won></actorSupporting>
<actorSupporting year="1936">
<lost>
<movie>My Man Godfrey</movie>
<person>Mischa Auer</person></lost></actorSupporting>
<actorSupporting year="1936">
<lost>
<movie>Pigskin Parade</movie>
<person>Stuart Erwin</person></lost></actorSupporting>
<actorSupporting year="1936">
<lost>
<movie>Romeo and Juliet</movie>
<person>Basil Rathbone</person></lost></actorSupporting>
<actorSupporting year="1936">
<lost>
<movie>The General Died at Dawn</movie>
<person>Akim Tamiroff</person></lost></actorSupporting>
<actress year="1936">
<won>
<movie>The Great Ziegfeld</movie>
<person>Luise Rainer</person></won></actress>
<actress year="1936">
<lost>
<movie>Theodora Goes Wild</movie>
<person>Irene Dunne</person></lost></actress>
<actress year="1936">
<lost>
<movie>Valiant Is the Word for Carrie</movie>
<person>Gladys George</person></lost></actress>
<actress year="1936">
<lost>
<movie>My Man Godfrey</movie>
<person>Carole Lombard</person></lost></actress>
<actress year="1936">
<lost>
<movie>Romeo and Juliet</movie>
<person>Norma Shearer</person></lost></actress>
<actressSupporting year="1936">
<won>
<movie>Anthony Adverse</movie>
<person>Gale Sondergaard</person></won></actressSupporting>
<actressSupporting year="1936">
<lost>
<movie>The Gorgeous Hussy</movie>
<person>Beulah Bondi</person></lost></actressSupporting>
<actressSupporting year="1936">
<lost>
<movie>My Man Godfrey</movie>
<person>Alice Brady</person></lost></actressSupporting>
<actressSupporting year="1936">
<lost>
<movie>These Three</movie>
<person>Bonita Granville</person></lost></actressSupporting>
<actressSupporting year="1936">
<lost>
<movie>Dodsworth</movie>
<person>Maria Ouspenskaya</person></lost></actressSupporting>
<artDirection year="1936">
<won>
<movie>Dodsworth</movie>
<person>Richard Day</person></won></artDirection>
<artDirection year="1936">
<lost>
<movie>Anthony Adverse</movie>
<person>Anton Grot</person></lost></artDirection>
<artDirection year="1936">
<lost>
<movie>The Great Ziegfeld</movie>
<person>Cedric Gibbons</person>
<person>Eddie Imazu</person>
<person>Edwin B. Willis</person></lost></artDirection>
<artDirection year="1936">
<lost>
<movie>Lloyds of London</movie>
<person>William S. Darling</person></lost></artDirection>
<artDirection year="1936">
<lost>
<movie>The Magnificent Brute</movie>
<person>Albert S. D'Agostino</person>
<person>Jack Otterson</person></lost></artDirection>
<artDirection year="1936">
<lost>
<movie>Romeo and Juliet</movie>
<person>Cedric Gibbons</person>
<person>Frederic Hope</person>
<person>Edwin B. Willis</person></lost></artDirection>
<artDirection year="1936">
<lost>
<movie>Winterset</movie>
<person>Perry Ferguson</person></lost></artDirection>
<assistantDirector year="1936" note="archaic">
<won>
<movie>The Charge of the Light Brigade</movie>
<person>Jack Sullivan</person></won></assistantDirector>
<assistantDirector year="1936" note="archaic">
<lost>
<movie>Anthony Adverse</movie>
<person>William Cannon</person></lost></assistantDirector>
<assistantDirector year="1936" note="archaic">
<lost>
<movie>The Garden of Allah</movie>
<person>Eric G. Stacey</person></lost></assistantDirector>
<assistantDirector year="1936" note="archaic">
<lost>
<movie>The Last of the Mohicans</movie>
<person>Clem Beauchamp</person></lost></assistantDirector>
<assistantDirector year="1936" note="archaic">
<lost>
<movie>San Francisco</movie>
<person>Joseph Newman</person></lost></assistantDirector>
<bestPicture year="1936">
<won>
<movie>The Great Ziegfeld</movie>
<org>Metro-Goldwyn-Mayer</org></won></bestPicture>
<bestPicture year="1936">
<lost>
<movie>Anthony Adverse</movie>
<org>Warner Bros.</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>Dodsworth</movie>
<org>Samuel Goldwyn</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>Libeled Lady</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>Mr. Deeds Goes to Town</movie>
<org>Columbia</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>Romeo and Juliet</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>San Francisco</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>The Story of Louis Pasteur</movie>
<org>Cosmopolitan</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>A Tale of Two Cities</movie>
<org>Metro-Goldwyn-Mayer</org></lost></bestPicture>
<bestPicture year="1936">
<lost>
<movie>Three Smart Girls</movie>
<org>Universal</org></lost></bestPicture>
<cinematography year="1936">
<won>
<movie>Anthony Adverse</movie>
<person>Gaetano Gaudio</person></won></cinematography>
<cinematography year="1936">
<lost>
<movie>The General Died at Dawn</movie>
<person>Victor Milner</person></lost></cinematography>
<cinematography year="1936">
<lost>
<movie>The Gorgeous Hussy</movie>
<person>George Folsey</person></lost></cinematography>
<danceDirection year="1936" note="archaic">
<won>
<movie>The Great Ziegfeld</movie>
<person>Seymour Felix</person></won></danceDirection>
<danceDirection year="1936" note="archaic">
<lost>
<movie>Born to Dance</movie>
<person>Dave Gould</person></lost></danceDirection>
<danceDirection year="1936" note="archaic">
<lost>
<movie>Cain and Mabel</movie>
<person>Bobby Connolly</person></lost></danceDirection>
<danceDirection year="1936" note="archaic">
<lost>
<movie>Dancing Pirate</movie>
<person>Russell Lewis</person></lost></danceDirection>
<danceDirection year="1936" note="archaic">
<lost>
<movie>Gold Diggers of 1937</movie>
<person>Busby Berkeley</person></lost></danceDirection>
<danceDirection year="1936" note="archaic">
<lost>
<movie>One in a Million</movie>
<person>Jack Haskell</person></lost></danceDirection>
<danceDirection year="1936" note="archaic">
<lost>
<movie>Swing Time</movie>
<person>Hermes Pan</person></lost></danceDirection>
<director year="1936">
<won>
<movie>Mr. Deeds Goes to Town</movie>
<person>Frank Capra</person></won></director>
<director year="1936">
<lost>
<movie>Dodsworth</movie>
<person>William Wyler</person></lost></director>
<director year="1936">
<lost>
<movie>The Great Ziegfeld</movie>
<person>Robert Z. Leonard</person></lost></director>
<director year="1936">
<lost>
<movie>My Man Godfrey</movie>
<person>Gregory La Cava</person></lost></director>
<director year="1936">
<lost>
<movie>San Francisco</movie>
<person>W. S. Van Dyke</person></lost></director>
<filmEditing year="1936">
<won>
<movie>Anthony Adverse</movie>
<person>Ralph Dawson</person></won></filmEditing>
<filmEditing year="1936">
<lost>
<movie>Come and Get It</movie>
<person>Edward Curtiss</person></lost></filmEditing>
<filmEditing year="1936">
<lost>
<movie>The Great Ziegfeld</movie>
<person>William S. Gray</person></lost></filmEditing>
<filmEditing year="1936">
<lost>
<movie>Lloyds of London</movie>
<person>Barbara McLean</person></lost></filmEditing>
<filmEditing year="1936">
<lost>
<movie>A Tale of Two Cities</movie>
<person>Conrad A. Nervig</person></lost></filmEditing>
<filmEditing year="1936">
<lost>
<movie>Theodora Goes Wild</movie>
<person>Otto Meyer</person></lost></filmEditing>
<musicScore year="1936">
<won>
<movie>Anthony Adverse</movie>
<org>Warner Bros. Studio Music Department</org>
<person>Erich Wolfgang Korngold</person>
<person>Leo Forbstein</person></won></musicScore>
<musicScore year="1936">
<lost>
<movie>The Charge of the Light Brigade</movie>
<org>Max Steiner, Warner Bros. Studio Music Department</org>
<person>Max Steiner</person>
<person>Leo Forbstein</person></lost></musicScore>
<musicScore year="1936">
<lost>
<movie>The Garden of Allah</movie>
<org>Selznick International Pictures Music Department</org>
<person>Max Steiner</person></lost></musicScore>
<musicScore year="1936">
<lost>
<movie>The General Died at Dawn</movie>
<org>Paramount Studio Music Department</org>
<person>Werner Janssen</person>
<person>Boris Morros</person></lost></musicScore>
<musicScore year="1936">
<lost>
<movie>Winterset</movie>
<org>RKO Radio Studio Music Department</org>
<person>Nathaniel Shilkret</person></lost></musicScore>
<musicSong year="1936">
<won>
<title>The Way You Look Tonight</title>
<movie>Swing Time</movie>
<person>Dorothy Fields</person>
<person>Jerome Kern</person></won></musicSong>
<musicSong year="1936">
<lost>
<title>A Melody from the Sky</title>
<movie>Trail of the Lonesome Pine</movie>
<person>Louis Alter</person>
<person>Sidney Mitchell</person></lost></musicSong>
<musicSong year="1936">
<lost>
<title>Did I Remember</title>
<movie>Suzy</movie>
<person>Harold Adamson</person>
<person>Walter Donaldson</person></lost></musicSong>
<musicSong year="1936">
<lost>
<title>I've Got You Under My Skin</title>
<movie>Born To Dance</movie>
<person>Cole Porter</person></lost></musicSong>
<musicSong year="1936">
<lost>
<title>Pennies from Heaven</title>
<movie>Pennies from Heaven</movie>
<person>Johnny Burke</person>
<person>Arthur Johnston</person></lost></musicSong>
<musicSong year="1936">
<lost>
<title>When Did You Leave Heaven</title>
<movie>Sing, Baby, Sing</movie>
<person>Walter Bullock</person>
<person>Richard A. Whiting</person></lost></musicSong>
<shortAnimation year="1936">
<won>
<movie>The Country Cousin</movie>
<person>Walt Disney</person></won></shortAnimation>
<shortAnimation year="1936">
<lost>
<movie>Old Mill Pond</movie>
<person>Harman-Ising</person></lost></shortAnimation>
<shortAnimation year="1936">
<lost>
<movie>Sinbad the Sailor</movie>
<org>Paramount</org></lost></shortAnimation>
<shortLiveAction year="1936" subcat="one reel">
<won>
<movie>Bored of Education</movie>
<person>Hal Roach</person></won></shortLiveAction>
<shortLiveAction year="1936" subcat="one reel">
<lost>
<movie>Moscow Moods</movie>
<org>Paramount</org></lost></shortLiveAction>
<shortLiveAction year="1936" subcat="one reel">
<lost>
<movie>Wanted, a Master</movie>
<person>Pete Smith</person></lost></shortLiveAction>
<shortLiveAction year="1936" subcat="two reel">
<won>
<movie>The Public Pays</movie>
<org>Metro-Goldwyn-Mayer</org></won></shortLiveAction>
<shortLiveAction year="1936" subcat="two reel">
<lost>
<movie>Double Or Nothing</movie>
<org>Warner Bros.</org></lost></shortLiveAction>
<shortLiveAction year="1936" subcat="two reel">
<lost>
<movie>Dummy Ache</movie>
<org>RKO Radio</org></lost></shortLiveAction>
<shortLiveAction year="1936" subcat="color">
<won>
<movie>Give Me Liberty</movie>
<org>Warner Bros.</org></won></shortLiveAction>
<shortLiveAction year="1936" subcat="color">
<lost>
<movie>La Fiesta De Santa Barbara</movie>
<person>Lewis Lewyn</person></lost></shortLiveAction>
<shortLiveAction year="1936" subcat="color">
<lost>
<movie>Popular Science J-6-2</movie>
<org>Paramount</org></lost></shortLiveAction>
<sound year="1936">
<won>
<movie>San Francisco</movie>
<org>Metro-Goldwyn-Mayer Studio Sound Department</org>
<person>Douglas Shearer</person></won></sound>
<sound year="1936">
<lost>
<movie>Banjo on My Knee</movie>
<org>20th Century-Fox Studio Sound Department</org>
<person>E. H. Hansen</person></lost></sound>
<sound year="1936">
<lost>
<movie>The Charge of the Light Brigade</movie>
<org>Warner Bros. Studio Sound Department</org>
<person>Nathan Levinson</person></lost></sound>
<sound year="1936">
<lost>
<movie>Dodsworth</movie>
<org>United Artists Studio Sound Department</org>
<person>Thomas T. Moulton</person></lost></sound>
<sound year="1936">
<lost>
<movie>General Spanky</movie>
<org>Hal Roach Studio Sound Department</org>
<person>Elmer A. Raguse</person></lost></sound>
<sound year="1936">
<lost>
<movie>Mr. Deeds Goes to Town</movie>
<org>Columbia Studio Sound Department</org>
<person>John Livadary</person></lost></sound>
<sound year="1936">
<lost>
<movie>The Texas Rangers</movie>
<org>Paramount Studio Sound Department</org>
<person>Franklin B. Hansen</person></lost></sound>
<sound year="1936">
<lost>
<movie>That Girl from Paris</movie>
<org>Paramount Studio Sound Department</org>
<person>J. O. Aalberg</person></lost></sound>
<sound year="1936">
<lost>
<movie>Three Smart Girls</movie>
<org>Universal Studio Sound Department</org>
<person>Homer G. Tasker</person></lost></sound>
<writing year="1936" subcat="original story">
<won>
<movie>The Story of Louis Pasteur</movie>
<person>Pierre Collings</person>
<person>Sheridan Gibney</person></won></writing>
<writing year="1936" subcat="original story">
<lost>
<movie>Fury</movie>
<person>Norman Krasna</person></lost></writing>
<writing year="1936" subcat="original story">
<lost>
<movie>The Great Ziegfeld</movie>
<person>William Anthony McGuire</person></lost></writing>
<writing year="1936" subcat="original story">
<lost>
<movie>San Francisco</movie>
<person>Robert Hopkins</person></lost></writing>
<writing year="1936" subcat="original story">
<lost>
<movie>Three Smart Girls</movie>
<person>Adele Comandini</person></lost></writing>
<writing year="1936" subcat="screenplay">
<won>
<movie>The Story of Louis Pasteur</movie>
<person>Pierre Collings</person>
<person>Sheridan Gibney</person></won></writing>
<writing year="1936" subcat="screenplay">
<lost>
<movie>After the Thin Man</movie>
<person>Frances Goodrich</person>
<person>Albert Hackett</person></lost></writing>
<writing year="1936" subcat="screenplay">
<lost>
<movie>Dodsworth</movie>
<person>Sidney Howard</person></lost></writing>
<writing year="1936" subcat="screenplay">
<lost>
<movie>Mr. Deeds Goes to Town</movie>
<person>Robert Riskin</person></lost></writing>
<writing year="1936" subcat="screenplay">
<lost>
<movie>My Man Godfrey</movie>
<person>Eric Hatch</person>
<person>Morris Ryskind</person></lost></writing>
</oscars>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8199910.java Fri Mar 23 18:44:47 2018 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8199910
+ * @summary Compile variables of intersection type inferred by `var` with -g option
+ * @compile -g T8199910.java
+ */
+import java.util.List;
+
+class T8199910 {
+ <T> T first(T... ts) {
+ return ts[0];
+ }
+
+ void m() {
+ var list1 = List.of("", 1);
+ var list2 = List.of(1, 2.0);
+ var a = first("", 1);
+ var b = first(1, 2.0);
+ }
+}
--- a/test/langtools/tools/javac/lvti/harness/LocalVariableInferenceTester.java Fri Mar 23 18:01:52 2018 +0000
+++ b/test/langtools/tools/javac/lvti/harness/LocalVariableInferenceTester.java Fri Mar 23 18:44:47 2018 +0000
@@ -80,12 +80,16 @@
void compileAndCheck(JavaFileObject input) throws IOException {
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
- JavacTask task = (JavacTask) c.getTask(null, fm, null, null, null, Arrays.asList(input));
+ JavacTask task = (JavacTask) c.getTask(null, fm, null, Arrays.asList("-g"), null, Arrays.asList(input));
JavacTrees trees = JavacTrees.instance(task);
Types types = Types.instance(((JavacTaskImpl)task).getContext());
Iterable<? extends CompilationUnitTree> roots = task.parse();
- task.analyze(); //force attribution
Log log = Log.instance(((JavacTaskImpl)task).getContext());
+ //force code generation (to shake out non-denotable issues)
+ boolean hasClasses = task.generate().iterator().hasNext();
+ if (!hasClasses) {
+ throw new AssertionError("Errors occurred during compilation!");
+ }
errors += log.nerrors;
new LocalVarTypeChecker(trees, types).scan(roots, null);
System.err.println("Checks executed: " + checks);