Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:48 2009

## Asterisk developer's documentation

# app_parkandannounce.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * Author: Ben Miller <bgmiller@dccinc.com>
    00009  *    With TONS of help from Mark!
    00010  *
    00011  * See http://www.asterisk.org for more information about
    00012  * the Asterisk project. Please do not directly contact
    00013  * any of the maintainers of this project for assistance;
    00014  * the project provides a web site, mailing lists and IRC
    00015  * channels for your use.
    00016  *
    00017  * This program is free software, distributed under the terms of
    00018  * the GNU General Public License Version 2. See the LICENSE file
    00019  * at the top of the source tree.
    00020  */
    00021
    00022 /*! \file
    00023  *
    00024  * \brief ParkAndAnnounce application for Asterisk
    00025  *
    00026  * \ingroup applications
    00027  */
    00028
    00029 #include <stdlib.h>
    00030 #include <stdio.h>
    00031 #include <string.h>
    00032 #include <unistd.h>
    00033 #include <sys/types.h>
    00034
    00035 #include "asterisk.h"
    00036
    00037 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
    00038
    00039 #include "asterisk/file.h"
    00040 #include "asterisk/logger.h"
    00041 #include "asterisk/channel.h"
    00042 #include "asterisk/pbx.h"
    00043 #include "asterisk/module.h"
    00044 #include "asterisk/features.h"
    00045 #include "asterisk/options.h"
    00046 #include "asterisk/logger.h"
    00047 #include "asterisk/say.h"
    00048 #include "asterisk/lock.h"
    00049
    00050 static char *tdesc = "Call Parking and Announce Application";
    00051
    00052 static char *app = "ParkAndAnnounce";
    00053
    00054 static char *synopsis = "Park and Announce";
    00055
    00056 static char *descrip =
    00057 "  ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
    00058 "Park a call into the parkinglot and announce the call over the console.\n"
    00059 "announce template: colon separated list of files to announce, the word PARKED\n"
    00060 "                   will be replaced by a say_digits of the ext the call is parked in\n"
    00061 "timeout: time in seconds before the call returns into the return context.\n"
    00062 "dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
    00063 "return_context: the goto style label to jump the call back into after timeout. default=prio+1\n";
    00064
    00065
    00066 STANDARD_LOCAL_USER;
    00067
    00068 LOCAL_USER_DECL;
    00069
    00070 static int parkandannounce_exec(struct ast_channel *chan, void *data)
    00071 {
    00072    int res=0;
    00073    char *return_context;
    00074    int l, lot, timeout = 0, dres;
    00075    char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
    00076    char *template, *tpl_working, *tpl_current;
    00077    char *tmp[100];
    00078    int looptemp=0,i=0;
    00079    char *s,*orig_s;
    00080
    00081    struct ast_channel *dchan;
    00082    struct outgoing_helper oh;
    00083    int outstate;
    00084
    00085    struct localuser *u;
    00086
    00087    if (ast_strlen_zero(data)) {
    00088       ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
    00089       return -1;
    00090    }
    00091
    00092    LOCAL_USER_ADD(u);
    00093
    00094    l=strlen(data)+2;
    00095    orig_s=malloc(l);
    00096    if(!orig_s) {
    00097       ast_log(LOG_WARNING, "Out of memory\n");
    00098       LOCAL_USER_REMOVE(u);
    00099       return -1;
    00100    }
    00101    s=orig_s;
    00102    strncpy(s,data,l);
    00103
    00104    template=strsep(&s,"|");
    00105    if(! template) {
    00106       ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
    00107       free(orig_s);
    00108       LOCAL_USER_REMOVE(u);
    00109       return -1;
    00110    }
    00111
    00112    if(s) {
    00113       timeout = atoi(strsep(&s, "|"));
    00114       timeout *= 1000;
    00115    }
    00116    dial=strsep(&s, "|");
    00117    if(!dial) {
    00118       ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
    00119       free(orig_s);
    00120       LOCAL_USER_REMOVE(u);
    00121       return -1;
    00122    } else {
    00123       dialtech=strsep(&dial, "/");
    00124       dialstr=dial;
    00125       ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
    00126    }
    00127
    00128    return_context = s;
    00129
    00130    if(return_context != NULL) {
    00131       /* set the return context. Code borrowed from the Goto builtin */
    00132
    00133       working = return_context;
    00134       context = strsep(&working, "|");
    00135       exten = strsep(&working, "|");
    00136       if(!exten) {
    00137          /* Only a priority in this one */
    00138          priority = context;
    00139          exten = NULL;
    00140          context = NULL;
    00141       } else {
    00142          priority = strsep(&working, "|");
    00143          if(!priority) {
    00144             /* Only an extension and priority in this one */
    00145             priority = exten;
    00146             exten = context;
    00147             context = NULL;
    00148       }
    00149    }
    00150    if(atoi(priority) < 0) {
    00151       ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
    00152       free(orig_s);
    00153       LOCAL_USER_REMOVE(u);
    00154       return -1;
    00155    }
    00156    /* At this point we have a priority and maybe an extension and a context */
    00157    chan->priority = atoi(priority);
    00158    if(exten && strcasecmp(exten, "BYEXTENSION"))
    00159       strncpy(chan->exten, exten, sizeof(chan->exten)-1);
    00160    if(context)
    00161       strncpy(chan->context, context, sizeof(chan->context)-1);
    00162    } else {  /* increment the priority by default*/
    00163       chan->priority++;
    00164    }
    00165
    00166    if(option_verbose > 2) {
    00167       ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
    00168       if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
    00169          ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
    00170       }
    00171    }
    00172
    00173    /* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
    00174    before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
    00175
    00176    ast_masq_park_call(chan, NULL, timeout, &lot);
    00177
    00178    res=-1;
    00179
    00180    ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
    00181
    00182    /* Now place the call to the extention */
    00183
    00184    memset(&oh, 0, sizeof(oh));
    00185    oh.parent_channel = chan;
    00186    dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
    00187
    00188    if(dchan) {
    00189       if(dchan->_state == AST_STATE_UP) {
    00190          if(option_verbose > 3)
    00191             ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
    00192       } else {
    00193          if(option_verbose > 3)
    00194             ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
    00195                ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
    00196          ast_hangup(dchan);
    00197          free(orig_s);
    00198          LOCAL_USER_REMOVE(u);
    00199          return -1;
    00200       }
    00201    } else {
    00202       ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
    00203       free(orig_s);
    00204       LOCAL_USER_REMOVE(u);
    00205       return -1;
    00206    }
    00207
    00208    ast_stopstream(dchan);
    00209
    00210    /* now we have the call placed and are ready to play stuff to it */
    00211
    00212    ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
    00213
    00214    tpl_working = template;
    00215    tpl_current=strsep(&tpl_working, ":");
    00216
    00217    while(tpl_current && looptemp < sizeof(tmp)) {
    00218       tmp[looptemp]=tpl_current;
    00219       looptemp++;
    00220       tpl_current=strsep(&tpl_working,":");
    00221    }
    00222
    00223    for(i=0; i<looptemp; i++) {
    00224       ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
    00225       if(!strcmp(tmp[i], "PARKED")) {
    00226          ast_say_digits(dchan, lot, "", dchan->language);
    00227       } else {
    00228          dres = ast_streamfile(dchan, tmp[i], dchan->language);
    00229          if(!dres) {
    00230             dres = ast_waitstream(dchan, "");
    00231          } else {
    00232             ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
    00233             dres = 0;
    00234          }
    00235       }
    00236    }
    00237
    00238    ast_stopstream(dchan);
    00239    ast_hangup(dchan);
    00240    free(orig_s);
    00241
    00242    LOCAL_USER_REMOVE(u);
    00243
    00244    return res;
    00245 }
    00246
    00247
    00248
    00249 int unload_module(void)
    00250 {
    00251    int res;
    00252
    00253    res = ast_unregister_application(app);
    00254
    00255    STANDARD_HANGUP_LOCALUSERS;
    00256
    00257    return res;
    00258 }
    00259
    00260 int load_module(void)
    00261 {
    00262    /* return ast_register_application(app, park_exec); */
    00263    return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
    00264 }
    00265
    00266 char *description(void)
    00267 {
    00268    return tdesc;
    00269 }
    00270
    00271 int usecount(void)
    00272 {
    00273    int res;
    00274    STANDARD_USECOUNT(res);
    00275    return res;
    00276 }
    00277
    00278 char *key()
    00279 {
    00280    return ASTERISK_GPL_KEY;
    00281 }