Sat Aug 6 00:39:35 2011

Asterisk developer's documentation


app_playback.c File Reference

Trivial application to playback a sound file. More...

#include "asterisk.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/cli.h"
#include "asterisk/localtime.h"
#include "asterisk/say.h"

Go to the source code of this file.

Data Structures

struct  say_args_t

Functions

static void __reg_module (void)
static int __say_init (int fd, int argc, char *argv[])
static void __unreg_module (void)
static int do_say (say_args_t *a, const char *s, const char *options, int depth)
static int load_module (void)
static int playback_exec (struct ast_channel *chan, void *data)
static int reload (void)
static void restore_say_mode (void *arg)
static int s_streamwait3 (const say_args_t *a, const char *fn)
static void save_say_mode (const void *arg)
static int say_date (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
static int say_date_generic (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone, const char *prefix)
static int say_date_with_format (struct ast_channel *chan, time_t t, const char *ints, const char *lang, const char *format, const char *timezone)
static int say_datetime (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
static int say_enumeration_full (struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd)
static int say_full (struct ast_channel *chan, const char *string, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd)
static int say_number_full (struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options, int audiofd, int ctrlfd)
static int say_time (struct ast_channel *chan, time_t t, const char *ints, const char *lang)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Sound File Playback Application" , .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, }
static char * app = "Playback"
static const struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_playback []
static char * descrip
static const void * say_api_buf [40]
static struct ast_configsay_cfg = NULL
static const char * say_new = "new"
static const char * say_old = "old"
static char * synopsis = "Play a file"


Detailed Description

Trivial application to playback a sound file.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_playback.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 495 of file app_playback.c.

static int __say_init ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 332 of file app_playback.c.

References ast_cli(), ast_config_load(), ast_log(), ast_say_character_str_full, ast_say_date, ast_say_date_with_format, ast_say_datetime, ast_say_datetime_from_now, ast_say_digit_str_full, ast_say_digits_full(), ast_say_enumeration_full, ast_say_number_full, ast_say_phonetic_str_full, ast_say_time, LOG_WARNING, restore_say_mode(), RESULT_SHOWUSAGE, RESULT_SUCCESS, save_say_mode(), say_cfg, say_character_str_full(), say_date(), say_date_with_format(), say_datetime(), say_datetime_from_now(), say_digit_str_full(), say_enumeration_full(), say_number_full(), say_phonetic_str_full(), and say_time().

00333 {
00334    const char *old_mode = say_api_buf[0] ? say_new : say_old;
00335    char *mode;
00336 
00337    if (argc == 2) {
00338       ast_cli(fd, "say mode is [%s]\n", old_mode);
00339       return RESULT_SUCCESS;
00340         } else if (argc != 3)
00341                 return RESULT_SHOWUSAGE;
00342         mode = argv[2];
00343 
00344    ast_log(LOG_WARNING, "init say.c from %s to %s\n", old_mode, mode);
00345 
00346    if (!strcmp(mode, old_mode)) {
00347       ast_log(LOG_WARNING, "say mode is %s already\n", mode);
00348    } else if (!strcmp(mode, say_new)) {
00349       if (say_cfg == NULL)
00350          say_cfg = ast_config_load("say.conf");
00351       save_say_mode(say_new);
00352       ast_say_number_full = say_number_full;
00353 
00354       ast_say_enumeration_full = say_enumeration_full;
00355 #if 0
00356       ast_say_digits_full = say_digits_full;
00357       ast_say_digit_str_full = say_digit_str_full;
00358       ast_say_character_str_full = say_character_str_full;
00359       ast_say_phonetic_str_full = say_phonetic_str_full;
00360       ast_say_datetime_from_now = say_datetime_from_now;
00361 #endif
00362       ast_say_datetime = say_datetime;
00363       ast_say_time = say_time;
00364       ast_say_date = say_date;
00365       ast_say_date_with_format = say_date_with_format;
00366    } else if (!strcmp(mode, say_old) && say_api_buf[0] == say_new) {
00367       restore_say_mode(NULL);
00368    } else {
00369       ast_log(LOG_WARNING, "unrecognized mode %s\n", mode);
00370    }
00371    return RESULT_SUCCESS;
00372 }

static void __unreg_module ( void   )  [static]

Definition at line 495 of file app_playback.c.

static int do_say ( say_args_t a,
const char *  s,
const char *  options,
int  depth 
) [static]

Definition at line 149 of file app_playback.c.

References ast_extension_match(), ast_log(), ast_strdupa, ast_variable_browse(), varshead::first, say_args_t::language, LOG_WARNING, ast_variable::name, ast_variable::next, say_cfg, and ast_variable::value.

Referenced by say_date_generic(), say_enumeration_full(), say_full(), and say_number_full().

00150 {
00151    struct ast_variable *v;
00152    char *lang, *x, *rule = NULL;
00153    int ret = 0;   
00154    struct varshead head = { .first = NULL, .last = NULL };
00155    struct ast_var_t *n;
00156 
00157    if (depth++ > 10) {
00158       ast_log(LOG_WARNING, "recursion too deep, exiting\n");
00159       return -1;
00160    } else if (!say_cfg) {
00161       ast_log(LOG_WARNING, "no say.conf, cannot spell '%s'\n", s);
00162       return -1;
00163    }
00164 
00165    /* scan languages same as in file.c */
00166    if (a->language == NULL)
00167       a->language = "en";     /* default */
00168    lang = ast_strdupa(a->language);
00169    for (;;) {
00170       for (v = ast_variable_browse(say_cfg, lang); v ; v = v->next) {
00171          if (ast_extension_match(v->name, s)) {
00172             rule = ast_strdupa(v->value);
00173             break;
00174          }
00175       }
00176       if (rule)
00177          break;
00178       if ( (x = strchr(lang, '_')) )
00179          *x = '\0';      /* try without suffix */
00180       else if (strcmp(lang, "en"))
00181          lang = "en";    /* last resort, try 'en' if not done yet */
00182       else
00183          break;
00184    }
00185    if (!rule)
00186       return 0;
00187 
00188    /* skip up to two prefixes to get the value */
00189    if ( (x = strchr(s, ':')) )
00190       s = x + 1;
00191    if ( (x = strchr(s, ':')) )
00192       s = x + 1;
00193    n = ast_var_assign("SAY", s);
00194    AST_LIST_INSERT_HEAD(&head, n, entries);
00195 
00196    /* scan the body, one piece at a time */
00197    while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */
00198       char fn[128];
00199       const char *p, *fmt, *data; /* format and data pointers */
00200 
00201       /* prepare a decent file name */
00202       x = ast_skip_blanks(x);
00203       ast_trim_blanks(x);
00204 
00205       /* replace variables */
00206       memset(fn, 0, sizeof(fn)); /* XXX why isn't done in pbx_substitute_variables_helper! */
00207       pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn));
00208 
00209       /* locate prefix and data, if any */
00210       fmt = strchr(fn, ':');
00211       if (!fmt || fmt == fn)  {  /* regular filename */
00212          ret = s_streamwait3(a, fn);
00213          continue;
00214       }
00215       fmt++;
00216       data = strchr(fmt, ':');   /* colon before data */
00217       if (!data || data == fmt) {   /* simple prefix-fmt */
00218          ret = do_say(a, fn, options, depth);
00219          continue;
00220       }
00221       /* prefix:fmt:data */
00222       for (p = fmt; p < data && ret <= 0; p++) {
00223          char fn2[sizeof(fn)];
00224          if (*p == ' ' || *p == '\t')  /* skip blanks */
00225             continue;
00226          if (*p == '\'') {/* file name - we trim them */
00227             char *y;
00228             strcpy(fn2, ast_skip_blanks(p+1));  /* make a full copy */
00229             y = strchr(fn2, '\'');
00230             if (!y) {
00231                p = data;   /* invalid. prepare to end */
00232                break;
00233             }
00234             *y = '\0';
00235             ast_trim_blanks(fn2);
00236             p = strchr(p + 1, '\'');
00237             ret = s_streamwait3(a, fn2);
00238          } else {
00239             int l = fmt-fn;
00240             strcpy(fn2, fn); /* copy everything */
00241             /* after prefix, append the format */
00242             fn2[l++] = *p;
00243             strcpy(fn2 + l, data);
00244             ret = do_say(a, fn2, options, depth);
00245          }
00246          
00247          if (ret) {
00248             break;
00249          }
00250       }
00251    }
00252    ast_var_delete(n);
00253    return ret;
00254 }

static int load_module ( void   )  [static]

Definition at line 484 of file app_playback.c.

References ast_cli_register_multiple(), ast_config_load(), ast_register_application(), cli_playback, playback_exec(), and say_cfg.

00485 {
00486    say_cfg = ast_config_load("say.conf");
00487         ast_cli_register_multiple(cli_playback, sizeof(cli_playback) / sizeof(struct ast_cli_entry));
00488    return ast_register_application(app, playback_exec, synopsis, descrip);
00489 }

static int playback_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 380 of file app_playback.c.

References ast_channel::_state, ast_answer(), AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_goto_if_exists(), ast_log(), ast_module_user_add, ast_module_user_remove, ast_opt_priority_jumping, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_waitstream(), ast_module_user::chan, ast_channel::context, ast_channel::language, LOG_WARNING, ast_channel::name, pbx_builtin_setvar_helper(), and say_full().

Referenced by load_module().

00381 {
00382    int res = 0;
00383    int mres = 0;
00384    struct ast_module_user *u;
00385    char *tmp;
00386    int option_skip=0;
00387    int option_say=0;
00388    int option_noanswer = 0;
00389    int priority_jump = 0;
00390 
00391    AST_DECLARE_APP_ARGS(args,
00392       AST_APP_ARG(filenames);
00393       AST_APP_ARG(options);
00394    );
00395    
00396    if (ast_strlen_zero(data)) {
00397       ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
00398       return -1;
00399    }
00400 
00401    tmp = ast_strdupa(data);
00402 
00403    u = ast_module_user_add(chan);
00404    AST_STANDARD_APP_ARGS(args, tmp);
00405 
00406    if (args.options) {
00407       if (strcasestr(args.options, "skip"))
00408          option_skip = 1;
00409       if (strcasestr(args.options, "say"))
00410          option_say = 1;
00411       if (strcasestr(args.options, "noanswer"))
00412          option_noanswer = 1;
00413       if (strchr(args.options, 'j'))
00414          priority_jump = 1;
00415    }
00416    
00417    if (chan->_state != AST_STATE_UP) {
00418       if (option_skip) {
00419          /* At the user's option, skip if the line is not up */
00420          goto done;
00421       } else if (!option_noanswer) {
00422          /* Otherwise answer unless we're supposed to send this while on-hook */
00423          res = ast_answer(chan);
00424       }
00425    }
00426    if (!res) {
00427       char *back = args.filenames;
00428       char *front;
00429 
00430       ast_stopstream(chan);
00431       while (!res && (front = strsep(&back, "&"))) {
00432          if (option_say)
00433             res = say_full(chan, front, "", chan->language, NULL, -1, -1);
00434          else
00435             res = ast_streamfile(chan, front, chan->language);
00436          if (!res) { 
00437             res = ast_waitstream(chan, "");  
00438             ast_stopstream(chan);
00439          } else {
00440             ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
00441             if (priority_jump || ast_opt_priority_jumping)
00442                ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
00443             res = 0;
00444             mres = 1;
00445          }
00446       }
00447    }
00448 done:
00449    pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", mres ? "FAILED" : "SUCCESS");
00450    ast_module_user_remove(u);
00451    return res;
00452 }

static int reload ( void   )  [static]

Definition at line 454 of file app_playback.c.

References ast_config_destroy(), ast_config_load(), ast_log(), LOG_NOTICE, and say_cfg.

00455 {
00456    if (say_cfg) {
00457       ast_config_destroy(say_cfg);
00458       ast_log(LOG_NOTICE, "Reloading say.conf\n");
00459    }
00460    say_cfg = ast_config_load("say.conf");
00461    /*
00462     * XXX here we should sort rules according to the same order
00463     * we have in pbx.c so we have the same matching behaviour.
00464     */
00465    return 0;
00466 }

static void restore_say_mode ( void *  arg  )  [static]

Definition at line 100 of file app_playback.c.

References ast_say_character_str_full, ast_say_date, ast_say_date_with_format, ast_say_datetime, ast_say_datetime_from_now, ast_say_digit_str_full, ast_say_enumeration_full, ast_say_number_full, ast_say_phonetic_str_full, and ast_say_time.

Referenced by __say_init().

00101 {
00102    int i = 0;
00103    say_api_buf[i++] = arg;
00104 
00105         ast_say_number_full = say_api_buf[i++];
00106         ast_say_enumeration_full = say_api_buf[i++];
00107         ast_say_digit_str_full = say_api_buf[i++];
00108         ast_say_character_str_full = say_api_buf[i++];
00109         ast_say_phonetic_str_full = say_api_buf[i++];
00110         ast_say_datetime = say_api_buf[i++];
00111         ast_say_time = say_api_buf[i++];
00112         ast_say_date = say_api_buf[i++];
00113         ast_say_datetime_from_now = say_api_buf[i++];
00114         ast_say_date_with_format = say_api_buf[i++];
00115 }

static int s_streamwait3 ( const say_args_t a,
const char *  fn 
) [static]

Definition at line 131 of file app_playback.c.

References ast_log(), ast_stopstream(), ast_streamfile(), ast_waitstream(), ast_waitstream_full(), say_args_t::audiofd, say_args_t::chan, say_args_t::ctrlfd, say_args_t::ints, say_args_t::language, and LOG_WARNING.

00132 {
00133         int res = ast_streamfile(a->chan, fn, a->language);
00134         if (res) {
00135                 ast_log(LOG_WARNING, "Unable to play message %s\n", fn);
00136                 return res;
00137         }
00138         res = (a->audiofd  > -1 && a->ctrlfd > -1) ?
00139                 ast_waitstream_full(a->chan, a->ints, a->audiofd, a->ctrlfd) :
00140                 ast_waitstream(a->chan, a->ints);
00141         ast_stopstream(a->chan);
00142         return res;  
00143 }

static void save_say_mode ( const void *  arg  )  [static]

Definition at line 83 of file app_playback.c.

References ast_say_character_str_full, ast_say_date, ast_say_date_with_format, ast_say_datetime, ast_say_datetime_from_now, ast_say_digit_str_full, ast_say_enumeration_full, ast_say_number_full, ast_say_phonetic_str_full, and ast_say_time.

Referenced by __say_init().

00084 {
00085    int i = 0;
00086    say_api_buf[i++] = arg;
00087 
00088         say_api_buf[i++] = ast_say_number_full;
00089         say_api_buf[i++] = ast_say_enumeration_full;
00090         say_api_buf[i++] = ast_say_digit_str_full;
00091         say_api_buf[i++] = ast_say_character_str_full;
00092         say_api_buf[i++] = ast_say_phonetic_str_full;
00093         say_api_buf[i++] = ast_say_datetime;
00094         say_api_buf[i++] = ast_say_time;
00095         say_api_buf[i++] = ast_say_date;
00096         say_api_buf[i++] = ast_say_datetime_from_now;
00097         say_api_buf[i++] = ast_say_date_with_format;
00098 }

static int say_date ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
) [static]

Definition at line 314 of file app_playback.c.

References say_date_generic().

00315 {
00316    return say_date_generic(chan, t, ints, lang, "", NULL, "date");
00317 }

static int say_date_generic ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  timezone,
const char *  prefix 
) [static]

Definition at line 284 of file app_playback.c.

References ast_localtime(), and do_say().

Referenced by say_date(), say_date_with_format(), say_datetime(), and say_time().

00286 {
00287    char buf[128];
00288    struct tm tm;
00289         say_args_t a = { chan, ints, lang, -1, -1 };
00290    if (format == NULL)
00291       format = "";
00292 
00293    ast_localtime(&t, &tm, NULL);
00294    snprintf(buf, sizeof(buf), "%s:%s:%04d%02d%02d%02d%02d.%02d-%d-%3d",
00295       prefix,
00296       format,
00297       tm.tm_year+1900,
00298       tm.tm_mon+1,
00299       tm.tm_mday,
00300       tm.tm_hour,
00301       tm.tm_min,
00302       tm.tm_sec,
00303       tm.tm_wday,
00304       tm.tm_yday);
00305         return do_say(&a, buf, NULL, 0);
00306 }

static int say_date_with_format ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang,
const char *  format,
const char *  timezone 
) [static]

Definition at line 308 of file app_playback.c.

References say_date_generic().

00310 {
00311    return say_date_generic(chan, t, ints, lang, format, timezone, "datetime");
00312 }

static int say_datetime ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
) [static]

Definition at line 324 of file app_playback.c.

References say_date_generic().

00325 {
00326    return say_date_generic(chan, t, ints, lang, "", NULL, "datetime");
00327 }

static int say_enumeration_full ( struct ast_channel chan,
int  num,
const char *  ints,
const char *  lang,
const char *  options,
int  audiofd,
int  ctrlfd 
) [static]

Definition at line 274 of file app_playback.c.

References do_say().

00277 {
00278    char buf[64];
00279         say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
00280    snprintf(buf, sizeof(buf), "enum:%d", num);
00281         return do_say(&a, buf, options, 0);
00282 }

static int say_full ( struct ast_channel chan,
const char *  string,
const char *  ints,
const char *  lang,
const char *  options,
int  audiofd,
int  ctrlfd 
) [static]

Definition at line 256 of file app_playback.c.

References do_say().

Referenced by playback_exec().

00259 {
00260         say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
00261         return do_say(&a, string, options, 0);
00262 }

static int say_number_full ( struct ast_channel chan,
int  num,
const char *  ints,
const char *  lang,
const char *  options,
int  audiofd,
int  ctrlfd 
) [static]

Definition at line 264 of file app_playback.c.

References do_say().

00267 {
00268    char buf[64];
00269         say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
00270    snprintf(buf, sizeof(buf), "num:%d", num);
00271         return do_say(&a, buf, options, 0);
00272 }

static int say_time ( struct ast_channel chan,
time_t  t,
const char *  ints,
const char *  lang 
) [static]

Definition at line 319 of file app_playback.c.

References say_date_generic().

00320 {
00321    return say_date_generic(chan, t, ints, lang, "", NULL, "time");
00322 }

static int unload_module ( void   )  [static]

Definition at line 468 of file app_playback.c.

References ast_cli_unregister_multiple(), ast_config_destroy(), ast_module_user_hangup_all, ast_unregister_application(), cli_playback, and say_cfg.

00469 {
00470    int res;
00471 
00472    res = ast_unregister_application(app);
00473 
00474    ast_cli_unregister_multiple(cli_playback, sizeof(cli_playback) / sizeof(struct ast_cli_entry));
00475 
00476    ast_module_user_hangup_all();
00477 
00478    if (say_cfg)
00479       ast_config_destroy(say_cfg);
00480 
00481    return res; 
00482 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Sound File Playback Application" , .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 495 of file app_playback.c.

char* app = "Playback" [static]

Definition at line 50 of file app_playback.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 495 of file app_playback.c.

struct ast_cli_entry cli_playback[] [static]

Initial value:

 {
        { { "say", "load", NULL },
   __say_init, "set/show the say mode",
   "Usage: say load [new|old]\n    Set/show the say mode\n" },
}

Definition at line 374 of file app_playback.c.

Referenced by load_module(), and unload_module().

char* descrip [static]

Definition at line 54 of file app_playback.c.

const void* say_api_buf[40] [static]

Definition at line 79 of file app_playback.c.

struct ast_config* say_cfg = NULL [static]

Definition at line 73 of file app_playback.c.

Referenced by __say_init(), do_say(), load_module(), reload(), and unload_module().

const char* say_new = "new" [static]

Definition at line 81 of file app_playback.c.

const char* say_old = "old" [static]

Definition at line 80 of file app_playback.c.

char* synopsis = "Play a file" [static]

Definition at line 52 of file app_playback.c.


Generated on Sat Aug 6 00:39:35 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7