1 package tim.prune.function;
3 import java.io.BufferedOutputStream;
4 import java.io.ByteArrayInputStream;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.lang.reflect.InvocationTargetException;
10 import javax.sound.sampled.AudioInputStream;
11 import javax.sound.sampled.AudioSystem;
12 import javax.sound.sampled.Clip;
15 import tim.prune.GenericFunction;
16 import tim.prune.data.AudioClip;
19 * Class to play the current audio clip
21 public class PlayAudioFunction extends GenericFunction implements Runnable
23 /** Audio clip used for playing within java */
24 private Clip _clip = null;
29 * @param inApp app object
31 public PlayAudioFunction(App inApp) {
38 public String getNameKey() {
39 return "function.playaudio";
47 // Launch new thread if clip isn't currently playing
49 new Thread(this).start();
54 * Play the audio in a new thread
58 AudioClip audio = _app.getTrackInfo().getCurrentAudio();
59 File audioFile = audio.getFile();
60 boolean played = false;
61 if (audioFile != null && audioFile.exists() && audioFile.isFile() && audioFile.canRead())
63 // First choice is to play using java
64 played = playClip(audio);
65 // If this didn't work, then try to play the file another way
67 played = playAudioFile(audioFile);
70 else if (audioFile == null && audio.getByteData() != null)
72 // Try to play audio clip using byte array
73 played = playClip(audio);
74 // If this didn't work, then need to copy the byte data to a file and play it from there
79 String suffix = getSuffix(audio.getName());
80 File tempFile = File.createTempFile("gpsaudio", suffix);
81 tempFile.deleteOnExit();
82 // Copy byte data to this file
83 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile));
84 bos.write(audio.getByteData(), 0, audio.getByteData().length);
86 played = playAudioFile(tempFile);
88 catch (IOException ignore) {
89 System.err.println("Error: " + ignore.getClass().getName() + " - " + ignore.getMessage());
95 // If still not worked, show error message
96 _app.showErrorMessage(getNameKey(), "error.playaudiofailed");
101 * Try to play the sound file using built-in java libraries
102 * @param inAudio audio clip to play
103 * @return true if play was successful
105 private boolean playClip(AudioClip inClip)
107 boolean success = false;
108 AudioInputStream audioInputStream = null;
112 if (inClip.getFile() != null)
113 audioInputStream = AudioSystem.getAudioInputStream(inClip.getFile());
114 else if (inClip.getByteData() != null)
115 audioInputStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(inClip.getByteData()));
117 _clip = AudioSystem.getClip();
118 _clip.open(audioInputStream);
123 } catch (Exception e) {
124 System.err.println(e.getClass().getName() + " - " + e.getMessage());
126 // close the stream to clean up
129 audioInputStream.close();
130 } catch (Exception e) {}
137 * Try to play the specified audio file
138 * @param inFile file to play
139 * @return true if play was successful
141 private boolean playAudioFile(File inFile)
143 boolean played = false;
144 // Try the Desktop library from java 6, if available
149 Class<?> d = Class.forName("java.awt.Desktop");
150 d.getDeclaredMethod("open", new Class[] {File.class}).invoke(
151 d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {inFile});
152 //above code mimics: Desktop.getDesktop().open(audioFile);
155 catch (InvocationTargetException e) {
156 System.err.println("ITE: " + e.getCause().getClass().getName() + " - " + e.getCause().getMessage());
159 catch (Exception ignore) {
160 System.err.println(ignore.getClass().getName() + " - " + ignore.getMessage());
165 // If the Desktop call failed, need to try backup methods
168 // If system looks like a Mac, try the open command
169 String osName = System.getProperty("os.name").toLowerCase();
170 boolean isMacOsx = osName.indexOf("mac os") >= 0 || osName.indexOf("darwin") >= 0;
173 String[] command = new String[] {"open", inFile.getAbsolutePath()};
175 Runtime.getRuntime().exec(command);
178 catch (IOException ioe) {}
185 * Try to stop a currently playing clip
187 public void stopClip()
189 if (_clip != null && _clip.isActive()) {
194 catch (Exception e) {}
199 * @return percentage of clip currently played, or -1 if not playing
201 public int getPercentage()
204 if (_clip != null && _clip.isActive())
206 long clipLen = _clip.getMicrosecondLength();
208 percent = (int) (_clip.getMicrosecondPosition() * 100.0 / clipLen);
215 * @param inName name of audio file
216 * @return suffix (rest of name after the dot) - expect mp3, wav, ogg
218 private static final String getSuffix(String inName)
220 if (inName == null || inName.equals("")) {return ".tmp";}
221 final int dotPos = inName.lastIndexOf('.');
222 if (dotPos < 0) {return inName;} // no dot found
223 return inName.substring(dotPos);