Sat Aug 6 00:39:20 2011

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 - 2006, 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  * \author Ben Miller <bgmiller@dccinc.com>
00027  * \arg With TONS of help from Mark!
00028  *
00029  * \ingroup applications
00030  */
00031 
00032 #include "asterisk.h"
00033 
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 251410 $")
00035 
00036 #include <stdlib.h>
00037 #include <stdio.h>
00038 #include <string.h>
00039 #include <unistd.h>
00040 #include <sys/types.h>
00041 
00042 #include "asterisk/file.h"
00043 #include "asterisk/logger.h"
00044 #include "asterisk/channel.h"
00045 #include "asterisk/pbx.h"
00046 #include "asterisk/module.h"
00047 #include "asterisk/features.h"
00048 #include "asterisk/options.h"
00049 #include "asterisk/logger.h"
00050 #include "asterisk/say.h"
00051 #include "asterisk/lock.h"
00052 #include "asterisk/utils.h"
00053 
00054 static char *app = "ParkAndAnnounce";
00055 
00056 static char *synopsis = "Park and Announce";
00057 
00058 static char *descrip =
00059 "  ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
00060 "Park a call into the parkinglot and announce the call to another channel.\n"
00061 "\n"
00062 "announce template: Colon-separated list of files to announce.  The word PARKED\n"
00063 "                   will be replaced by a say_digits of the extension in which\n"
00064 "                   the call is parked.\n"
00065 "timeout:           Time in seconds before the call returns into the return\n"
00066 "                   context.\n"
00067 "dial:              The app_dial style resource to call to make the\n"
00068 "                   announcement.  Console/dsp calls the console.\n"
00069 "return_context:    The goto-style label to jump the call back into after\n"
00070 "                   timeout.  Default <priority+1>.\n"
00071 "\n"
00072 "The variable ${PARKEDAT} will contain the parking extension into which the\n"
00073 "call was placed.  Use with the Local channel to allow the dialplan to make\n"
00074 "use of this information.\n";
00075 
00076 
00077 static int parkandannounce_exec(struct ast_channel *chan, void *data)
00078 {
00079    char *return_context;
00080    int lot, timeout = 0, dres;
00081    char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
00082    char *template, *tpl_working, *tpl_current;
00083    char *tmp[100];
00084    char buf[13];
00085    int looptemp = 0,i = 0, res = 0;
00086    char *s;
00087 
00088    struct ast_channel *dchan;
00089    struct outgoing_helper oh;
00090    int outstate;
00091 
00092    struct ast_module_user *u;
00093 
00094    if (ast_strlen_zero(data)) {
00095       ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
00096       return -1;
00097    }
00098   
00099    u = ast_module_user_add(chan);
00100 
00101    s = ast_strdupa(data);
00102 
00103    template = strsep(&s,"|");
00104    if(! template) {
00105       ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
00106       ast_module_user_remove(u);
00107       return -1;
00108    }
00109   
00110    if(s) {
00111       timeout = atoi(strsep(&s, "|"));
00112       timeout *= 1000;
00113    }
00114    dial = strsep(&s, "|");
00115    if (ast_strlen_zero(dial)) {
00116       ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
00117       ast_module_user_remove(u);
00118       return -1;
00119    } else {
00120       dialtech = strsep(&dial, "/");
00121       dialstr = dial;
00122       ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
00123    }
00124 
00125    return_context = s;
00126   
00127    if(return_context != NULL) {
00128       /* set the return context. Code borrowed from the Goto builtin */
00129     
00130       working = return_context;
00131       context = strsep(&working, "|");
00132       exten = strsep(&working, "|");
00133       if(!exten) {
00134          /* Only a priority in this one */
00135          priority = context;
00136          exten = NULL;
00137          context = NULL;
00138       } else {
00139          priority = strsep(&working, "|");
00140          if(!priority) {
00141             /* Only an extension and priority in this one */
00142             priority = exten;
00143             exten = context;
00144             context = NULL;
00145       }
00146    }
00147    if(atoi(priority) < 0) {
00148       ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
00149       ast_module_user_remove(u);
00150       return -1;
00151    }
00152    /* At this point we have a priority and maybe an extension and a context */
00153    chan->priority = atoi(priority);
00154    if (exten)
00155       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
00156    if (context)
00157       ast_copy_string(chan->context, context, sizeof(chan->context));
00158    } else {  /* increment the priority by default*/
00159       chan->priority++;
00160    }
00161 
00162    if(option_verbose > 2) {
00163       ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
00164       if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
00165          ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
00166       }
00167    }
00168   
00169    /* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
00170    before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
00171 
00172    res = ast_masq_park_call(chan, NULL, timeout, &lot);
00173    if (res == -1) {
00174       goto finish;
00175    }
00176 
00177    ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
00178 
00179    /* Now place the call to the extention */
00180 
00181    snprintf(buf, sizeof(buf), "%d", lot);
00182    memset(&oh, 0, sizeof(oh));
00183    oh.parent_channel = chan;
00184    oh.vars = ast_variable_new("_PARKEDAT", buf);
00185    dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
00186 
00187    if(dchan) {
00188       if(dchan->_state == AST_STATE_UP) {
00189          if(option_verbose > 3)
00190             ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
00191       } else {
00192          if(option_verbose > 3)
00193             ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
00194                ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
00195          ast_hangup(dchan);
00196          ast_module_user_remove(u);
00197          return -1;
00198       }
00199    } else {
00200       ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
00201       ast_module_user_remove(u);
00202       return -1; 
00203    }
00204 
00205    ast_stopstream(dchan);
00206 
00207    /* now we have the call placed and are ready to play stuff to it */
00208 
00209    ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
00210 
00211    tpl_working = template;
00212    tpl_current = strsep(&tpl_working, ":");
00213 
00214    while(tpl_current && looptemp < ARRAY_LEN(tmp)) {
00215       tmp[looptemp]=tpl_current;
00216       looptemp++;
00217       tpl_current = strsep(&tpl_working,":");
00218    }
00219 
00220    for(i = 0; i < looptemp; i++) {
00221       ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
00222       if(!strcmp(tmp[i], "PARKED")) {
00223          ast_say_digits(dchan, lot, "", dchan->language);
00224       } else {
00225          dres = ast_streamfile(dchan, tmp[i], dchan->language);
00226          if(!dres) {
00227             dres = ast_waitstream(dchan, "");
00228          } else {
00229             ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
00230             dres = 0;
00231          }
00232       }
00233    }
00234 
00235    ast_stopstream(dchan);  
00236    ast_hangup(dchan);
00237 
00238 finish:
00239    ast_module_user_remove(u);
00240    return res;
00241 }
00242 
00243 static int unload_module(void)
00244 {
00245    int res;
00246 
00247    res = ast_unregister_application(app);
00248 
00249    ast_module_user_hangup_all();
00250 
00251    return res;
00252 }
00253 
00254 static int load_module(void)
00255 {
00256    /* return ast_register_application(app, park_exec); */
00257    return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
00258 }
00259 
00260 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Parking and Announce Application");

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