Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


app_festival.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2002, Christos Ricudis
5  *
6  * Christos Ricudis <ricudis@itc.auth.gr>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Connect to festival
22  *
23  * \author Christos Ricudis <ricudis@itc.auth.gr>
24  *
25  * \extref The Festival Speech Synthesis System - http://www.cstr.ed.ac.uk/projects/festival/
26  *
27  * \ingroup applications
28  */
29 
30 /*** MODULEINFO
31  <support_level>extended</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
37 
38 #include <sys/socket.h>
39 #include <netdb.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
42 #include <signal.h>
43 #include <fcntl.h>
44 #include <ctype.h>
45 #include <errno.h>
46 
47 #include "asterisk/file.h"
48 #include "asterisk/channel.h"
49 #include "asterisk/pbx.h"
50 #include "asterisk/module.h"
51 #include "asterisk/md5.h"
52 #include "asterisk/config.h"
53 #include "asterisk/utils.h"
54 #include "asterisk/lock.h"
55 #include "asterisk/app.h"
56 #include "asterisk/endian.h"
57 
58 #define FESTIVAL_CONFIG "festival.conf"
59 #define MAXLEN 180
60 #define MAXFESTLEN 2048
61 
62 /*** DOCUMENTATION
63  <application name="Festival" language="en_US">
64  <synopsis>
65  Say text to the user.
66  </synopsis>
67  <syntax>
68  <parameter name="text" required="true" />
69  <parameter name="intkeys" />
70  </syntax>
71  <description>
72  <para>Connect to Festival, send the argument, get back the waveform, play it to the user,
73  allowing any given interrupt keys to immediately terminate and return the value, or
74  <literal>any</literal> to allow any number back (useful in dialplan).</para>
75  </description>
76  </application>
77  ***/
78 
79 static char *app = "Festival";
80 
81 static char *socket_receive_file_to_buff(int fd, int *size)
82 {
83  /* Receive file (probably a waveform file) from socket using
84  * Festival key stuff technique, but long winded I know, sorry
85  * but will receive any file without closing the stream or
86  * using OOB data
87  */
88  static char *file_stuff_key = "ft_StUfF_key"; /* must == Festival's key */
89  char *buff, *tmp;
90  int bufflen;
91  int n,k,i;
92  char c;
93 
94  bufflen = 1024;
95  if (!(buff = ast_malloc(bufflen)))
96  return NULL;
97  *size = 0;
98 
99  for (k = 0; file_stuff_key[k] != '\0';) {
100  n = read(fd, &c, 1);
101  if (n == 0)
102  break; /* hit stream eof before end of file */
103  if ((*size) + k + 1 >= bufflen) {
104  /* +1 so you can add a terminating NULL if you want */
105  bufflen += bufflen / 4;
106  if (!(tmp = ast_realloc(buff, bufflen))) {
107  ast_free(buff);
108  return NULL;
109  }
110  buff = tmp;
111  }
112  if (file_stuff_key[k] == c)
113  k++;
114  else if ((c == 'X') && (file_stuff_key[k+1] == '\0')) {
115  /* It looked like the key but wasn't */
116  for (i = 0; i < k; i++, (*size)++)
117  buff[*size] = file_stuff_key[i];
118  k = 0;
119  /* omit the stuffed 'X' */
120  } else {
121  for (i = 0; i < k; i++, (*size)++)
122  buff[*size] = file_stuff_key[i];
123  k = 0;
124  buff[*size] = c;
125  (*size)++;
126  }
127  }
128 
129  return buff;
130 }
131 
132 static int send_waveform_to_fd(char *waveform, int length, int fd)
133 {
134  int res;
135 #if __BYTE_ORDER == __BIG_ENDIAN
136  int x;
137  char c;
138 #endif
139 
140  res = ast_safe_fork(0);
141  if (res < 0)
142  ast_log(LOG_WARNING, "Fork failed\n");
143  if (res) {
144  return res;
145  }
146  dup2(fd, 0);
149  ast_set_priority(0);
150 #if __BYTE_ORDER == __BIG_ENDIAN
151  for (x = 0; x < length; x += 2) {
152  c = *(waveform + x + 1);
153  *(waveform + x + 1) = *(waveform + x);
154  *(waveform + x) = c;
155  }
156 #endif
157 
158  if (write(0, waveform, length) < 0) {
159  /* Cannot log -- all FDs are already closed */
160  }
161 
162  close(fd);
163  _exit(0);
164 }
165 
166 static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys)
167 {
168  int res = 0;
169  int fds[2];
170  int needed = 0;
171  int owriteformat;
172  struct ast_frame *f;
173  struct myframe {
174  struct ast_frame f;
176  char frdata[2048];
177  } myf = {
178  .f = { 0, },
179  };
180 
181  if (pipe(fds)) {
182  ast_log(LOG_WARNING, "Unable to create pipe\n");
183  return -1;
184  }
185 
186  /* Answer if it's not already going */
187  if (chan->_state != AST_STATE_UP)
188  ast_answer(chan);
189  ast_stopstream(chan);
190  ast_indicate(chan, -1);
191 
192  owriteformat = chan->writeformat;
194  if (res < 0) {
195  ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
196  return -1;
197  }
198 
199  res = send_waveform_to_fd(waveform, length, fds[1]);
200  if (res >= 0) {
201  /* Order is important -- there's almost always going to be mp3... we want to prioritize the
202  user */
203  for (;;) {
204  res = ast_waitfor(chan, 1000);
205  if (res < 1) {
206  res = -1;
207  break;
208  }
209  f = ast_read(chan);
210  if (!f) {
211  ast_log(LOG_WARNING, "Null frame == hangup() detected\n");
212  res = -1;
213  break;
214  }
215  if (f->frametype == AST_FRAME_DTMF) {
216  ast_debug(1, "User pressed a key\n");
217  if (intkeys && strchr(intkeys, f->subclass.integer)) {
218  res = f->subclass.integer;
219  ast_frfree(f);
220  break;
221  }
222  }
223  if (f->frametype == AST_FRAME_VOICE) {
224  /* Treat as a generator */
225  needed = f->samples * 2;
226  if (needed > sizeof(myf.frdata)) {
227  ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
228  (int)sizeof(myf.frdata) / 2, needed/2);
229  needed = sizeof(myf.frdata);
230  }
231  res = read(fds[0], myf.frdata, needed);
232  if (res > 0) {
233  myf.f.frametype = AST_FRAME_VOICE;
234  myf.f.subclass.codec = AST_FORMAT_SLINEAR;
235  myf.f.datalen = res;
236  myf.f.samples = res / 2;
237  myf.f.offset = AST_FRIENDLY_OFFSET;
238  myf.f.src = __PRETTY_FUNCTION__;
239  myf.f.data.ptr = myf.frdata;
240  if (ast_write(chan, &myf.f) < 0) {
241  res = -1;
242  ast_frfree(f);
243  break;
244  }
245  if (res < needed) { /* last frame */
246  ast_debug(1, "Last frame\n");
247  res = 0;
248  ast_frfree(f);
249  break;
250  }
251  } else {
252  ast_debug(1, "No more waveform\n");
253  res = 0;
254  }
255  }
256  ast_frfree(f);
257  }
258  }
259  close(fds[0]);
260  close(fds[1]);
261 
262  if (!res && owriteformat)
263  ast_set_write_format(chan, owriteformat);
264  return res;
265 }
266 
267 static int festival_exec(struct ast_channel *chan, const char *vdata)
268 {
269  int usecache;
270  int res = 0;
271  struct sockaddr_in serv_addr;
272  struct hostent *serverhost;
273  struct ast_hostent ahp;
274  int fd;
275  FILE *fs;
276  const char *host;
277  const char *cachedir;
278  const char *temp;
279  const char *festivalcommand;
280  int port = 1314;
281  int n;
282  char ack[4];
283  char *waveform;
284  int filesize;
285  char bigstring[MAXFESTLEN];
286  int i;
287  struct MD5Context md5ctx;
288  unsigned char MD5Res[16];
289  char MD5Hex[33] = "";
290  char koko[4] = "";
291  char cachefile[MAXFESTLEN]="";
292  int readcache = 0;
293  int writecache = 0;
294  int strln;
295  int fdesc = -1;
296  char buffer[16384];
297  int seekpos = 0;
298  char *data;
299  struct ast_config *cfg;
300  char *newfestivalcommand;
301  struct ast_flags config_flags = { 0 };
303  AST_APP_ARG(text);
304  AST_APP_ARG(interrupt);
305  );
306 
307  if (ast_strlen_zero(vdata)) {
308  ast_log(LOG_WARNING, "festival requires an argument (text)\n");
309  return -1;
310  }
311 
312  cfg = ast_config_load(FESTIVAL_CONFIG, config_flags);
313  if (!cfg) {
314  ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
315  return -1;
316  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
317  ast_log(LOG_ERROR, "Config file " FESTIVAL_CONFIG " is in an invalid format. Aborting.\n");
318  return -1;
319  }
320 
321  if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
322  host = "localhost";
323  }
324  if (!(temp = ast_variable_retrieve(cfg, "general", "port"))) {
325  port = 1314;
326  } else {
327  port = atoi(temp);
328  }
329  if (!(temp = ast_variable_retrieve(cfg, "general", "usecache"))) {
330  usecache = 0;
331  } else {
332  usecache = ast_true(temp);
333  }
334  if (!(cachedir = ast_variable_retrieve(cfg, "general", "cachedir"))) {
335  cachedir = "/tmp/";
336  }
337 
338  data = ast_strdupa(vdata);
340 
341  if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
342  const char *startcmd = "(tts_textasterisk \"";
343  const char *endcmd = "\" 'file)(quit)\n";
344 
345  strln = strlen(startcmd) + strlen(args.text) + strlen(endcmd) + 1;
346  newfestivalcommand = ast_alloca(strln);
347  snprintf(newfestivalcommand, strln, "%s%s%s", startcmd, args.text, endcmd);
348  festivalcommand = newfestivalcommand;
349  } else { /* This else parses the festivalcommand that we're sent from the config file for \n's, etc */
350  int x, j;
351  newfestivalcommand = ast_alloca(strlen(festivalcommand) + strlen(args.text) + 1);
352 
353  for (x = 0, j = 0; x < strlen(festivalcommand); x++) {
354  if (festivalcommand[x] == '\\' && festivalcommand[x + 1] == 'n') {
355  newfestivalcommand[j++] = '\n';
356  x++;
357  } else if (festivalcommand[x] == '\\') {
358  newfestivalcommand[j++] = festivalcommand[x + 1];
359  x++;
360  } else if (festivalcommand[x] == '%' && festivalcommand[x + 1] == 's') {
361  sprintf(&newfestivalcommand[j], "%s", args.text); /* we know it is big enough */
362  j += strlen(args.text);
363  x++;
364  } else
365  newfestivalcommand[j++] = festivalcommand[x];
366  }
367  newfestivalcommand[j] = '\0';
368  festivalcommand = newfestivalcommand;
369  }
370 
371  if (args.interrupt && !strcasecmp(args.interrupt, "any"))
372  args.interrupt = AST_DIGIT_ANY;
373 
374  ast_debug(1, "Text passed to festival server : %s\n", args.text);
375  /* Connect to local festival server */
376 
377  fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
378 
379  if (fd < 0) {
380  ast_log(LOG_WARNING, "festival_client: can't get socket\n");
381  ast_config_destroy(cfg);
382  return -1;
383  }
384 
385  memset(&serv_addr, 0, sizeof(serv_addr));
386 
387  if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
388  /* its a name rather than an ipnum */
389  serverhost = ast_gethostbyname(host, &ahp);
390 
391  if (serverhost == NULL) {
392  ast_log(LOG_WARNING, "festival_client: gethostbyname failed\n");
393  ast_config_destroy(cfg);
394  return -1;
395  }
396  memmove(&serv_addr.sin_addr, serverhost->h_addr, serverhost->h_length);
397  }
398 
399  serv_addr.sin_family = AF_INET;
400  serv_addr.sin_port = htons(port);
401 
402  if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
403  ast_log(LOG_WARNING, "festival_client: connect to server failed\n");
404  ast_config_destroy(cfg);
405  return -1;
406  }
407 
408  /* Compute MD5 sum of string */
409  MD5Init(&md5ctx);
410  MD5Update(&md5ctx, (unsigned char *)args.text, strlen(args.text));
411  MD5Final(MD5Res, &md5ctx);
412  MD5Hex[0] = '\0';
413 
414  /* Convert to HEX and look if there is any matching file in the cache
415  directory */
416  for (i = 0; i < 16; i++) {
417  snprintf(koko, sizeof(koko), "%X", (unsigned)MD5Res[i]);
418  strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
419  }
420  readcache = 0;
421  writecache = 0;
422  if (strlen(cachedir) + strlen(MD5Hex) + 1 <= MAXFESTLEN && (usecache == -1)) {
423  snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
424  fdesc = open(cachefile, O_RDWR);
425  if (fdesc == -1) {
426  fdesc = open(cachefile, O_CREAT | O_RDWR, AST_FILE_MODE);
427  if (fdesc != -1) {
428  writecache = 1;
429  strln = strlen(args.text);
430  ast_debug(1, "line length : %d\n", strln);
431  if (write(fdesc,&strln,sizeof(int)) < 0) {
432  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
433  }
434  if (write(fdesc,data,strln) < 0) {
435  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
436  }
437  seekpos = lseek(fdesc, 0, SEEK_CUR);
438  ast_debug(1, "Seek position : %d\n", seekpos);
439  }
440  } else {
441  if (read(fdesc,&strln,sizeof(int)) != sizeof(int)) {
442  ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
443  }
444  ast_debug(1, "Cache file exists, strln=%d, strlen=%d\n", strln, (int)strlen(args.text));
445  if (strlen(args.text) == strln) {
446  ast_debug(1, "Size OK\n");
447  if (read(fdesc,&bigstring,strln) != strln) {
448  ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
449  }
450  bigstring[strln] = 0;
451  if (strcmp(bigstring, args.text) == 0) {
452  readcache = 1;
453  } else {
454  ast_log(LOG_WARNING, "Strings do not match\n");
455  }
456  } else {
457  ast_log(LOG_WARNING, "Size mismatch\n");
458  }
459  }
460  }
461 
462  if (readcache == 1) {
463  close(fd);
464  fd = fdesc;
465  ast_debug(1, "Reading from cache...\n");
466  } else {
467  ast_debug(1, "Passing text to festival...\n");
468  fs = fdopen(dup(fd), "wb");
469 
470  fprintf(fs, "%s", festivalcommand);
471  fflush(fs);
472  fclose(fs);
473  }
474 
475  /* Write to cache and then pass it down */
476  if (writecache == 1) {
477  ast_debug(1, "Writing result to cache...\n");
478  while ((strln = read(fd, buffer, 16384)) != 0) {
479  if (write(fdesc,buffer,strln) < 0) {
480  ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
481  }
482  }
483  close(fd);
484  close(fdesc);
485  fd = open(cachefile, O_RDWR);
486  lseek(fd, seekpos, SEEK_SET);
487  }
488 
489  ast_debug(1, "Passing data to channel...\n");
490 
491  /* Read back info from server */
492  /* This assumes only one waveform will come back, also LP is unlikely */
493  do {
494  int read_data;
495  for (n = 0; n < 3; ) {
496  read_data = read(fd, ack + n, 3 - n);
497  /* this avoids falling in infinite loop
498  * in case that festival server goes down
499  */
500  if (read_data == -1) {
501  ast_log(LOG_WARNING, "Unable to read from cache/festival fd\n");
502  close(fd);
503  ast_config_destroy(cfg);
504  return -1;
505  }
506  n += read_data;
507  }
508  ack[3] = '\0';
509  if (strcmp(ack, "WV\n") == 0) { /* receive a waveform */
510  ast_debug(1, "Festival WV command\n");
511  if ((waveform = socket_receive_file_to_buff(fd, &filesize))) {
512  res = send_waveform_to_channel(chan, waveform, filesize, args.interrupt);
513  ast_free(waveform);
514  }
515  break;
516  } else if (strcmp(ack, "LP\n") == 0) { /* receive an s-expr */
517  ast_debug(1, "Festival LP command\n");
518  if ((waveform = socket_receive_file_to_buff(fd, &filesize))) {
519  waveform[filesize] = '\0';
520  ast_log(LOG_WARNING, "Festival returned LP : %s\n", waveform);
521  ast_free(waveform);
522  }
523  } else if (strcmp(ack, "ER\n") == 0) { /* server got an error */
524  ast_log(LOG_WARNING, "Festival returned ER\n");
525  res = -1;
526  break;
527  }
528  } while (strcmp(ack, "OK\n") != 0);
529  close(fd);
530  ast_config_destroy(cfg);
531  return res;
532 }
533 
534 static int unload_module(void)
535 {
536  return ast_unregister_application(app);
537 }
538 
539 static int load_module(void)
540 {
541  struct ast_flags config_flags = { 0 };
542  struct ast_config *cfg = ast_config_load(FESTIVAL_CONFIG, config_flags);
543  if (!cfg) {
544  ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
546  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
547  ast_log(LOG_ERROR, "Config file " FESTIVAL_CONFIG " is in an invalid format. Aborting.\n");
549  }
550  ast_config_destroy(cfg);
552 }
553 
554 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Festival Interface");
union ast_frame_subclass subclass
Definition: frame.h:146
static int unload_module(void)
Definition: app_festival.c:534
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:396
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
int offset
Definition: frame.h:156
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: app.c:2242
format_t writeformat
Definition: channel.h:854
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
static int festival_exec(struct ast_channel *chan, const char *vdata)
Definition: app_festival.c:267
#define LOG_WARNING
Definition: logger.h:144
#define AST_FRAME_DTMF
Definition: frame.h:128
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
void MD5Final(unsigned char digest[16], struct MD5Context *context)
Definition: md5.c:122
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
Configuration File Parser.
char * text
Definition: app_queue.c:1091
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
#define AST_FILE_MODE
Definition: asterisk.h:36
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys)
Definition: app_festival.c:166
void MD5Init(struct MD5Context *context)
Definition: md5.c:59
Utility functions.
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
General Asterisk PBX channel definitions.
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
Asterisk architecture endianess compatibility definitions.
#define MAXFESTLEN
Definition: app_festival.c:60
Core PBX routines and definitions.
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1650
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
Definition: md5.c:74
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
static struct @350 args
enum ast_channel_state _state
Definition: channel.h:839
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
#define ast_free(a)
Definition: astmm.h:97
#define FESTIVAL_CONFIG
Definition: app_festival.c:58
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: app.c:2237
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
static char * app
Definition: app_festival.c:79
Structure used to handle boolean flags.
Definition: utils.h:200
Definition: md5.h:26
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: utils.c:195
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
static unsigned char * buff
Definition: chan_unistim.c:232
#define ast_realloc(a, b)
Definition: astmm.h:103
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
Data structure associated with a single frame of data.
Definition: frame.h:142
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
static int load_module(void)
Definition: app_festival.c:539
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
#define ast_malloc(a)
Definition: astmm.h:91
Asterisk module definitions.
MD5 digest functions.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
int samples
Definition: frame.h:150
#define ast_opt_high_priority
Definition: options.h:108
static char * socket_receive_file_to_buff(int fd, int *size)
Definition: app_festival.c:81
static int send_waveform_to_fd(char *waveform, int length, int fd)
Definition: app_festival.c:132