Initial import to Gerrit.
[profile/ivi/festival.git] / src / modules / java / cstr / festival / client / Festival.java
1
2  //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
3  //                                                                        \\
4  //                 Centre for Speech Technology Research                  \\
5  //                      University of Edinburgh, UK                       \\
6  //                        Copyright (c) 1996,1997                         \\
7  //                         All Rights Reserved.                           \\
8  //   Permission is hereby granted, free of charge, to use and distribute  \\
9  //   this software and its documentation without restriction, including   \\
10  //   without limitation the rights to use, copy, modify, merge, publish,  \\
11  //   distribute, sublicense, and/or sell copies of this work, and to      \\
12  //   permit persons to whom this work is furnished to do so, subject to   \\
13  //   the following conditions:                                            \\
14  //    1. The code must retain the above copyright notice, this list of    \\
15  //       conditions and the following disclaimer.                         \\
16  //    2. Any modifications must be clearly marked as such.                \\
17  //    3. Original authors' names are not deleted.                         \\
18  //    4. The authors' names are not used to endorse or promote products   \\
19  //       derived from this software without specific prior written        \\
20  //       permission.                                                      \\
21  //   THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        \\
22  //   DISCLAIM ALL WARRANTIES With REGARD TO THIS SOFTWARE, INCLUDING      \\
23  //   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   \\
24  //   SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     \\
25  //   FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    \\
26  //   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   \\
27  //   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          \\
28  //   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       \\
29  //   THIS SOFTWARE.                                                       \\
30  //                                                                        \\
31  //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
32  //                                                                        \\
33  //                  Author: Richard Caley (rjc@cstr.ed.ac.uk)             \\
34  //  --------------------------------------------------------------------  \\
35  //  The thread which actually communicates with festival.                 \\
36  //                                                                        \\
37  //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
38
39
40 package cstr.festival.client ;
41
42 import java.lang.*;
43 import java.util.*;
44 import java.awt.*;
45 import java.io.*;
46 import java.net.*;
47
48 import cstr.est.*;
49
50 class Job
51 {
52   Integer id;
53   String command;
54   Session session;
55
56   public Job(Integer i, String c, Session s)
57     {
58       id=i;
59       command=c;
60       session=s;
61     }
62 }
63
64 class Festival extends Thread
65 {
66   public static final int FT_SCHEME = 1;
67   public static final int FT_WAVE = 2;
68
69   protected static byte [] endm;
70   protected Socket s;
71   protected String hostname=null;
72   protected InetAddress address = null;
73   protected int port=-1;
74   protected boolean closeOnExit;
75
76   protected PrintWriter out;
77   protected InputStream in;
78
79   protected boolean ok;
80
81   protected JobQueue jobs;
82
83   private byte buffer[];
84   private int buffered_p;
85   private int buffered_e;
86
87   static {
88     String end="ft_StUfF_key";
89     endm = new byte[end.length()];
90
91     for(int i=0;i<endm.length; i++)
92       {
93         endm[i] = (byte)end.charAt(i);
94       }
95
96   }
97
98   protected Festival(Socket sock, boolean close)
99     {
100       s=sock;
101       closeOnExit=close;
102       jobs = new JobQueue();
103       buffer = new byte[8096];
104       buffered_p=0;
105       buffered_e=0;
106       ok=true;
107     }
108
109   public Festival(Socket sock)
110     {
111       this(sock, false);
112     }
113
114   public Festival(InetAddress addr, int p)
115                 throws IOException
116     {
117       this(new Socket(addr, p), true);
118       address=addr;
119       port=p;
120     }
121
122   public Festival(String host, int p)
123                 throws IOException, UnknownHostException
124     {
125       this(InetAddress.getByName(host), p);
126       hostname=host;
127     }
128
129   public void run()
130     {
131       try {
132         setPriority(getPriority()+1);
133         out = new PrintWriter(s.getOutputStream());
134         in = s.getInputStream();
135         while (true)
136           {
137             if (jobs.isEmpty())
138               {
139                 if (ok)
140                   suspend();
141                 else
142                   break;
143               }
144             else
145               {
146                 Job job = (Job)jobs.get();
147                 // System.out.println("sending "+job.command);
148                 out.println(job.command);
149                 out.flush();
150
151                 String status;
152
153                 job.session.notifyRunning(job.id);
154
155                 while (true)
156                   {
157                     status = getStatus();
158                     if (status.startsWith("ER"))
159                       {
160                         job.session.notifyError(job.id, "");
161                         break;
162                       }
163                     else if (status.startsWith("LP"))
164                       {
165                         byte [] res=getResult();
166                         job.session.notifyResult(job.id, FT_SCHEME, res);
167                       }
168                     else if (status.startsWith("WV"))
169                       {
170                         byte[] res=getResult();
171                         job.session.notifyResult(job.id, FT_WAVE, res);
172                       }
173                     else if (status.startsWith("OK"))
174                       {
175                         break;
176                       }
177                     else
178                       {
179                         byte [] res=getResult();
180                         job.session.notifyError(job.id, "unknown type");
181                       }
182                   }
183                 
184                 job.session.notifyFinished(job.id);
185               }
186           }
187       } catch (IOException ex) {
188         System.err.println("IO Error '"+ex.getMessage()+"'");
189       } finally {
190         try {
191           closeSocket();
192         } catch (IOException ex) {
193           System.err.println("Error closing festival socket '"+ex.getMessage()+"'");
194         }
195         while (!jobs.isEmpty())
196           {
197             System.out.println("Left Job '"+((Job)jobs.get()).command+"'");
198           }
199       }
200     }
201
202   public void connect()
203     {
204       // System.err.println("Connecting");
205       start();
206     }
207
208   public void disconnect(boolean carefully)
209     {
210       // System.err.println("Disconnecting");
211       ok=false;
212       resume();
213       if (carefully)
214         {
215           try {
216             join();
217           } catch (InterruptedException ex) {
218             stop();
219           };
220         }
221       else
222         stop();
223     }
224
225   private void closeSocket() throws IOException
226     {
227       if (closeOnExit)
228         {
229           // System.err.println("Closing festival socket");
230           s.close();
231         }
232     }
233
234   public void newJob(Integer id, String c, Session s)
235     {
236       jobs.add(new Job(id,c,s));
237       resume();
238     }
239
240   // finally! To the things which talk to festival.
241
242   private byte[] readTo(InputStream s, char end) throws IOException
243     {
244       if (buffered_e == buffered_p)
245         {
246           buffered_p=0;
247           buffered_e=s.read(buffer, 0, 8096);
248         }
249
250       byte [] res=null;
251       for(int i=buffered_p; i<buffered_e; i++)
252         if (buffer[i] == (byte)end)
253           {
254             res = new byte[i-buffered_p+1];
255             break;
256           }
257
258       if (res==null)
259         res = new byte[buffered_e-buffered_p];
260
261       for(int i=0; i< res.length; i++)
262         res[i] = buffer[buffered_p+i];
263
264       buffered_p = buffered_p+res.length;
265
266       return res;
267     }
268
269   protected String getLine() throws IOException
270     {
271       StringBuffer line= new StringBuffer(20);
272
273       while (true)
274         {
275           byte [] bit = readTo(in, '\n');
276           line.append(new String(bit));
277
278           //System.out.println("got '"+line.toString()+"'");
279
280           if (line.charAt(line.length()-1) == '\n')
281             break;
282         }
283
284       //System.out.println("result '"+line.toString()+"'");
285       return line.toString();
286     }
287
288           
289   protected String getStatus() throws IOException
290     {
291       String line = getLine();
292
293       // System.out.println("        Status = '"+line+"'");
294       return line==null?"EOF":line;
295     }
296
297   protected byte[] getResult() throws IOException
298     {
299       byte [] res = new byte[0];
300
301       while (true)
302         {
303           byte [] bit = readTo(in, 'y');
304
305           int end = bit.length-endm.length;
306
307           if (end < 0)
308             end = bit.length;
309           else
310             {
311               for(int i=0; i< endm.length; i++)
312                 if (bit[i+end] != endm[i])
313                   {
314                     end = bit.length;
315                     break;
316                   }
317             }
318
319           byte  [] new_res = new byte[res.length+end];
320
321           for (int i=0; i< res.length; i++)
322             new_res[i] = res[i];
323           for (int i=0; i< end; i++)
324             new_res[res.length+i] = bit[i];
325
326           res= new_res;
327
328           if (end < bit.length)
329             break;
330         }
331
332       return res;
333       
334
335       /*
336       String line;
337       StringBuffer val = new StringBuffer();
338
339       if (pending != null)
340         {
341           line=pending;
342           pending=null;
343         }
344       else
345         line = in.readLine();
346
347       while (line != null)
348         {
349           int endm = line.indexOf("ft_StUfF_key");
350
351           if (endm >=0)
352             {
353               val.append(line.substring(0, endm));
354               pending = line.substring(endm+12);
355               break;
356             }
357           else
358             {
359               val.append(line);
360               val.append("\n");
361             }
362
363           line = in.readLine();
364         }
365       return val.toString();
366       */
367     }
368 }