]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/function/PlayAudioFunction.java
0e14d7c9ad1f9f6c9f4df9f761b7c466838b751d
[GpsPrune.git] / tim / prune / function / PlayAudioFunction.java
1 package tim.prune.function;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.File;
5 import java.io.IOException;
6 import javax.sound.sampled.AudioInputStream;
7 import javax.sound.sampled.AudioSystem;
8 import javax.sound.sampled.Clip;
9
10 import tim.prune.App;
11 import tim.prune.GenericFunction;
12 import tim.prune.data.AudioClip;
13
14 /**
15  * Class to play the current audio clip
16  */
17 public class PlayAudioFunction extends GenericFunction implements Runnable
18 {
19         /** Audio clip used for playing within java */
20         private Clip _clip = null;
21
22
23         /**
24          * Constructor
25          * @param inApp app object
26          */
27         public PlayAudioFunction(App inApp) {
28                 super(inApp);
29         }
30
31         /**
32          * @return name key
33          */
34         public String getNameKey() {
35                 return "function.playaudio";
36         }
37
38         /**
39          * Perform function
40          */
41         public void begin()
42         {
43                 // Launch new thread if clip isn't currently playing
44                 if (_clip == null) {
45                         new Thread(this).start();
46                 }
47         }
48
49         /**
50          * Play the audio in a new thread
51          */
52         public void run()
53         {
54                 AudioClip audio = _app.getTrackInfo().getCurrentAudio();
55                 File audioFile = audio.getFile();
56                 boolean played = false;
57                 if (audioFile != null && audioFile.exists() && audioFile.isFile() && audioFile.canRead())
58                 {
59                         // First choice is to play using java
60                         played = playClip(audio);
61                         // Second choice is to try the Desktop library from java 6, if available
62                         if (!played) {
63                                 try {
64                                         Class<?> d = Class.forName("java.awt.Desktop");
65                                         d.getDeclaredMethod("open", new Class[] {File.class}).invoke(
66                                                 d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {audioFile});
67                                         //above code mimics: Desktop.getDesktop().open(audioFile);
68                                         played = true;
69                                 }
70                                 catch (Exception ignore) {
71                                         played = false;
72                                 }
73                         }
74                         // If the Desktop call failed, need to try backup methods
75                         if (!played)
76                         {
77                                 // If system looks like a Mac, try open command
78                                 String osName = System.getProperty("os.name").toLowerCase();
79                                 boolean isMacOsx = osName.indexOf("mac os") >= 0 || osName.indexOf("darwin") >= 0;
80                                 if (isMacOsx) {
81                                         String[] command = new String[] {"open", audioFile.getAbsolutePath()};
82                                         try {
83                                                 Runtime.getRuntime().exec(command);
84                                                 played = true;
85                                         }
86                                         catch (IOException ioe) {}
87                                 }
88                         }
89                 }
90                 else if (audioFile == null && audio.getByteData() != null) {
91                         // Try to play audio clip using byte array (can't use Desktop or Runtime)
92                         played = playClip(audio);
93                 }
94                 if (!played)
95                 {
96                         // If still not worked, show error message
97                         _app.showErrorMessage(getNameKey(), "error.playaudiofailed");
98                 }
99         }
100
101         /**
102          * Try to play the sound file using built-in java libraries
103          * @param inAudio audio clip to play
104          * @return true if play was successful
105          */
106         private boolean playClip(AudioClip inClip)
107         {
108                 boolean success = false;
109                 AudioInputStream audioInputStream = null;
110                 _clip = null;
111                 try
112                 {
113                         if (inClip.getFile() != null)
114                                 audioInputStream = AudioSystem.getAudioInputStream(inClip.getFile());
115                         else if (inClip.getByteData() != null)
116                                 audioInputStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(inClip.getByteData()));
117                         else return false;
118                         _clip = AudioSystem.getClip();
119                         _clip.open(audioInputStream);
120                         // play the clip
121                         _clip.start();
122                         _clip.drain();
123                         success = true;
124                 } catch (Exception e) {
125                         System.err.println(e.getClass().getName() + " - " + e.getMessage());
126                 } finally {
127                         // close the stream to clean up
128                         try {
129                                 _clip.close();
130                                 audioInputStream.close();
131                         } catch (Exception e) {}
132                         _clip = null;
133                 }
134                 return success;
135         }
136
137         /**
138          * Try to stop a currently playing clip
139          */
140         public void stopClip()
141         {
142                 if (_clip != null && _clip.isActive()) {
143                         try {
144                                 _clip.stop();
145                                 _clip.flush();
146                         }
147                         catch (Exception e) {}
148                 }
149         }
150
151         /**
152          * @return percentage of clip currently played, or -1 if not playing
153          */
154         public int getPercentage()
155         {
156                 int percent = -1;
157                 if (_clip != null && _clip.isActive())
158                 {
159                         long clipLen = _clip.getMicrosecondLength();
160                         if (clipLen > 0) {
161                                 percent = (int) (_clip.getMicrosecondPosition() * 100.0 / clipLen);
162                         }
163                 }
164                 return percent;
165         }
166 }