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