Mon Mar 12 2012 21:18:38

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: 348310 $")
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    struct ast_party_id caller_id;
00100 
00101    struct ast_channel *dchan;
00102    struct outgoing_helper oh = { 0, };
00103    int outstate;
00104    AST_DECLARE_APP_ARGS(args,
00105       AST_APP_ARG(template);
00106       AST_APP_ARG(timeout);
00107       AST_APP_ARG(dial);
00108       AST_APP_ARG(return_context);
00109    );
00110    if (ast_strlen_zero(data)) {
00111       ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce_template,timeout,dial,[return_context])\n");
00112       return -1;
00113    }
00114   
00115    s = ast_strdupa(data);
00116    AST_STANDARD_APP_ARGS(args, s);
00117 
00118    if (args.timeout)
00119       timeout = atoi(args.timeout) * 1000;
00120 
00121    if (ast_strlen_zero(args.dial)) {
00122       ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or DAHDI/g1/5551212\n");
00123       return -1;
00124    }
00125 
00126    dialtech = strsep(&args.dial, "/");
00127    ast_verb(3, "Dial Tech,String: (%s,%s)\n", dialtech, args.dial);
00128 
00129    if (!ast_strlen_zero(args.return_context)) {
00130       ast_clear_flag(chan, AST_FLAG_IN_AUTOLOOP);
00131       ast_parseable_goto(chan, args.return_context);
00132    }
00133 
00134    ast_verb(3, "Return Context: (%s,%s,%d) ID: %s\n", chan->context, chan->exten,
00135       chan->priority,
00136       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
00137    if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
00138       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
00139       ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n");
00140    }
00141 
00142    /* Save the CallerID because the masquerade turns chan into a ZOMBIE. */
00143    ast_channel_lock(chan);
00144    ast_party_id_copy(&caller_id, &chan->caller.id);
00145    ast_channel_unlock(chan);
00146 
00147    /* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
00148    before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
00149 
00150    res = ast_masq_park_call(chan, NULL, timeout, &lot);
00151    if (res) {
00152       /* Parking failed. */
00153       ast_party_id_free(&caller_id);
00154       return -1;
00155    }
00156 
00157    ast_verb(3, "Call parked in space: %d, timeout: %d, return-context: %s\n",
00158       lot, timeout, args.return_context ? args.return_context : "");
00159 
00160    /* Now place the call to the extension */
00161 
00162    snprintf(buf, sizeof(buf), "%d", lot);
00163    oh.parent_channel = chan;
00164    oh.vars = ast_variable_new("_PARKEDAT", buf, "");
00165    dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, chan, args.dial, 30000,
00166       &outstate,
00167       S_COR(caller_id.number.valid, caller_id.number.str, NULL),
00168       S_COR(caller_id.name.valid, caller_id.name.str, NULL),
00169       &oh);
00170    ast_variables_destroy(oh.vars);
00171    ast_party_id_free(&caller_id);
00172    if (dchan) {
00173       if (dchan->_state == AST_STATE_UP) {
00174          ast_verb(4, "Channel %s was answered.\n", dchan->name);
00175       } else {
00176          ast_verb(4, "Channel %s was never answered.\n", dchan->name);
00177          ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
00178          ast_hangup(dchan);
00179          return -1;
00180       }
00181    } else {
00182       ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
00183       return -1; 
00184    }
00185 
00186    ast_stopstream(dchan);
00187 
00188    /* now we have the call placed and are ready to play stuff to it */
00189 
00190    ast_verb(4, "Announce Template:%s\n", args.template);
00191 
00192    for (looptemp = 0; looptemp < ARRAY_LEN(tmp); looptemp++) {
00193       if ((tmp[looptemp] = strsep(&args.template, ":")) != NULL)
00194          continue;
00195       else
00196          break;
00197    }
00198 
00199    for (i = 0; i < looptemp; i++) {
00200       ast_verb(4, "Announce:%s\n", tmp[i]);
00201       if (!strcmp(tmp[i], "PARKED")) {
00202          ast_say_digits(dchan, lot, "", dchan->language);
00203       } else {
00204          dres = ast_streamfile(dchan, tmp[i], dchan->language);
00205          if (!dres) {
00206             dres = ast_waitstream(dchan, "");
00207          } else {
00208             ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
00209          }
00210       }
00211    }
00212 
00213    ast_stopstream(dchan);  
00214    ast_hangup(dchan);
00215    
00216    return res;
00217 }
00218 
00219 static int unload_module(void)
00220 {
00221    return ast_unregister_application(app);
00222 }
00223 
00224 static int load_module(void)
00225 {
00226    /* return ast_register_application(app, park_exec); */
00227    return ast_register_application_xml(app, parkandannounce_exec);
00228 }
00229 
00230 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Parking and Announce Application");