Wed Jan 8 2020 09:49:53

Asterisk developer's documentation


app_festival.c File Reference

Connect to festival. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/md5.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/endian.h"

Go to the source code of this file.

Macros

#define FESTIVAL_CONFIG   "festival.conf"
 
#define MAXFESTLEN   2048
 
#define MAXLEN   180
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int festival_exec (struct ast_channel *chan, const char *vdata)
 
static int load_module (void)
 
static int send_waveform_to_channel (struct ast_channel *chan, char *waveform, int length, char *intkeys)
 
static int send_waveform_to_fd (char *waveform, int length, int fd)
 
static char * socket_receive_file_to_buff (int fd, int *size)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Simple Festival Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static char * app = "Festival"
 
static struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

Connect to festival.

Author
Christos Ricudis ricud.nosp@m.is@i.nosp@m.tc.au.nosp@m.th.g.nosp@m.r
ExtRef:
The Festival Speech Synthesis System - http://www.cstr.ed.ac.uk/projects/festival/

Definition in file app_festival.c.

Macro Definition Documentation

#define FESTIVAL_CONFIG   "festival.conf"

Definition at line 58 of file app_festival.c.

Referenced by festival_exec(), and load_module().

#define MAXFESTLEN   2048

Definition at line 60 of file app_festival.c.

Referenced by festival_exec().

#define MAXLEN   180

Definition at line 59 of file app_festival.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 554 of file app_festival.c.

static void __unreg_module ( void  )
static

Definition at line 554 of file app_festival.c.

static int festival_exec ( struct ast_channel chan,
const char *  vdata 
)
static

Definition at line 267 of file app_festival.c.

References args, ast_alloca, AST_APP_ARG, ast_config_destroy(), ast_config_load, ast_debug, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, AST_FILE_MODE, ast_free, ast_gethostbyname(), ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_true(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, errno, FESTIVAL_CONFIG, LOG_ERROR, LOG_WARNING, MAXFESTLEN, MD5Final(), MD5Init(), MD5Update(), send_waveform_to_channel(), socket_receive_file_to_buff(), and text.

Referenced by load_module().

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 }
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
#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
#define LOG_WARNING
Definition: logger.h:144
#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
char * text
Definition: app_queue.c:1091
#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
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#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
#define MAXFESTLEN
Definition: app_festival.c:60
static struct ast_hostent ahp
Definition: chan_skinny.c:1047
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
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
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_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#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
static char * socket_receive_file_to_buff(int fd, int *size)
Definition: app_festival.c:81
static int load_module ( void  )
static

Definition at line 539 of file app_festival.c.

References ast_config_destroy(), ast_config_load, ast_log(), AST_MODULE_LOAD_DECLINE, ast_register_application_xml, CONFIG_STATUS_FILEINVALID, FESTIVAL_CONFIG, festival_exec(), LOG_ERROR, and LOG_WARNING.

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 }
static int festival_exec(struct ast_channel *chan, const char *vdata)
Definition: app_festival.c:267
#define LOG_WARNING
Definition: logger.h:144
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
#define LOG_ERROR
Definition: logger.h:155
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
#define FESTIVAL_CONFIG
Definition: app_festival.c:58
static char * app
Definition: app_festival.c:79
Structure used to handle boolean flags.
Definition: utils.h:200
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int send_waveform_to_channel ( struct ast_channel chan,
char *  waveform,
int  length,
char *  intkeys 
)
static

Definition at line 166 of file app_festival.c.

References ast_channel::_state, ast_answer(), ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, AST_FRIENDLY_OFFSET, ast_indicate(), ast_log(), ast_read(), ast_set_write_format(), AST_STATE_UP, ast_stopstream(), ast_waitfor(), ast_write(), f, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, ast_frame::offset, ast_frame::samples, send_waveform_to_fd(), ast_frame::subclass, and ast_channel::writeformat.

Referenced by festival_exec().

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 }
union ast_frame_subclass subclass
Definition: frame.h:146
int offset
Definition: frame.h:156
format_t writeformat
Definition: channel.h:854
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#define LOG_WARNING
Definition: logger.h:144
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
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
#define AST_FRIENDLY_OFFSET
Offset into a frame&#39;s data buffer.
Definition: frame.h:204
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
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
#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
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
int samples
Definition: frame.h:150
static int send_waveform_to_fd(char *waveform, int length, int fd)
Definition: app_festival.c:132
static int send_waveform_to_fd ( char *  waveform,
int  length,
int  fd 
)
static

Definition at line 132 of file app_festival.c.

References ast_close_fds_above_n(), ast_log(), ast_opt_high_priority, ast_safe_fork(), ast_set_priority(), and LOG_WARNING.

Referenced by send_waveform_to_channel().

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 }
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
#define LOG_WARNING
Definition: logger.h:144
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 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
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
#define ast_opt_high_priority
Definition: options.h:108
static char* socket_receive_file_to_buff ( int  fd,
int *  size 
)
static

Definition at line 81 of file app_festival.c.

References ast_free, ast_malloc, ast_realloc, and buff.

Referenced by festival_exec().

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 }
#define ast_free(a)
Definition: astmm.h:97
static unsigned char * buff
Definition: chan_unistim.c:232
#define ast_realloc(a, b)
Definition: astmm.h:103
#define ast_malloc(a)
Definition: astmm.h:91
static int unload_module ( void  )
static

Definition at line 534 of file app_festival.c.

References ast_unregister_application().

535 {
537 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static char * app
Definition: app_festival.c:79

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Simple Festival Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 554 of file app_festival.c.

char* app = "Festival"
static

Definition at line 79 of file app_festival.c.

Definition at line 554 of file app_festival.c.