<Sound Dev> JDK6 doesn't see the "default" ALSA device, preventing sound card sharing with other applications?
Damjan Jovanovic
damjan.jov at gmail.com
Mon May 30 02:30:53 PDT 2011
Hi
On Linux, JDK6 doesn't show/use the "default" ALSA device. By
comparison, this device is shown and used by OpenJDK. The "default"
device is the only device capable of properly sharing access to the
sound card with other native applications, so it's pretty vital.
My investigation is detailed below:
Sound card:
00:1b.0 Audio device: Intel Corporation 82801I (ICH9 Family) HD Audio
Controller (rev 03)
JDK = JDK 1.6.0_22 on x86 Linux
OpenJDK = OpenJDK7 19.0-b06 on same x86 Linux
JDK's /META-INF/services/javax.sound.sampled.spi.MixerProvider:
com.sun.media.sound.PortMixerProvider
com.sun.media.sound.SimpleInputDeviceProvider
com.sun.media.sound.HeadspaceMixerProvider
com.sun.media.sound.DirectAudioDeviceProvider
OpenJDK's /META-INF/services/javax.sound.sampled.spi.MixerProvider:
com.sun.media.sound.PortMixerProvider
com.sun.media.sound.DirectAudioDeviceProvider
JDK's mixer list:
"Intel [plughw:0,0], version 1.0.21"
"Intel [plughw:0,3], version 1.0.21"
"Java Sound Audio Engine, version 1.0"
"Port Intel [hw:0], version 1.0.21"
OpenJDK's mixer list:
"default [default], version 1.0.21"
"Intel [plughw:0,0], version 1.0.21"
"Intel [plughw:0,3], version 1.0.21"
"Port Intel [hw:0], version 1.0.21"
Here we have 5 distinct mixers, 3 of which are common to both JDK and
OpenJDK. Now testing them with the following conditions:
* audio format is "AudioFormat audioFormat = new
AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 8000, 16, 1, 2, 8000,
true);"
* 3 cases are tested: pasuspender is used to bypass PulseAudio,
PulseAudio is active with no other sound playing, and PulseAudio
active with VLC playing sound through its PulseAudio output module
during the test
* AudioSystem.getSourceDataLine(audioFormat, mixerInfo) is tested, and
if that succeeds, open(audioFormat, 2*8*60*3) on that sourceDataLine
is tested
The following results are obtained for each mixer:
"default [default]" (description: Direct Audio Device: default,
default, default)
Only available in OpenJDK
OpenJDK + pasuspender: AudioSystem.getSourceDataLine() succeeds, open() succeeds
OpenJDK + no other sound: AudioSystem.getSourceDataLine() succeeds,
open() succeeds
OpenJDK + VLC playing sound: AudioSystem.getSourceDataLine() succeeds,
open() succeeds
In other words, this mixer works perfectly.
"Intel [plughw:0,0], version 1.0.21" (description: Direct Audio
Device: HDA Intel, AD198x Analog, AD198x Analog)
JDK + pasuspender: AudioSystem.getSourceDataLine() succeeds, open() succeeds
OpenJDK + pasuspender: AudioSystem.getSourceDataLine() succeeds, open() succeeds
JDK + no other sound: AudioSystem.getSourceDataLine() succeeds, open() succeeds
OpenJDK + no other sound: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
JDK + VLC playing sound: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
OpenJDK + VLC playing sound: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
"Intel [plughw:0,3], version 1.0.21" (description: Direct Audio
Device: HDA Intel, INTEL HDMI, INTEL HDMI)
JDK + pasuspender: AudioSystem.getSourceDataLine() succeeds, open() succeeds
OpenJDK + pasuspender: AudioSystem.getSourceDataLine() succeeds, open() succeeds
JDK + no other sound: AudioSystem.getSourceDataLine() succeeds, open() succeeds
OpenJDK + no other sound: AudioSystem.getSourceDataLine() succeeds,
open() succeeds
JDK + VLC playing sound: AudioSystem.getSourceDataLine() succeeds,
open() succeeds
OpenJDK + VLC playing sound: AudioSystem.getSourceDataLine() succeeds,
open() succeeds
"Java Sound Audio Engine, version 1.0" (description: Software mixer
and synthesizer)
Only available in JDK
JDK + pasuspender: AudioSystem.getSourceDataLine() succeeds, open() succeeds
JDK + no other sound: AudioSystem.getSourceDataLine() succeeds, open() succeeds
JDK + VLC playing sound: AudioSystem.getSourceDataLine() succeeds, open() throws
"javax.sound.sampled.LineUnavailableException: Audio Device Unavailable"
"Port Intel [hw:0], version 1.0.21" (description: HDA Intel, Intel G45 DEVCTG)
JDK + pasuspender: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
OpenJDK + pasuspender: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
JDK + no other sound: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
OpenJDK + no other sound: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
JDK + VLC playing sound: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
OpenJDK + VLC playing sound: AudioSystem.getSourceDataLine() throws
"java.lang.IllegalArgumentException: Line unsupported: ..."
Also, while VLC is playing audio:
* In JDK, AudioSystem.getSourceDataLine(audioFormat) succeeds, but
open() throws an exception
* In OpenJDK, AudioSystem.getSourceDataLine(audioFormat) succeeds, and
open() succeeds
The above carnage amounts to:
* In JDK, sound is completely unusable with any other application playing sound
* In OpenJDK, at least one SourceDataLine - the default one called
"default [default]" - works well even with other applications playing
sound
The lack of the "default" device in JDK6 is strange, since
jdk/src/solaris/native/com/sun/media/sound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.c
seems to have had it since the initial import in revision
0c738a3e5791.
$ strings openjdk7/build/linux-i586/j2sdk-image/jre/lib/i386/libjsoundalsa.so
| grep default
default
$ strings jdk6/jre/lib/i386/libjsoundalsa.so | grep default
(nothing)
So it looks like there's some vital patch that adds support for the
"default" ALSA device that hasn't been applied to JDK6.
My tests on jre-7-ea-bin-b144-linux-i586-26_may_2011.tar.gz from
http://jdk7.java.net show that it does see the "default" device, but
even the latest jdk1.6.0_25 doesn't see it, so this bug seems specific
to JDK6/JRE6.
So please can you add the "default" device to JDK6?
Thank you
Damjan Jovanovic
P.S. Out of interest, why is the "default" device necessary? Java
opens most ALSA devices with the "plughw:" prefix, which is "plug"
(ALSA does sample conversions in user-space) and "hw" together (direct
hardware access, locking out other applications unless the sound card
supports hardware mixing). The "default" device is special-cased, and
opened without a "plughw:" prefix. In addition, with PulseAudio
installed, most Linux distributions make the "default" device go
through PulseAudio, which does high quality resampling and mixing, and
allows multiple applications to share access to sound hardware.
More information about the sound-dev
mailing list