00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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 int res=0;
00080 char *return_context;
00081 int lot, timeout = 0, dres;
00082 char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
00083 char *template, *tpl_working, *tpl_current;
00084 char *tmp[100];
00085 char buf[13];
00086 int looptemp=0,i=0;
00087 char *s;
00088
00089 struct ast_channel *dchan;
00090 struct outgoing_helper oh;
00091 int outstate;
00092
00093 struct ast_module_user *u;
00094
00095 if (ast_strlen_zero(data)) {
00096 ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
00097 return -1;
00098 }
00099
00100 u = ast_module_user_add(chan);
00101
00102 s = ast_strdupa(data);
00103
00104 template=strsep(&s,"|");
00105 if(! template) {
00106 ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
00107 ast_module_user_remove(u);
00108 return -1;
00109 }
00110
00111 if(s) {
00112 timeout = atoi(strsep(&s, "|"));
00113 timeout *= 1000;
00114 }
00115 dial=strsep(&s, "|");
00116 if(!dial) {
00117 ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
00118 ast_module_user_remove(u);
00119 return -1;
00120 } else {
00121 dialtech=strsep(&dial, "/");
00122 dialstr=dial;
00123 ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
00124 }
00125
00126 return_context = s;
00127
00128 if(return_context != NULL) {
00129
00130
00131 working = return_context;
00132 context = strsep(&working, "|");
00133 exten = strsep(&working, "|");
00134 if(!exten) {
00135
00136 priority = context;
00137 exten = NULL;
00138 context = NULL;
00139 } else {
00140 priority = strsep(&working, "|");
00141 if(!priority) {
00142
00143 priority = exten;
00144 exten = context;
00145 context = NULL;
00146 }
00147 }
00148 if(atoi(priority) < 0) {
00149 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
00150 ast_module_user_remove(u);
00151 return -1;
00152 }
00153
00154 chan->priority = atoi(priority);
00155 if (exten)
00156 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
00157 if (context)
00158 ast_copy_string(chan->context, context, sizeof(chan->context));
00159 } else {
00160 chan->priority++;
00161 }
00162
00163 if(option_verbose > 2) {
00164 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
00165 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
00166 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
00167 }
00168 }
00169
00170
00171
00172
00173 ast_masq_park_call(chan, NULL, timeout, &lot);
00174
00175 res=-1;
00176
00177 ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
00178
00179
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
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 < sizeof(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 ast_module_user_remove(u);
00239
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
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");