Sat Nov 25 00:45:28 2006

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 }

Generated on Sat Nov 25 00:45:28 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6