Index: modules/tools/src/main/java/org/apache/harmony/tools/appletviewer/ViewerAudioClip.java =================================================================== --- modules/tools/src/main/java/org/apache/harmony/tools/appletviewer/ViewerAudioClip.java (revision 616752) +++ modules/tools/src/main/java/org/apache/harmony/tools/appletviewer/ViewerAudioClip.java (working copy) @@ -20,61 +20,191 @@ import java.applet.AudioClip; import java.net.URL; -import javax.sound.midi.MidiSystem; -import javax.sound.midi.Receiver; -import javax.sound.midi.Sequence; -import javax.sound.midi.Sequencer; -import javax.sound.midi.Synthesizer; -import javax.sound.midi.Transmitter; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.SourceDataLine; class ViewerAudioClip implements AudioClip { - //private Clip clip; - private Sequencer sequencer; - + + private ClipImpl clip; + public ViewerAudioClip(URL url) { + AudioFormat af = null; + AudioInputStream ais = null; + SourceDataLine line = null; try { - sequencer = MidiSystem.getSequencer(); - sequencer.open(); - - Sequence sequence = MidiSystem.getSequence(url); - sequencer.setSequence(sequence); - - if (!(sequencer instanceof Synthesizer)) { - Synthesizer synthesizer = MidiSystem.getSynthesizer(); - synthesizer.open(); - Receiver receiver = synthesizer.getReceiver(); - Transmitter transmitter = sequencer.getTransmitter(); - transmitter.setReceiver(receiver); - } + ais = AudioSystem.getAudioInputStream(url); } catch (Exception e) { - sequencer = null; + System.out.println(url.toString()); + e.printStackTrace(); + ais = null; + return; } -// try { -// this.clip = AudioSystem.getClip(); -// clip.open(AudioSystem.getAudioInputStream(url)); -// } catch (Exception e) { -// this.clip = null; -// } + af = ais.getFormat(); + DataLine.Info info = new DataLine.Info(SourceDataLine.class, af); + + boolean isSupported = AudioSystem.isLineSupported(info); + if (!isSupported){ + AudioFormat tf = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + af.getSampleRate(), + 16, + af.getChannels(), + af.getChannels() << 1, + af.getSampleRate(), + false); + ais = AudioSystem.getAudioInputStream(tf, ais); + af = ais.getFormat(); + info = new DataLine.Info(SourceDataLine.class, af); + } + try{ + line = (SourceDataLine) AudioSystem.getLine(info); + }catch (Exception e){ + e.printStackTrace(); + } + + clip = new ClipImpl(af, ais, line); + } public void loop() { - if (sequencer != null) - sequencer.start(); -// if (clip != null) -// clip.loop(Clip.LOOP_CONTINUOUSLY); + if(clip != null) + clip.loop(); } public void play() { - if (sequencer != null) - sequencer.start(); -// if (clip != null) -// clip.start(); + if(clip != null) + clip.play(); } public void stop() { - if (sequencer != null) - sequencer.stop(); -// if (clip != null) -// clip.stop(); + if(clip != null) + clip.stop(); } + + private static class ClipImpl implements AudioClip, Runnable { + + static final int BufferSize = 1024; + static final int UNLIMITED = -1; + + AudioFormat af; + AudioInputStream ais; + SourceDataLine line; + Thread clip; + boolean started; + int streamLength; + int count; + + ClipImpl(AudioFormat af, AudioInputStream ais, SourceDataLine line){ + this.af = af; + this.ais = ais; + this.line = line; + + if(ais.getFrameLength() == AudioSystem.NOT_SPECIFIED || + af.getFrameSize() == AudioSystem.NOT_SPECIFIED){ + + streamLength = -1; + } + + long length = ais.getFrameLength() * af.getFrameSize(); + + if(length > Integer.MAX_VALUE){ + streamLength = -1; + } + + streamLength = (int)length; + clip = new Thread(this); + } + + public void run(){ + if(streamLength < 0) return; + + started = true; + + int bytesRead = 0; + byte[] data = new byte[BufferSize]; + + try{ + line.open(af); + }catch (Exception e){ + e.printStackTrace(); + } + + // Main cycle + + while(true){ + + line.start(); + + do{ + + ais.mark(streamLength); + bytesRead = 0; + while (bytesRead != -1){ + try{ + bytesRead = ais.read(data, 0, data.length); + }catch (Exception e){ + e.printStackTrace(); + } + + if (bytesRead >= 0){ + line.write(data, 0, bytesRead); + } + } + + try{ + ais.reset(); + }catch (Exception e){ + e.printStackTrace(); + } + }while(count < 0 || --count > 0); + + synchronized(clip){ + try{ + clip.wait(); + }catch (Exception e){ + e.printStackTrace(); + } + } + + } + } + + public void play(){ + if(!started) clip.start(); + synchronized(this){ + count = 1; + synchronized(clip){ + clip.notify(); + } + } + } + + public void loop(){ + if(!started) clip.start(); + synchronized(this){ + count = UNLIMITED; + synchronized(clip){ + clip.notify(); + } + } + } + + public void stop(){ + synchronized(this){ + line.stop(); + count = 1; + } + } + + protected void finalize(){ + if(line != null && line.isOpen()){ + line.drain(); + line.close(); + } + } + + } }