1 /*************************************************************************/
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1996,1997 */
6 /* 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 */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
32 /*************************************************************************/
33 /* Author : Alan W Black */
34 /* Date : September 1996 */
35 /*-----------------------------------------------------------------------*/
37 /* Interface with the audio spooler */
39 /*=======================================================================*/
44 #include "festivalP.h"
47 void audsp_play_wave(EST_Wave *w) { cerr << "no spooler available\n"; }
48 LISP l_audio_mode(LISP mode) { return NIL; }
51 #include <sys/types.h>
54 static int start_sub_process(int *fds,int argc,char **argv);
55 static char **enargen(const char *command,int *argc);
56 static void audsp_send(const char *c);
57 static int *pipe_open(const char *command);
58 static void pipe_close(int *fds);
61 static int audsp_num=0;
62 static int audsp_pid = 0;
64 void audsp_play_wave(EST_Wave *w)
66 EST_String tpref = make_tmp_filename();
67 char *tmpfilename = walloc(char,tpref.length()+20);
68 sprintf(tmpfilename,"%s_aud_%05d",(const char *)tpref,audsp_num++);
69 w->save(tmpfilename,"nist");
70 audsp_send(EST_String("play ")+tmpfilename+EST_String(" ")+
71 itoString(w->sample_rate()));
75 static void audsp_send(const char *c)
81 pid = waitpid((pid_t)audsp_pid,&statusp,WNOHANG);
84 cerr << "Audio spooler has died unexpectedly" << endl;
89 write(audfds[0],c,strlen(c));
90 write(audfds[0],"\n",1);
91 read(audfds[1],reply,3); /* confirmation */
94 LISP l_audio_mode(LISP mode)
102 cerr << "audio_mode: nil is not a valid mode\n";
105 else if (streq("async",get_c_string(mode)))
106 { // Asynchronous mode using the audio spooler.
107 if (audsp_mode == FALSE)
109 audio = ft_get_param("Audio_Method");
110 command = ft_get_param("Audio_Command");
111 audfds = pipe_open("audsp");
113 audsp_send(EST_String("method ")+get_c_string(audio));
116 // command needs to be a single line so delete an newlines
117 EST_String flattened = get_c_string(command);
118 flattened.gsub("\\\n"," ");
119 flattened.gsub("\n"," ");
120 audsp_send(EST_String("command ")+flattened);
122 if ((audio = ft_get_param("Audio_Required_Rate")) != NIL)
123 audsp_send(EST_String("rate ")+get_c_string(audio));
124 if ((audio = ft_get_param("Audio_Required_Format")) != NIL)
125 audsp_send(EST_String("otype ")+get_c_string(audio));
126 if ((audio = ft_get_param("Audio_Device")) != NIL)
127 audsp_send(EST_String("device ")+get_c_string(audio));
131 else if (streq("sync",get_c_string(mode)))
138 else if (streq("shutup",get_c_string(mode)))
141 audsp_send("shutup");
144 cerr << "audio_mode: not in async mode, can't shutup\n";
148 else if (streq("close",get_c_string(mode)))
149 { // return only when queue is empty
153 else if (streq("query",get_c_string(mode)))
159 cerr << "audio_mode: not in async mode, can't query\n";
165 cerr << "audio_mode: unknown mode \"" << get_c_string(mode) <<
173 static void pipe_close(int *fds)
175 // Close down the pipes
180 static int *pipe_open(const char *command)
182 // Starts a subprocess with its stdin and stdout bounad to pipes
183 // the ends of which are returned in an array
188 argv = enargen(command,&argc);
191 if (start_sub_process(fds,argc,argv) != 0)
193 cerr << "pipe_open: failed to start subprocess: \n" << endl;
194 cerr << "pipe_open: \"" << command << "\"\n";
201 static int start_sub_process(int *fds, int argc, char **argv)
203 // start sub_process with stdin and stdout bound to pipes whose ends
204 // are in fds[0] and fds[1]
210 if ((pipe(in) != 0) ||
213 cerr << "pipe_open: failed to open pipes\n";
220 close(in[1]); /* close the end child isn't using */
221 dup2(in[0],0); /* reassign stdin to the pipe */
223 dup2(out[1],1); /* reassign stdout to the pipe */
224 execvp(argv[0],argv);
225 cerr << "pipe_open: failed to start " << argv[0] << endl;
226 exit(-1); /* should only get here on failure */
228 cerr << "pipe_open: fork failed\n";
230 default: /* parent */
231 close(in[0]); /* Close unused sides of the pipes */
241 static char **enargen(const char *command,int *argc)
247 ts.open_string(command);
248 for (i=0; ts.get() != ""; i++);
252 argv = walloc(char *,i+1);
253 ts.open_string(command);
254 for (i=0; i < *argc; i++)
255 argv[i] = wstrdup(ts.get().string());