+++ /dev/null
-package tim.prune.function;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-
-import javax.sound.sampled.AudioInputStream;
-import javax.sound.sampled.AudioSystem;
-import javax.sound.sampled.Clip;
-
-import tim.prune.App;
-import tim.prune.GenericFunction;
-import tim.prune.data.AudioClip;
-
-/**
- * Class to play the current audio clip
- */
-public class PlayAudioFunction extends GenericFunction implements Runnable
-{
- /** Audio clip used for playing within java */
- private Clip _clip = null;
-
-
- /**
- * Constructor
- * @param inApp app object
- */
- public PlayAudioFunction(App inApp) {
- super(inApp);
- }
-
- /**
- * @return name key
- */
- public String getNameKey() {
- return "function.playaudio";
- }
-
- /**
- * Perform function
- */
- public void begin()
- {
- // Launch new thread if clip isn't currently playing
- if (_clip == null) {
- new Thread(this).start();
- }
- }
-
- /**
- * Play the audio in a new thread
- */
- public void run()
- {
- AudioClip audio = _app.getTrackInfo().getCurrentAudio();
- File audioFile = audio.getFile();
- boolean played = false;
- if (audioFile != null && audioFile.exists() && audioFile.isFile() && audioFile.canRead())
- {
- // First choice is to play using java
- played = playClip(audio);
- // If this didn't work, then try to play the file another way
- if (!played) {
- played = playAudioFile(audioFile);
- }
- }
- else if (audioFile == null && audio.getByteData() != null)
- {
- // Try to play audio clip using byte array
- played = playClip(audio);
- // If this didn't work, then need to copy the byte data to a file and play it from there
- if (!played)
- {
- try
- {
- String suffix = getSuffix(audio.getName());
- File tempFile = File.createTempFile("gpsaudio", suffix);
- tempFile.deleteOnExit();
- // Copy byte data to this file
- BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile));
- bos.write(audio.getByteData(), 0, audio.getByteData().length);
- bos.close();
- played = playAudioFile(tempFile);
- }
- catch (IOException ignore) {
- System.err.println("Error: " + ignore.getClass().getName() + " - " + ignore.getMessage());
- }
- }
- }
- if (!played)
- {
- // If still not worked, show error message
- _app.showErrorMessage(getNameKey(), "error.playaudiofailed");
- }
- }
-
- /**
- * Try to play the sound file using built-in java libraries
- * @param inAudio audio clip to play
- * @return true if play was successful
- */
- private boolean playClip(AudioClip inClip)
- {
- boolean success = false;
- AudioInputStream audioInputStream = null;
- _clip = null;
- try
- {
- if (inClip.getFile() != null)
- audioInputStream = AudioSystem.getAudioInputStream(inClip.getFile());
- else if (inClip.getByteData() != null)
- audioInputStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(inClip.getByteData()));
- else return false;
- _clip = AudioSystem.getClip();
- _clip.open(audioInputStream);
- // play the clip
- _clip.start();
- _clip.drain();
- success = true;
- } catch (Exception e) {
- System.err.println(e.getClass().getName() + " - " + e.getMessage());
- } finally {
- // close the stream to clean up
- try {
- _clip.close();
- audioInputStream.close();
- } catch (Exception e) {}
- _clip = null;
- }
- return success;
- }
-
- /**
- * Try to play the specified audio file
- * @param inFile file to play
- * @return true if play was successful
- */
- private boolean playAudioFile(File inFile)
- {
- boolean played = false;
- // Try the Desktop library from java 6, if available
- if (!played)
- {
- try
- {
- Class<?> d = Class.forName("java.awt.Desktop");
- d.getDeclaredMethod("open", new Class[] {File.class}).invoke(
- d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {inFile});
- //above code mimics: Desktop.getDesktop().open(audioFile);
- played = true;
- }
- catch (InvocationTargetException e) {
- System.err.println("ITE: " + e.getCause().getClass().getName() + " - " + e.getCause().getMessage());
- played = false;
- }
- catch (Exception ignore) {
- System.err.println(ignore.getClass().getName() + " - " + ignore.getMessage());
- played = false;
- }
- }
-
- // If the Desktop call failed, need to try backup methods
- if (!played)
- {
- // If system looks like a Mac, try the open command
- String osName = System.getProperty("os.name").toLowerCase();
- boolean isMacOsx = osName.indexOf("mac os") >= 0 || osName.indexOf("darwin") >= 0;
- if (isMacOsx)
- {
- String[] command = new String[] {"open", inFile.getAbsolutePath()};
- try {
- Runtime.getRuntime().exec(command);
- played = true;
- }
- catch (IOException ioe) {}
- }
- }
- return played;
- }
-
- /**
- * Try to stop a currently playing clip
- */
- public void stopClip()
- {
- if (_clip != null && _clip.isActive()) {
- try {
- _clip.stop();
- _clip.flush();
- }
- catch (Exception e) {}
- }
- }
-
- /**
- * @return percentage of clip currently played, or -1 if not playing
- */
- public int getPercentage()
- {
- int percent = -1;
- if (_clip != null && _clip.isActive())
- {
- long clipLen = _clip.getMicrosecondLength();
- if (clipLen > 0) {
- percent = (int) (_clip.getMicrosecondPosition() * 100.0 / clipLen);
- }
- }
- return percent;
- }
-
- /**
- * @param inName name of audio file
- * @return suffix (rest of name after the dot) - expect mp3, wav, ogg
- */
- private static final String getSuffix(String inName)
- {
- if (inName == null || inName.equals("")) {return ".tmp";}
- final int dotPos = inName.lastIndexOf('.');
- if (dotPos < 0) {return inName;} // no dot found
- return inName.substring(dotPos);
- }
-}