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 #include "asterisk.h"
00029
00030 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 180032 $")
00031
00032 #include "asterisk/file.h"
00033 #include "asterisk/pbx.h"
00034 #include "asterisk/channel.h"
00035 #include "asterisk/app.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/indications.h"
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 enum {
00112 OPT_SKIP = (1 << 0),
00113 OPT_INDICATION = (1 << 1),
00114 OPT_NOANSWER = (1 << 2),
00115 } read_option_flags;
00116
00117 AST_APP_OPTIONS(read_app_options, {
00118 AST_APP_OPTION('s', OPT_SKIP),
00119 AST_APP_OPTION('i', OPT_INDICATION),
00120 AST_APP_OPTION('n', OPT_NOANSWER),
00121 });
00122
00123 static char *app = "Read";
00124
00125 #define ast_next_data(instr,ptr,delim) if((ptr=strchr(instr,delim))) { *(ptr) = '\0' ; ptr++;}
00126
00127 static int read_exec(struct ast_channel *chan, void *data)
00128 {
00129 int res = 0;
00130 char tmp[256] = "";
00131 int maxdigits = 255;
00132 int tries = 1, to = 0, x = 0;
00133 double tosec;
00134 char *argcopy = NULL;
00135 struct ast_tone_zone_sound *ts = NULL;
00136 struct ast_flags flags = {0};
00137 const char *status = "ERROR";
00138
00139 AST_DECLARE_APP_ARGS(arglist,
00140 AST_APP_ARG(variable);
00141 AST_APP_ARG(filename);
00142 AST_APP_ARG(maxdigits);
00143 AST_APP_ARG(options);
00144 AST_APP_ARG(attempts);
00145 AST_APP_ARG(timeout);
00146 );
00147
00148 pbx_builtin_setvar_helper(chan, "READSTATUS", status);
00149 if (ast_strlen_zero(data)) {
00150 ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
00151 return 0;
00152 }
00153
00154 argcopy = ast_strdupa(data);
00155
00156 AST_STANDARD_APP_ARGS(arglist, argcopy);
00157
00158 if (!ast_strlen_zero(arglist.options)) {
00159 ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
00160 }
00161
00162 if (!ast_strlen_zero(arglist.attempts)) {
00163 tries = atoi(arglist.attempts);
00164 if (tries <= 0)
00165 tries = 1;
00166 }
00167
00168 if (!ast_strlen_zero(arglist.timeout)) {
00169 tosec = atof(arglist.timeout);
00170 if (tosec <= 0)
00171 to = 0;
00172 else
00173 to = tosec * 1000.0;
00174 }
00175
00176 if (ast_strlen_zero(arglist.filename)) {
00177 arglist.filename = NULL;
00178 }
00179 if (!ast_strlen_zero(arglist.maxdigits)) {
00180 maxdigits = atoi(arglist.maxdigits);
00181 if ((maxdigits < 1) || (maxdigits > 255)) {
00182 maxdigits = 255;
00183 } else
00184 ast_verb(3, "Accepting a maximum of %d digits.\n", maxdigits);
00185 }
00186 if (ast_strlen_zero(arglist.variable)) {
00187 ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[,filename][,maxdigits][,option][,attempts][,timeout])\n\n");
00188 return 0;
00189 }
00190 if (ast_test_flag(&flags, OPT_INDICATION)) {
00191 if (!ast_strlen_zero(arglist.filename)) {
00192 ts = ast_get_indication_tone(chan->zone, arglist.filename);
00193 }
00194 }
00195 if (chan->_state != AST_STATE_UP) {
00196 if (ast_test_flag(&flags, OPT_SKIP)) {
00197
00198 pbx_builtin_setvar_helper(chan, arglist.variable, "");
00199 pbx_builtin_setvar_helper(chan, "READSTATUS", "SKIPPED");
00200 return 0;
00201 } else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
00202
00203 res = ast_answer(chan);
00204 }
00205 }
00206 if (!res) {
00207 while (tries && !res) {
00208 ast_stopstream(chan);
00209 if (ts && ts->data[0]) {
00210 if (!to)
00211 to = chan->pbx ? chan->pbx->rtimeoutms : 6000;
00212 res = ast_playtones_start(chan, 0, ts->data, 0);
00213 for (x = 0; x < maxdigits; ) {
00214 res = ast_waitfordigit(chan, to);
00215 ast_playtones_stop(chan);
00216 if (res < 1) {
00217 if (res == 0)
00218 status = "TIMEOUT";
00219 tmp[x]='\0';
00220 break;
00221 }
00222 tmp[x++] = res;
00223 if (tmp[x-1] == '#') {
00224 tmp[x-1] = '\0';
00225 status = "OK";
00226 break;
00227 }
00228 if (x >= maxdigits) {
00229 status = "OK";
00230 }
00231 }
00232 } else {
00233 res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
00234 if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED)
00235 status = "OK";
00236 else if (res == AST_GETDATA_TIMEOUT)
00237 status = "TIMEOUT";
00238 else if (res == AST_GETDATA_INTERRUPTED)
00239 status = "INTERRUPTED";
00240 }
00241 if (res > -1) {
00242 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00243 if (!ast_strlen_zero(tmp)) {
00244 ast_verb(3, "User entered '%s'\n", tmp);
00245 tries = 0;
00246 } else {
00247 tries--;
00248 if (tries)
00249 ast_verb(3, "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
00250 else
00251 ast_verb(3, "User entered nothing.\n");
00252 }
00253 res = 0;
00254 } else {
00255 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00256 ast_verb(3, "User disconnected\n");
00257 }
00258 }
00259 }
00260
00261 if (ts) {
00262 ts = ast_tone_zone_sound_unref(ts);
00263 }
00264
00265 if (ast_check_hangup(chan))
00266 status = "HANGUP";
00267 pbx_builtin_setvar_helper(chan, "READSTATUS", status);
00268 return 0;
00269 }
00270
00271 static int unload_module(void)
00272 {
00273 return ast_unregister_application(app);
00274 }
00275
00276 static int load_module(void)
00277 {
00278 return ast_register_application_xml(app, read_exec);
00279 }
00280
00281 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read Variable Application");