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