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 
Job(Integer i, String c, Session s)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 
Festival(Socket sock, boolean close)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 
Festival(Socket sock)109   public Festival(Socket sock)
110     {
111       this(sock, false);
112     }
113 
Festival(InetAddress addr, int p)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 
Festival(String host, int p)122   public Festival(String host, int p)
123 		throws IOException, UnknownHostException
124     {
125       this(InetAddress.getByName(host), p);
126       hostname=host;
127     }
128 
run()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 
connect()202   public void connect()
203     {
204       // System.err.println("Connecting");
205       start();
206     }
207 
disconnect(boolean carefully)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 
closeSocket()225   private void closeSocket() throws IOException
226     {
227       if (closeOnExit)
228 	{
229 	  // System.err.println("Closing festival socket");
230 	  s.close();
231 	}
232     }
233 
newJob(Integer id, String c, Session s)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 
readTo(InputStream s, char end)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 
getLine()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 
getStatus()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 
getResult()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 }
369