Java audio Clip cannot be closed when using Linux PulseAudio

送分小仙女□ 提交于 2019-12-06 08:22:36

问题


I'm trying to play a sound in a Java application but the application never actually terminates because the PulseAudio Eventloop thread is left running even after trying to close the Clip instance used for playing the sound:

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

final class AudioClipTest {

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException {
        try (AudioInputStream instream = AudioSystem.getAudioInputStream(new File("resources/test-sound.wav"))){
            final AudioFormat format = instream.getFormat();
            final Clip clip = (Clip) AudioSystem.getLine(new DataLine.Info(Clip.class, format));
            clip.addLineListener(new LineListener() {
                @Override
                public void update(final LineEvent event) {
                    if (event.getType() == LineEvent.Type.STOP) {
                        System.out.println("Finished playing audio.");
                        event.getLine().close();
                        // FIXME: This line is never reached on Linux with
                        // PulseAudio
                        System.out.println("Closed audio data line.");
                    }
                }
            });
            clip.open(instream);
            clip.start();
        }
    }

}

On my Linux machine, the above main method plays the relevant sound, prints

Finished playing audio.

and then hangs, while on a Windows‡ machine it prints

Finished playing audio.

Closed audio data line.

and exits properly.

The actual Clip implementation used on the Linux machine is org.classpath.icedtea.pulseaudio.PulseAudioClip whereas on Windows it is com.sun.media.sound.DirectAudioDevice.DirectClip; What is going on here? — What is PulseAudioClip.close() doing which isn't returning?


Distribution: Linux Mint 18.1; Kernel: 4.4.0-92-generic x86_64; OpenJDK: 8u131-b11-2ubuntu1.16.04.3; PulseAudio: 1:8.0-ubuntu3.3

‡Distribution: Windows 10 Pro; Version: 1703; OS Build: 15063.540 x64; Oracle JDK: 1.8.0_144-b01; DirectX: version 12


回答1:


One possible way to work around this issue is to use the Alsa (userspace) API for playing audio using Java. The alsa userspace API will redirect to PulseAudio (or another API/mixer) so you should still get correct audio.

Edit $JAVA_HOME/jre/lib/sound.properties and comment out everything related to org.classpath.icedtea.pulseaudio and add this:

javax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider
javax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider

Also, please file a bug against your distribution's openjdk package. The PulseAudio/Java bindings have been unsupported for years now and should be removed.



来源:https://stackoverflow.com/questions/45847635/java-audio-clip-cannot-be-closed-when-using-linux-pulseaudio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!