Description: TODO: Put a short summary on the line above and replace this paragraph with a longer explanation of this change. Complete the meta-information with other relevant fields (see below for details). To make it easier, the information below has been extracted from the changelog. Adjust it or drop it. . jclic (0.2.1.0-1) unstable; urgency=low . * New upstream version * Fixed bashism in jclic launcher (Closes: #581114) * Switch to dpkg-source 3.0 (quilt) format * debian/control: bumped standards version to 3.8.4 * debian/control: added quilt build dependency * fix detection of PulseAudio and remote DISPLAY, thanks again to Mario Izquierdo for his hints (Closes: #576465) Author: José L. Redrejo Rodríguez Bug-Debian: http://bugs.debian.org/576465 Bug-Debian: http://bugs.debian.org/581114 --- The information above should follow the Patch Tagging Guidelines, please checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here are templates for supplementary fields that you might want to add: Origin: , Bug: Bug-Debian: http://bugs.debian.org/ Bug-Ubuntu: https://launchpad.net/bugs/ Forwarded: Reviewed-By: Last-Update: --- jclic-0.2.1.0.orig/src/player/edu/xtec/jclic/SingleInstanceJFrame.java +++ jclic-0.2.1.0/src/player/edu/xtec/jclic/SingleInstanceJFrame.java @@ -96,6 +96,7 @@ public class SingleInstanceJFrame extend result=args[i]; } } + options.needViaHack(); return result; } --- jclic-0.2.1.0.orig/src/core/edu/xtec/jclic/media/JavaSoundAudioPlayer.java +++ jclic-0.2.1.0/src/core/edu/xtec/jclic/media/JavaSoundAudioPlayer.java @@ -22,6 +22,7 @@ package edu.xtec.jclic.media; import edu.xtec.jclic.bags.MediaBag; +import edu.xtec.util.ResourceManager; import edu.xtec.util.ExtendedByteArrayInputStream; import edu.xtec.util.StreamIO; import java.io.ByteArrayInputStream; @@ -33,11 +34,17 @@ import javax.sound.sampled.AudioInputStr import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.sound.sampled.DataLine; +import javax.sound.sampled.Line; +import javax.sound.sampled.LineListener; +import javax.sound.sampled.LineEvent; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; import javax.sound.sampled.UnsupportedAudioFileException; import org.tritonus.applet.AppletMpegSPIWorkaround; import org.tritonus.applet.AppletVorbisSPIWorkaround; +import edu.xtec.util.Options; + + /** * @@ -46,11 +53,16 @@ import org.tritonus.applet.AppletVorbisS public class JavaSoundAudioPlayer implements AudioPlayer{ private Clip clip; - protected AudioInputStream ais; + + protected AudioInputStream ais = null; protected boolean isMpeg; protected boolean isOgg; protected boolean isWav; - + private MediaBag mb; + private String mediaFileName; + private Options options; + private PlayThread playThread; + static final int INTERNAL_BUFFER_SIZE=1024; static final int CHECK_BUFFER_SIZE=0x60; static final int BIT_SAMPLE_SIZE=16; @@ -61,20 +73,27 @@ public class JavaSoundAudioPlayer implem } public boolean setDataSource(Object source) throws Exception{ - + this.options = options; close(); + //System.out.println("JavaSoundAudioPlayer: setDataSource " + source ); InputStream is=null; javax.sound.sampled.AudioFileFormat m_audioFileFormat=null; if(source instanceof ExtendedByteArrayInputStream){ + this.mediaFileName=((ExtendedByteArrayInputStream)source).getName(); is=checkInputStream((InputStream)source, ((ExtendedByteArrayInputStream)source).getName()); + //System.out.println("JavaSoundAudioPlayer: setDataSource " + this.mediaFileName ); } else if(source instanceof InputStream){ - is=checkInputStream((InputStream)source, null); + this.mediaFileName=null; + is=checkInputStream((InputStream)source, this.mediaFileName); + //System.out.println("JavaSoundAudioPlayer: setDataSource " + this.mediaFileName ); } else if(source instanceof File){ + this.mediaFileName=((File)source).getName(); is=checkInputStream(new java.io.FileInputStream((File)source), ((File)source).getName()); + //System.out.println("JavaSoundAudioPlayer: setDataSource " + this.mediaFileName ); } else{ java.net.URL url=null; @@ -84,7 +103,9 @@ public class JavaSoundAudioPlayer implem url=new java.net.URL((String)source); } if(url!=null){ + this.mediaFileName=source.toString(); is=checkInputStream(url.openStream(), source.toString()); + //System.out.println("JavaSoundAudioPlayer: setDataSource " + this.mediaFileName ); } } @@ -146,45 +167,130 @@ public class JavaSoundAudioPlayer implem } return ais!=null; } + + private void getAudioInputStream() throws Exception{ + if(ais==null){ + //System.out.println("getAudioInputStream: " + mediaFileName + " mb " + mb); + JavaSoundAudioPlayer jsap=new JavaSoundAudioPlayer(); + jsap.setDataSource(ResourceManager.getResourceAsByteArray(mediaFileName)); + ais=jsap.ais; + if(ais==null) + throw new Exception("Unable to open audio data!"); + } + + } public Clip getClip() throws Exception{ - if(clip==null && ais!=null){ - clip = (Clip)AudioSystem.getLine(new DataLine.Info(Clip.class, ais.getFormat(), INTERNAL_BUFFER_SIZE)); - } - return clip; + if (!Options.CLOSE_STREAMS.booleanValue()) { + if(clip==null && ais!=null){ + clip = (Clip)AudioSystem.getLine(new DataLine.Info(Clip.class, ais.getFormat(), INTERNAL_BUFFER_SIZE)); + } + return clip; + } else { + //System.out.println("getClip() with closestreams " + Options.CLOSE_STREAMS.booleanValue()); + if (ais !=null) close(); + if (ais == null) getAudioInputStream(); + else return null; + + DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat(), INTERNAL_BUFFER_SIZE); + if((clip==null && ais!=null)){ + clip = (Clip)AudioSystem.getLine(info); + clip.addLineListener(new LineListener(){ + public void update(LineEvent event){ + //System.out.println("LineListener " + event.getType() ); + + if(event.getType() == LineEvent.Type.CLOSE){ + } + if(event.getType() == LineEvent.Type.STOP){ + clip.stop(); + close(); + } + if(event.getType() == LineEvent.Type.OPEN){ + if(clip!=null && clip.isRunning()) { + clip.stop(); + } + } + } + }); + return clip; + } + } + return null; } public void realize(String fileName, MediaBag mediaBag) throws Exception{ - if(fileName!=null) + if(fileName!=null) { setDataSource(mediaBag.getMediaDataSource(fileName)); - if(ais!=null && getClip()!=null){ - clip.open(ais); - } + this.mediaFileName=fileName; + } + this.mb=mediaBag; + if (!Options.CLOSE_STREAMS.booleanValue()) { + if(ais!=null && getClip()!=null){ + clip.open(ais); + } + } } public void close(){ - if(clip!=null){ - clip.close(); - clip=null; - } - ais=null; + if (!Options.CLOSE_STREAMS.booleanValue()) { + if(clip!=null){ + clip.close(); + clip=null; + } + ais=null; + } else { + try { + if(clip!=null){ + //System.out.println("close() clip"); + clip.close(); + clip=null; + } + if(ais!=null){ + //System.out.println("close() ais"); + ais.close(); + ais=null; + } + } catch(java.io.IOException ex){ + System.err.println("close(): close error"); + } + } } public void play(){ try{ - stop(); - if(getClip()!=null){ - clip.setFramePosition(0); - clip.start(); - } + if (!Options.CLOSE_STREAMS.booleanValue()) { + stop(); + if(getClip()!=null){ + clip.setFramePosition(0); + clip.start(); + } + } else { + if(playThread==null){ + playThread=new PlayThread(); + playThread.start(); + } + } } catch(Exception ex){ System.err.println("Error playing sound:\n"+ex); } } public void stop(){ - if(clip!=null && clip.isActive()) - clip.stop(); + if (!Options.CLOSE_STREAMS.booleanValue()) { + if(clip!=null && clip.isActive()) + clip.stop(); + } else { + if(playThread!=null){ + if(playThread.isAlive()){ + playThread.running=false; + while(playThread!=null){ + Thread.currentThread().yield(); + } + } else{ + playThread=null; + } + } + } } protected InputStream checkInputStream(InputStream is, String name) throws Exception{ @@ -225,5 +331,79 @@ public class JavaSoundAudioPlayer implem } } return is; - } + } + + class PlayThread extends Thread { + + public boolean running; + private Clip clip2 = null; + + public PlayThread() throws Exception{ + //System.out.println("PlayThread() with closestreams " + Options.CLOSE_STREAMS.booleanValue()); + if (ais !=null) close(); + if (ais == null) getAudioInputStream(); + + DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat(), INTERNAL_BUFFER_SIZE); + if((clip2==null && ais!=null)){ + clip2 = (Clip)AudioSystem.getLine(info); + clip2.addLineListener(new LineListener(){ + public void update(LineEvent event){ + //System.out.println("LineListener " +event.getType() ); + + if(event.getType() == LineEvent.Type.CLOSE){ + } + if(event.getType() == LineEvent.Type.STOP){ + clip2.stop(); + close2(); + playThread=null; + running=false; + } + if(event.getType() == LineEvent.Type.OPEN){ + if(clip2!=null && clip2.isRunning()) { + clip2.stop(); + } + } + } + }); + } + } + + public void close2(){ + try { + if(clip2!=null){ + //System.out.println("close2() clip"); + clip2.close(); + clip2=null; + } + if(ais!=null){ + //System.out.println("close2() ais"); + ais.close(); + ais=null; + } + } catch(java.io.IOException ex){ + System.err.println("close2(): close error"); + } + } + + public void run(){ + try{ + if(clip2!=null) { + running=true; + clip2.stop(); + + if (!clip2.isOpen()) { + if(ais!=null){ + clip2.open(ais); + } + } + clip2.setFramePosition(0); + clip2.start(); + Thread.currentThread().yield(); + } + } catch(Exception ex){ + System.err.println("Error playing sound:\n"+ex); + } + } + } + } --- jclic-0.2.1.0.orig/src/core/edu/xtec/jclic/media/JavaSoundAudioBuffer.java +++ jclic-0.2.1.0/src/core/edu/xtec/jclic/media/JavaSoundAudioBuffer.java @@ -32,6 +32,8 @@ import java.util.Timer; import java.util.TimerTask; import java.util.Vector; +import edu.xtec.util.Options; + /** * This class extends {@link AudioBuffer} using the javax.sound.sampled package. * @author Francesc Busquets (fbusquets@xtec.net) @@ -171,7 +173,12 @@ public class JavaSoundAudioBuffer extend // build m_sourceLine dli=new javax.sound.sampled.DataLine.Info(SourceDataLine.class, m_targetLine.getFormat()); - m_sourceLine=(SourceDataLine)AudioSystem.getLine(dli); + if (Options.CLOSE_STREAMS.booleanValue()) { + //System.out.println("JavaSoundAudioBuffer: Default mixer " + (SourceDataLine)AudioSystem.getSourceDataLine(m_targetLine.getFormat(), AudioSystem.getMixer(null).getMixerInfo())); + m_sourceLine=(SourceDataLine)AudioSystem.getSourceDataLine(m_targetLine.getFormat(), AudioSystem.getMixer(null).getMixerInfo()); + } else { + m_sourceLine=(SourceDataLine)AudioSystem.getLine(dli); + } m_sourceLine.open(); initialized=true; } @@ -269,6 +276,7 @@ public class JavaSoundAudioBuffer extend public void run(){ running=true; try{ + //System.out.println("JavaSoundAudioBuffer: playing dataline"); m_sourceLine.start(); int l=m_sourceLine.getBufferSize()/2; int p=0; @@ -279,12 +287,13 @@ public class JavaSoundAudioBuffer extend remainingData-=k; Thread.currentThread().yield(); } + //System.out.println("JavaSoundAudioBuffer: end dataline"); } catch(Exception ex){ System.err.println("JavaSound playing error:\n"+ex); } m_sourceLine.drain(); m_sourceLine.stop(); - //m_sourceLine.close(); + if (Options.CLOSE_STREAMS.booleanValue()) m_sourceLine.close(); playThread=null; running=false; } --- jclic-0.2.1.0.orig/src/core/edu/xtec/jclic/media/JavaSoundActiveMediaPlayer.java +++ jclic-0.2.1.0/src/core/edu/xtec/jclic/media/JavaSoundActiveMediaPlayer.java @@ -32,6 +32,7 @@ import javax.sound.midi.MidiSystem; import javax.sound.sampled.*; import javax.sound.sampled.UnsupportedAudioFileException; import javax.swing.Timer; +import edu.xtec.util.Options; /** * @@ -112,9 +113,12 @@ public class JavaSoundActiveMediaPlayer sequencer=MidiSystem.getSequencer(); } else{ - if(clip!=null && !clip.isOpen()){ - clip.open(); - } + if (!Options.CLOSE_STREAMS.booleanValue()) { + //System.out.println("JavaSoundActiveMediaPlayer: Playing wav"); + if(clip!=null && !clip.isOpen()){ + clip.open(); + } + } } } catch(Exception e){ System.err.println("Error realizing media \""+mc.mediaFileName+"\"\n"+e); @@ -136,20 +140,31 @@ public class JavaSoundActiveMediaPlayer if(!sequencer.isOpen()) sequencer.open(); midiIs.reset(); + //System.out.println("JavaSoundActiveMediaPlayer: Playing midi"); sequencer.setSequence(midiIs); sequencer.stop(); setTimeRanges(); sequencer.start(); } } else if(clip!=null){ - if(!clip.isOpen()) - realize(); + if (Options.CLOSE_STREAMS.booleanValue()) { + //System.out.println("JavaSoundActiveMediaPlayer: open clip"); + clip.stop(); + if(clip!=null) { + if(!clip.isOpen()) + clip.open(); + } + } else { + if(!clip.isOpen()) + realize(); + } setTimeRanges(); attachVisualComponent(); if(mc.loop){ clip.loop(Clip.LOOP_CONTINUOUSLY); } else{ + //System.out.println("JavaSoundActiveMediaPlayer: clip playnow"); clip.start(); if(timer!=null) timer.start(); --- jclic-0.2.1.0.orig/src/core/edu/xtec/jclic/media/FalseClip.java +++ jclic-0.2.1.0/src/core/edu/xtec/jclic/media/FalseClip.java @@ -28,6 +28,9 @@ import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.SourceDataLine; +import edu.xtec.util.Options; + + /** * * @author Francesc Busquets (fbusquets@xtec.net) @@ -54,6 +57,7 @@ public class FalseClip implements Pseudo private AudioInputStream getAudioInputStream() throws Exception{ if(ais==null){ + //System.out.println("FalseClip: creating clip " + mediaFileName); JavaSoundAudioPlayer jsap=new JavaSoundAudioPlayer(); jsap.setDataSource(mb.getMediaDataSource(mediaFileName)); ais=jsap.ais; @@ -133,9 +137,12 @@ public class FalseClip implements Pseudo running=false; getAudioInputStream(); DataLine.Info info = new DataLine.Info(SourceDataLine.class, af); - line = (SourceDataLine)AudioSystem.getLine(info); + //System.out.println("FalseClip: Default mixer " + (SourceDataLine)AudioSystem.getSourceDataLine(af, AudioSystem.getMixer(null).getMixerInfo())); + if (Options.CLOSE_STREAMS.booleanValue()) line = (SourceDataLine)AudioSystem.getSourceDataLine(af, AudioSystem.getMixer(null).getMixerInfo()); + else line = (SourceDataLine)AudioSystem.getLine(info); + if(line!=null) - line.open(af); + if (!Options.CLOSE_STREAMS.booleanValue()) line.open(af); } public void run(){ @@ -143,6 +150,7 @@ public class FalseClip implements Pseudo running=true; int nBytesRead = 0; try{ + if (Options.CLOSE_STREAMS.booleanValue()) line.open(af); line.start(); while (running && nBytesRead >=0) { nBytesRead = ais.read(buf, 0, buf.length); @@ -155,6 +163,9 @@ public class FalseClip implements Pseudo line.drain(); else line.stop(); + } catch(javax.sound.sampled.LineUnavailableException ex){ + System.err.println("JavaSound playing error:\n"+ex); + } catch(Exception ex){ System.err.println("JavaSound playing error:\n"+ex); } --- jclic-0.2.1.0.orig/src/core/edu/xtec/jclic/media/JMFActiveMediaPlayer.java +++ jclic-0.2.1.0/src/core/edu/xtec/jclic/media/JMFActiveMediaPlayer.java @@ -31,7 +31,9 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import javax.sound.midi.MidiSystem; import javax.sound.midi.Sequencer; - +//import javax.sound.midi.MidiDevice; +//import javax.sound.midi.Synthesizer; +//import edu.xtec.util.Options; /** * * @author Francesc Busquets (fbusquets@xtec.net) @@ -98,8 +100,29 @@ public class JMFActiveMediaPlayer extend if(!useAudioBuffer){ try{ if(midi){ - if(sequencer==null) - sequencer=MidiSystem.getSequencer(); + if(sequencer==null) { + /*ClassLoader.getSystemClassLoader().loadClass("com.sun.media.sound.RealTimeSequencer"); + MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); + if (devices.length == 0) { + System.out.println("No MIDI devices found"); + } else { + MidiDevice device; + for (MidiDevice.Info dev : devices) { + device = MidiSystem.getMidiDevice(dev); + if (device instanceof Sequencer) { + if (!(device.isOpen())) { + device.open(); + } + sequencer = (Sequencer) device; + //break; + } + //} else if (device instanceof Synthesizer) { + // Synthesizer synthesizer = (Synthesizer) device; + // synthesizer.open(); + //} + }*/ + sequencer=MidiSystem.getSequencer(); + } } else{ if(player==null && dataSource!=null){ @@ -128,6 +151,7 @@ public class JMFActiveMediaPlayer extend if(!sequencer.isOpen()) sequencer.open(); midiIs.reset(); + //System.out.println("JMFActiveMediaPlayer: playing midi"); sequencer.setSequence(midiIs); sequencer.stop(); setTimeRanges(); --- jclic-0.2.1.0.orig/src/utilities/edu/xtec/util/Messages.java +++ jclic-0.2.1.0/src/utilities/edu/xtec/util/Messages.java @@ -108,11 +108,17 @@ public class Messages { Messages msg=(Messages)options.get(MESSAGES); if(msg==null){ String language=(String)options.get(LANGUAGE); + //System.out.println("language getMessages: " + language); if(language==null){ JOptionPane pane=new JOptionPane("Please select your language:", JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION); //pane.setSelectionValues(DESCRIPTIVE_LANGUAGE_CODES); pane.setSelectionValues(getDescriptiveLanguageCodes(null)); pane.setWantsInput(true); + //String systemlanguage=Locale.getDefault().getLanguage(); + //System.out.println("System Language: " + systemlanguage); + //String selectedlang=(systemlanguage.equals("qc")) ? "qcv" : systemlanguage; + //System.out.println("Selected Language: " + systemlanguage); + //String initialSelection=getDescriptiveLanguageCode(selectedlang); String initialSelection=getDescriptiveLanguageCode(Locale.getDefault().getLanguage()); pane.setInitialSelectionValue(initialSelection); showDlg((Component)options.get(Options.MAIN_PARENT_COMPONENT), pane, "Language selecion"); @@ -134,6 +140,9 @@ public class Messages { public void init(String bundle, String language, String country, String variant) { setLocale(language, country, variant); + //System.out.println("language: " +language); + //System.out.println("country: " + country); + //System.out.println("variant: "+ variant); addBundle(bundle); addBundle(BASIC_BUNDLE); getDlgButtons(true); @@ -658,8 +667,10 @@ public class Messages { public static final HashMap ISO_639_2_CODES=new HashMap(); static{ ISO_639_2_CODES.put("ast","asturianu"); - } + ISO_639_2_CODES.put("qc","valencià"); + } + public static String getDescriptiveLanguageCode(String languageCode){ String result=null; if(languageCode!=null){ @@ -669,6 +680,7 @@ public class Messages { result=lx.getDisplayName(Locale.getDefault()); } result=result+" ("+languageCode+")"; + //System.out.println("Resultado language: " + result); } return result; } --- jclic-0.2.1.0.orig/src/utilities/edu/xtec/util/Options.java +++ jclic-0.2.1.0/src/utilities/edu/xtec/util/Options.java @@ -27,6 +27,8 @@ import java.awt.Component; import java.applet.Applet; import java.util.Iterator; import java.util.Properties; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Mixer; /** * @@ -34,7 +36,8 @@ import java.util.Properties; * @version 1.0 */ public class Options extends HashMap { - + public static Boolean CLOSE_STREAMS=null; + public static String CLOSESTREAMS="closestreams"; public static final String TRUE="true", FALSE="false"; public static final Boolean BTRUE=new Boolean(true), BFALSE=new Boolean(false); public static final String MAC="Mac", WIN="Windows", @@ -87,7 +90,25 @@ public class Options extends HashMap { put(ARCH64BIT, new Boolean(true)); } - + public void needViaHack(){ + if (CLOSE_STREAMS == null) { + if (containsKey(CLOSESTREAMS)) CLOSE_STREAMS=new Boolean(getBoolean(CLOSESTREAMS)); + else { + put(CLOSESTREAMS, "false"); + Mixer.Info[] mixers = AudioSystem.getMixerInfo(); + for(int i = 0; i < mixers.length; ++i) { + //System.out.println(mixers[i].getDescription()); + if (mixers[i].getDescription().indexOf("8237") > 0 || mixers[i].getDescription().indexOf("8235") > 0 || mixers[i].getDescription().indexOf("VT1708") > 0 || mixers[i].getDescription().indexOf("8233") > 0) { + put(CLOSESTREAMS, "true"); + break; + } + } + CLOSE_STREAMS=new Boolean(getBoolean(CLOSESTREAMS)); + } + } + //if (CLOSE_STREAMS.booleanValue()) System.out.println("Options: CLOSESTREAMS="+ CLOSE_STREAMS); + } + public Properties toProperties(){ Properties prop=new Properties(); Iterator it=keySet().iterator();