Thu Apr 28 2011 16:56:40

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: 170047 $")
00035 
00036 #include "asterisk/file.h"
00037 #include "asterisk/channel.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/features.h"
00041 #include "asterisk/say.h"
00042 #include "asterisk/lock.h"
00043 #include "asterisk/utils.h"
00044 #include "asterisk/app.h"
00045 
00046 /*** DOCUMENTATION
00047    <application name="ParkAndAnnounce" language="en_US">
00048       <synopsis>
00049          Park and Announce.
00050       </synopsis>
00051       <syntax>
00052          <parameter name="announce_template" required="true" argsep=":">
00053             <argument name="announce" required="true">
00054                <para>Colon-separated list of files to announce. The word
00055                <literal>PARKED</literal> will be replaced by a say_digits of the extension in which
00056                the call is parked.</para>
00057             </argument>
00058             <argument name="announce1" multiple="true" />
00059          </parameter>
00060          <parameter name="timeout" required="true">
00061             <para>Time in seconds before the call returns into the return
00062             context.</para>
00063          </parameter>
00064          <parameter name="dial" required="true">
00065             <para>The app_dial style resource to call to make the
00066             announcement. Console/dsp calls the console.</para>
00067          </parameter>
00068          <parameter name="return_context">
00069             <para>The goto-style label to jump the call back into after
00070             timeout. Default <literal>priority+1</literal>.</para>
00071          </parameter>
00072       </syntax>
00073       <description>
00074          <para>Park a call into the parkinglot and announce the call to another channel.</para>
00075          <para>The variable <variable>PARKEDAT</variable> will contain the parking extension
00076          into which the call was placed.  Use with the Local channel to allow the dialplan to make
00077          use of this information.</para>
00078       </description>
00079       <see-also>
00080          <ref type="application">Park</ref>
00081          <ref type="application">ParkedCall</ref>
00082       </see-also>
00083    </application>
00084  ***/
00085 
00086 static char *app = "ParkAndAnnounce";
00087 
00088 static int parkandannounce_exec(struct ast_channel *chan, void *data)
00089 {
00090    int res = -1;
00091    int lot, timeout = 0, dres;
00092    char *dialtech, *tmp[100], buf[13];
00093    int looptemp, i;
00094    char *s;
00095 
00096    struct ast_channel *dchan;
00097    struct outgoing_helper oh = { 0, };
00098    int outstate;
00099    AST_DECLARE_APP_ARGS(args,
00100       AST_APP_ARG(template);
00101       AST_APP_ARG(timeout);
00102       AST_APP_ARG(dial);
00103       AST_APP_ARG(return_context);
00104    );
00105    if (ast_strlen_zero(data)) {
00106       ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
00107       return -1;
00108    }
00109   
00110    s = ast_strdupa(data);
00111    AST_STANDARD_APP_ARGS(args, s);
00112 
00113    if (args.timeout)
00114       timeout = atoi(args.timeout) * 1000;
00115 
00116    if (ast_strlen_zero(args.dial)) {
00117       ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or DAHDI/g1/5551212\n");
00118       return -1;
00119    }
00120 
00121    dialtech = strsep(&args.dial, "/");
00122    ast_verb(3, "Dial Tech,String: (%s,%s)\n", dialtech, args.dial);
00123 
00124    if (!ast_strlen_zero(args.return_context)) {
00125       ast_clear_flag(chan, AST_FLAG_IN_AUTOLOOP);
00126       ast_parseable_goto(chan, args.return_context);
00127    }
00128 
00129    ast_verb(3, "Return Context: (%s,%s,%d) ID: %s\n", chan->context, chan->exten, chan->priority, chan->cid.cid_num);
00130       if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
00131       ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n");
00132       }
00133 
00134    /* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
00135    before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
00136 
00137    res = ast_masq_park_call(chan, NULL, timeout, &lot);
00138    if (res == -1)
00139       return res;
00140 
00141    ast_verb(3, "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, args.return_context);
00142 
00143    /* Now place the call to the extension */
00144 
00145    snprintf(buf, sizeof(buf), "%d", lot);
00146    oh.parent_channel = chan;
00147    oh.vars = ast_variable_new("_PARKEDAT", buf, "");
00148    dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, args.dial, 30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
00149 
00150    if (dchan) {
00151       if (dchan->_state == AST_STATE_UP) {
00152          ast_verb(4, "Channel %s was answered.\n", dchan->name);
00153       } else {
00154          ast_verb(4, "Channel %s was never answered.\n", dchan->name);
00155          ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
00156          ast_hangup(dchan);
00157          return -1;
00158       }
00159    } else {
00160       ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
00161       return -1; 
00162    }
00163 
00164    ast_stopstream(dchan);
00165 
00166    /* now we have the call placed and are ready to play stuff to it */
00167 
00168    ast_verb(4, "Announce Template:%s\n", args.template);
00169 
00170    for (looptemp = 0; looptemp < ARRAY_LEN(tmp); looptemp++) {
00171       if ((tmp[looptemp] = strsep(&args.template, ":")) != NULL)
00172          continue;
00173       else
00174          break;
00175    }
00176 
00177    for (i = 0; i < looptemp; i++) {
00178       ast_verb(4, "Announce:%s\n", tmp[i]);
00179       if (!strcmp(tmp[i], "PARKED")) {
00180          ast_say_digits(dchan, lot, "", dchan->language);
00181       } else {
00182          dres = ast_streamfile(dchan, tmp[i], dchan->language);
00183          if (!dres) {
00184             dres = ast_waitstream(dchan, "");
00185          } else {
00186             ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
00187             dres = 0;
00188          }
00189       }
00190    }
00191 
00192    ast_stopstream(dchan);  
00193    ast_hangup(dchan);
00194    
00195    return res;
00196 }
00197 
00198 static int unload_module(void)
00199 {
00200    return ast_unregister_application(app);
00201 }
00202 
00203 static int load_module(void)
00204 {
00205    /* return ast_register_application(app, park_exec); */
00206    return ast_register_application_xml(app, parkandannounce_exec);
00207 }
00208 
00209 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Parking and Announce Application");