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: 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
00129
00130 working = return_context;
00131 context = strsep(&working, "|");
00132 exten = strsep(&working, "|");
00133 if(!exten) {
00134
00135 priority = context;
00136 exten = NULL;
00137 context = NULL;
00138 } else {
00139 priority = strsep(&working, "|");
00140 if(!priority) {
00141
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
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 {
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
00170
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
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 < 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
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");