Wed Jan 8 2020 09:49:40

Asterisk developer's documentation


app_playback.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
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 Trivial application to playback a sound file
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \ingroup applications
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 396279 $")
35 
36 #include "asterisk/file.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/module.h"
39 #include "asterisk/app.h"
40 /* This file provides config-file based 'say' functions, and implenents
41  * some CLI commands.
42  */
43 #include "asterisk/say.h" /* provides config-file based 'say' functions */
44 #include "asterisk/cli.h"
45 
46 /*** DOCUMENTATION
47  <application name="Playback" language="en_US">
48  <synopsis>
49  Play a file.
50  </synopsis>
51  <syntax>
52  <parameter name="filenames" required="true" argsep="&amp;">
53  <argument name="filename" required="true" />
54  <argument name="filename2" multiple="true" />
55  </parameter>
56  <parameter name="options">
57  <para>Comma separated list of options</para>
58  <optionlist>
59  <option name="skip">
60  <para>Do not play if not answered</para>
61  </option>
62  <option name="noanswer">
63  <para>Playback without answering, otherwise the channel will
64  be answered before the sound is played.</para>
65  <note><para>Not all channel types support playing messages while still on hook.</para></note>
66  </option>
67  </optionlist>
68  </parameter>
69  </syntax>
70  <description>
71  <para>Plays back given filenames (do not put extension of wav/alaw etc).
72  The playback command answer the channel if no options are specified.
73  If the file is non-existant it will fail</para>
74  <para>This application sets the following channel variable upon completion:</para>
75  <variablelist>
76  <variable name="PLAYBACKSTATUS">
77  <para>The status of the playback attempt as a text string.</para>
78  <value name="SUCCESS"/>
79  <value name="FAILED"/>
80  </variable>
81  </variablelist>
82  <para>See Also: Background (application) -- for playing sound files that are interruptible</para>
83  <para>WaitExten (application) -- wait for digits from caller, optionally play music on hold</para>
84  </description>
85  </application>
86  ***/
87 
88 static char *app = "Playback";
89 
90 static struct ast_config *say_cfg = NULL;
91 /* save the say' api calls.
92  * The first entry is NULL if we have the standard source,
93  * otherwise we are sourcing from here.
94  * 'say load [new|old]' will enable the new or old method, or report status
95  */
96 static const void *say_api_buf[40];
97 static const char * const say_old = "old";
98 static const char * const say_new = "new";
99 
100 static void save_say_mode(const void *arg)
101 {
102  int i = 0;
103  say_api_buf[i++] = arg;
104 
105  say_api_buf[i++] = ast_say_number_full;
106  say_api_buf[i++] = ast_say_enumeration_full;
107  say_api_buf[i++] = ast_say_digit_str_full;
108  say_api_buf[i++] = ast_say_character_str_full;
109  say_api_buf[i++] = ast_say_phonetic_str_full;
110  say_api_buf[i++] = ast_say_datetime;
111  say_api_buf[i++] = ast_say_time;
112  say_api_buf[i++] = ast_say_date;
113  say_api_buf[i++] = ast_say_datetime_from_now;
114  say_api_buf[i++] = ast_say_date_with_format;
115 }
116 
117 static void restore_say_mode(void *arg)
118 {
119  int i = 0;
120  say_api_buf[i++] = arg;
121 
122  ast_say_number_full = say_api_buf[i++];
123  ast_say_enumeration_full = say_api_buf[i++];
124  ast_say_digit_str_full = say_api_buf[i++];
125  ast_say_character_str_full = say_api_buf[i++];
126  ast_say_phonetic_str_full = say_api_buf[i++];
127  ast_say_datetime = say_api_buf[i++];
128  ast_say_time = say_api_buf[i++];
129  ast_say_date = say_api_buf[i++];
130  ast_say_datetime_from_now = say_api_buf[i++];
131  ast_say_date_with_format = say_api_buf[i++];
132 }
133 
134 /*
135  * Typical 'say' arguments in addition to the date or number or string
136  * to say. We do not include 'options' because they may be different
137  * in recursive calls, and so they are better left as an external
138  * parameter.
139  */
140 typedef struct {
141  struct ast_channel *chan;
142  const char *ints;
143  const char *language;
144  int audiofd;
145  int ctrlfd;
146 } say_args_t;
147 
148 static int s_streamwait3(const say_args_t *a, const char *fn)
149 {
150  int res = ast_streamfile(a->chan, fn, a->language);
151  if (res) {
152  ast_log(LOG_WARNING, "Unable to play message %s\n", fn);
153  return res;
154  }
155  res = (a->audiofd > -1 && a->ctrlfd > -1) ?
156  ast_waitstream_full(a->chan, a->ints, a->audiofd, a->ctrlfd) :
157  ast_waitstream(a->chan, a->ints);
158  ast_stopstream(a->chan);
159  return res;
160 }
161 
162 /*
163  * the string is 'prefix:data' or prefix:fmt:data'
164  * with ':' being invalid in strings.
165  */
166 static int do_say(say_args_t *a, const char *s, const char *options, int depth)
167 {
168  struct ast_variable *v;
169  char *lang, *x, *rule = NULL;
170  int ret = 0;
171  struct varshead head = { .first = NULL, .last = NULL };
172  struct ast_var_t *n;
173 
174  ast_debug(2, "string <%s> depth <%d>\n", s, depth);
175  if (depth++ > 10) {
176  ast_log(LOG_WARNING, "recursion too deep, exiting\n");
177  return -1;
178  } else if (!say_cfg) {
179  ast_log(LOG_WARNING, "no say.conf, cannot spell '%s'\n", s);
180  return -1;
181  }
182 
183  /* scan languages same as in file.c */
184  if (a->language == NULL)
185  a->language = "en"; /* default */
186  ast_debug(2, "try <%s> in <%s>\n", s, a->language);
187  lang = ast_strdupa(a->language);
188  for (;;) {
189  for (v = ast_variable_browse(say_cfg, lang); v ; v = v->next) {
190  if (ast_extension_match(v->name, s)) {
191  rule = ast_strdupa(v->value);
192  break;
193  }
194  }
195  if (rule)
196  break;
197  if ( (x = strchr(lang, '_')) )
198  *x = '\0'; /* try without suffix */
199  else if (strcmp(lang, "en"))
200  lang = "en"; /* last resort, try 'en' if not done yet */
201  else
202  break;
203  }
204  if (!rule)
205  return 0;
206 
207  /* skip up to two prefixes to get the value */
208  if ( (x = strchr(s, ':')) )
209  s = x + 1;
210  if ( (x = strchr(s, ':')) )
211  s = x + 1;
212  ast_debug(2, "value is <%s>\n", s);
213  n = ast_var_assign("SAY", s);
214  if (!n) {
215  ast_log(LOG_ERROR, "Memory allocation error in do_say\n");
216  return -1;
217  }
218  AST_LIST_INSERT_HEAD(&head, n, entries);
219 
220  /* scan the body, one piece at a time */
221  while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */
222  char fn[128];
223  const char *p, *fmt, *data; /* format and data pointers */
224 
225  /* prepare a decent file name */
226  x = ast_skip_blanks(x);
227  ast_trim_blanks(x);
228 
229  /* replace variables */
230  pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn));
231  ast_debug(2, "doing [%s]\n", fn);
232 
233  /* locate prefix and data, if any */
234  fmt = strchr(fn, ':');
235  if (!fmt || fmt == fn) { /* regular filename */
236  ret = s_streamwait3(a, fn);
237  continue;
238  }
239  fmt++;
240  data = strchr(fmt, ':'); /* colon before data */
241  if (!data || data == fmt) { /* simple prefix-fmt */
242  ret = do_say(a, fn, options, depth);
243  continue;
244  }
245  /* prefix:fmt:data */
246  for (p = fmt; p < data && ret <= 0; p++) {
247  char fn2[sizeof(fn)];
248  if (*p == ' ' || *p == '\t') /* skip blanks */
249  continue;
250  if (*p == '\'') {/* file name - we trim them */
251  char *y;
252  strcpy(fn2, ast_skip_blanks(p+1)); /* make a full copy */
253  y = strchr(fn2, '\'');
254  if (!y) {
255  p = data; /* invalid. prepare to end */
256  break;
257  }
258  *y = '\0';
259  ast_trim_blanks(fn2);
260  p = strchr(p+1, '\'');
261  ret = s_streamwait3(a, fn2);
262  } else {
263  int l = fmt-fn;
264  strcpy(fn2, fn); /* copy everything */
265  /* after prefix, append the format */
266  fn2[l++] = *p;
267  strcpy(fn2 + l, data);
268  ret = do_say(a, fn2, options, depth);
269  }
270 
271  if (ret) {
272  break;
273  }
274  }
275  }
276  ast_var_delete(n);
277  return ret;
278 }
279 
280 static int say_full(struct ast_channel *chan, const char *string,
281  const char *ints, const char *lang, const char *options,
282  int audiofd, int ctrlfd)
283 {
284  say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
285  return do_say(&a, string, options, 0);
286 }
287 
288 static int say_number_full(struct ast_channel *chan, int num,
289  const char *ints, const char *lang, const char *options,
290  int audiofd, int ctrlfd)
291 {
292  char buf[64];
293  say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
294  snprintf(buf, sizeof(buf), "num:%d", num);
295  return do_say(&a, buf, options, 0);
296 }
297 
298 static int say_enumeration_full(struct ast_channel *chan, int num,
299  const char *ints, const char *lang, const char *options,
300  int audiofd, int ctrlfd)
301 {
302  char buf[64];
303  say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
304  snprintf(buf, sizeof(buf), "enum:%d", num);
305  return do_say(&a, buf, options, 0);
306 }
307 
308 static int say_date_generic(struct ast_channel *chan, time_t t,
309  const char *ints, const char *lang, const char *format, const char *timezonename, const char *prefix)
310 {
311  char buf[128];
312  struct ast_tm tm;
313  struct timeval when = { t, 0 };
314  say_args_t a = { chan, ints, lang, -1, -1 };
315  if (format == NULL)
316  format = "";
317 
318  ast_localtime(&when, &tm, NULL);
319  snprintf(buf, sizeof(buf), "%s:%s:%04d%02d%02d%02d%02d.%02d-%d-%3d",
320  prefix,
321  format,
322  tm.tm_year+1900,
323  tm.tm_mon+1,
324  tm.tm_mday,
325  tm.tm_hour,
326  tm.tm_min,
327  tm.tm_sec,
328  tm.tm_wday,
329  tm.tm_yday);
330  return do_say(&a, buf, NULL, 0);
331 }
332 
333 static int say_date_with_format(struct ast_channel *chan, time_t t,
334  const char *ints, const char *lang, const char *format, const char *timezonename)
335 {
336  return say_date_generic(chan, t, ints, lang, format, timezonename, "datetime");
337 }
338 
339 static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
340 {
341  return say_date_generic(chan, t, ints, lang, "", NULL, "date");
342 }
343 
344 static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
345 {
346  return say_date_generic(chan, t, ints, lang, "", NULL, "time");
347 }
348 
349 static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
350 {
351  return say_date_generic(chan, t, ints, lang, "", NULL, "datetime");
352 }
353 
354 /*
355  * remap the 'say' functions to use those in this file
356  */
357 static int say_init_mode(const char *mode) {
358  if (!strcmp(mode, say_new)) {
359  if (say_cfg == NULL) {
360  ast_log(LOG_ERROR, "There is no say.conf file to use new mode\n");
361  return -1;
362  }
363  save_say_mode(say_new);
365 
367 #if 0
368  ast_say_digits_full = say_digits_full;
373 #endif
378  } else if (!strcmp(mode, say_old) && say_api_buf[0] == say_new) {
379  restore_say_mode(NULL);
380  } else if (strcmp(mode, say_old)) {
381  ast_log(LOG_WARNING, "unrecognized mode %s\n", mode);
382  return -1;
383  }
384 
385  return 0;
386 }
387 
388 static char *__say_cli_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
389 {
390  const char *old_mode = say_api_buf[0] ? say_new : say_old;
391  const char *mode;
392  switch (cmd) {
393  case CLI_INIT:
394  e->command = "say load [new|old]";
395  e->usage =
396  "Usage: say load [new|old]\n"
397  " say load\n"
398  " Report status of current say mode\n"
399  " say load new\n"
400  " Set say method, configured in say.conf\n"
401  " say load old\n"
402  " Set old say method, coded in asterisk core\n";
403  return NULL;
404  case CLI_GENERATE:
405  return NULL;
406  }
407  if (a->argc == 2) {
408  ast_cli(a->fd, "say mode is [%s]\n", old_mode);
409  return CLI_SUCCESS;
410  } else if (a->argc != e->args)
411  return CLI_SHOWUSAGE;
412  mode = a->argv[2];
413  if (!strcmp(mode, old_mode))
414  ast_cli(a->fd, "say mode is %s already\n", mode);
415  else
416  if (say_init_mode(mode) == 0)
417  ast_cli(a->fd, "setting say mode from %s to %s\n", old_mode, mode);
418 
419  return CLI_SUCCESS;
420 }
421 
422 static struct ast_cli_entry cli_playback[] = {
423  AST_CLI_DEFINE(__say_cli_init, "Set or show the say mode"),
424 };
425 
426 static int playback_exec(struct ast_channel *chan, const char *data)
427 {
428  int res = 0;
429  int mres = 0;
430  char *tmp;
431  int option_skip=0;
432  int option_say=0;
433  int option_noanswer = 0;
434 
436  AST_APP_ARG(filenames);
437  AST_APP_ARG(options);
438  );
439 
440  if (ast_strlen_zero(data)) {
441  ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
442  return -1;
443  }
444 
445  tmp = ast_strdupa(data);
447 
448  if (args.options) {
449  if (strcasestr(args.options, "skip"))
450  option_skip = 1;
451  if (strcasestr(args.options, "say"))
452  option_say = 1;
453  if (strcasestr(args.options, "noanswer"))
454  option_noanswer = 1;
455  }
456  if (chan->_state != AST_STATE_UP) {
457  if (option_skip) {
458  /* At the user's option, skip if the line is not up */
459  goto done;
460  } else if (!option_noanswer) {
461  /* Otherwise answer unless we're supposed to send this while on-hook */
462  res = ast_answer(chan);
463  }
464  }
465  if (!res) {
466  char *back = args.filenames;
467  char *front;
468 
469  ast_stopstream(chan);
470  while (!res && (front = strsep(&back, "&"))) {
471  if (option_say)
472  res = say_full(chan, front, "", chan->language, NULL, -1, -1);
473  else
474  res = ast_streamfile(chan, front, chan->language);
475  if (!res) {
476  res = ast_waitstream(chan, "");
477  ast_stopstream(chan);
478  } else {
479  ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
480  res = 0;
481  mres = 1;
482  }
483  }
484  }
485 done:
486  pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", mres ? "FAILED" : "SUCCESS");
487  return res;
488 }
489 
490 static int reload(void)
491 {
492  struct ast_variable *v;
493  struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED };
494  struct ast_config *newcfg;
495 
496  if ((newcfg = ast_config_load("say.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
497  return 0;
498  } else if (newcfg == CONFIG_STATUS_FILEINVALID) {
499  ast_log(LOG_ERROR, "Config file say.conf is in an invalid format. Aborting.\n");
500  return 0;
501  }
502 
503  if (say_cfg) {
504  ast_config_destroy(say_cfg);
505  ast_log(LOG_NOTICE, "Reloading say.conf\n");
506  }
507  say_cfg = newcfg;
508 
509  if (say_cfg) {
510  for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) {
511  if (ast_extension_match(v->name, "mode")) {
512  say_init_mode(v->value);
513  break;
514  }
515  }
516  }
517 
518  /*
519  * XXX here we should sort rules according to the same order
520  * we have in pbx.c so we have the same matching behaviour.
521  */
522  return 0;
523 }
524 
525 static int unload_module(void)
526 {
527  int res;
528 
529  res = ast_unregister_application(app);
530 
531  ast_cli_unregister_multiple(cli_playback, ARRAY_LEN(cli_playback));
532 
533  if (say_cfg)
534  ast_config_destroy(say_cfg);
535 
536  return res;
537 }
538 
539 static int load_module(void)
540 {
541  struct ast_variable *v;
542  struct ast_flags config_flags = { 0 };
543 
544  say_cfg = ast_config_load("say.conf", config_flags);
545  if (say_cfg && say_cfg != CONFIG_STATUS_FILEINVALID) {
546  for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) {
547  if (ast_extension_match(v->name, "mode")) {
548  say_init_mode(v->value);
549  break;
550  }
551  }
552  }
553 
554  ast_cli_register_multiple(cli_playback, ARRAY_LEN(cli_playback));
556 }
557 
558 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Sound File Playback Application",
559  .load = load_module,
560  .unload = unload_module,
561  .reload = reload,
562  );
const char * language
Definition: app_playback.c:143
static void save_say_mode(const void *arg)
Definition: app_playback.c:100
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static int say_character_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
Definition: say.c:63
static int unload_module(void)
Definition: app_playback.c:525
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
Asterisk main include file. File version handling, generic pbx functions.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * strsep(char **str, const char *delims)
static int say_date_with_format(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezonename)
Definition: app_playback.c:333
static int do_say(say_args_t *a, const char *s, const char *options, int depth)
Definition: app_playback.c:166
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static int say_number_full(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd)
Definition: app_playback.c:288
struct ast_var_t * ast_var_assign(const char *name, const char *value)
Definition: chanvars.c:41
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
int ast_say_digits_full(struct ast_channel *chan, int num, const char *ints, const char *lang, int audiofd, int ctrlfd)
Definition: channel.c:8433
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static int say_datetime_from_now(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: say.c:7022
Definition: cli.h:146
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
static struct ast_cli_entry cli_playback[]
Definition: app_playback.c:422
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int tm_year
Definition: localtime.h:41
void ast_var_delete(struct ast_var_t *var)
Definition: chanvars.c:63
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
SAY_EXTERN int(* ast_say_datetime)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_datetime)
Definition: say.h:161
const char * ints
Definition: app_playback.c:142
int args
This gets set in ast_cli_register()
Definition: cli.h:179
static int say_enumeration_full(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd)
Definition: app_playback.c:298
static int reload(void)
Definition: app_playback.c:490
SAY_EXTERN int(* ast_say_date)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_date)
Definition: say.h:164
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
const char * value
Definition: config.h:79
SAY_EXTERN int(* ast_say_enumeration_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_enumeration_full)
Definition: say.h:105
struct ast_var_t * first
Definition: chanvars.h:34
const int fd
Definition: cli.h:153
#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
static struct ast_config * say_cfg
Definition: app_playback.c:90
int tm_mon
Definition: localtime.h:40
static int say_full(struct ast_channel *chan, const char *string, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd)
Definition: app_playback.c:280
const char * name
Definition: config.h:77
static int s_streamwait3(const say_args_t *a, const char *fn)
Definition: app_playback.c:148
int tm_mday
Definition: localtime.h:39
static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: app_playback.c:349
Core PBX routines and definitions.
SAY_EXTERN int(* ast_say_phonetic_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_phonetic_str_full)
Definition: say.h:159
const char *const * argv
Definition: cli.h:155
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
static struct @350 args
#define CLI_SHOWUSAGE
Definition: cli.h:44
SAY_EXTERN int(* ast_say_character_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_character_str_full)
Definition: say.h:154
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:97
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 LOG_NOTICE
Definition: logger.h:133
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:122
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
static const void * say_api_buf[40]
Definition: app_playback.c:96
int tm_wday
Definition: localtime.h:42
struct ast_var_t::@158 entries
char * command
Definition: cli.h:180
SAY_EXTERN int(* ast_say_datetime_from_now)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_datetime_from_now)
Definition: say.h:166
static char * app
Definition: app_playback.c:88
struct ast_channel * chan
Definition: app_playback.c:141
static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: app_playback.c:344
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2943
int tm_hour
Definition: localtime.h:38
Structure used to handle boolean flags.
Definition: utils.h:200
const char * usage
Definition: cli.h:171
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
int tm_sec
Definition: localtime.h:36
#define CLI_SUCCESS
Definition: cli.h:43
static int say_date_generic(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezonename, const char *prefix)
Definition: app_playback.c:308
static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
Definition: app_playback.c:339
int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd, int monfd)
Definition: file.c:1348
SAY_EXTERN int(* ast_say_digit_str_full)(struct ast_channel *chan, const char *num, const char *ints, const char *lang, int audiofd, int ctrlfd) SAY_INIT(ast_say_digit_str_full)
Definition: say.h:140
Standard Command Line Interface.
static int say_digit_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
Definition: say.c:225
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
SAY_EXTERN int(* ast_say_date_with_format)(struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone) SAY_INIT(ast_say_date_with_format)
Definition: say.h:168
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
static int say_phonetic_str_full(struct ast_channel *chan, const char *str, const char *ints, const char *lang, int audiofd, int ctrlfd)
Definition: say.c:145
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...
static const char *const say_new
Definition: app_playback.c:98
SAY_EXTERN int(* ast_say_number_full)(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd) SAY_INIT(ast_say_number_full)
Definition: say.h:86
static int load_module(void)
Definition: app_playback.c:539
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
struct ast_variable * next
Definition: config.h:82
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static char * __say_cli_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: app_playback.c:388
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
int tm_yday
Definition: localtime.h:43
SAY_EXTERN int(* ast_say_time)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_time)
Definition: say.h:162
Say numbers and dates (maybe words one day too)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Asterisk module definitions.
char * strcasestr(const char *, const char *)
static int playback_exec(struct ast_channel *chan, const char *data)
Definition: app_playback.c:426
static snd_pcm_format_t format
Definition: chan_alsa.c:93
static int say_init_mode(const char *mode)
Definition: app_playback.c:357
static const char *const say_old
Definition: app_playback.c:97
const ast_string_field language
Definition: channel.h:787
static void restore_say_mode(void *arg)
Definition: app_playback.c:117
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
int tm_min
Definition: localtime.h:37
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
Definition: pbx.c:4682
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static char prefix[MAX_PREFIX]
Definition: http.c:107