Sun Oct 16 2011 08:41:28

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