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: 328209 $")
00035
00036 #include "asterisk/file.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/app.h"
00040 #include "asterisk/module.h"
00041 #include "asterisk/indications.h"
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
00112
00113
00114
00115 enum read_option_flags {
00116 OPT_SKIP = (1 << 0),
00117 OPT_INDICATION = (1 << 1),
00118 OPT_NOANSWER = (1 << 2),
00119 };
00120
00121 AST_APP_OPTIONS(read_app_options, {
00122 AST_APP_OPTION('s', OPT_SKIP),
00123 AST_APP_OPTION('i', OPT_INDICATION),
00124 AST_APP_OPTION('n', OPT_NOANSWER),
00125 });
00126
00127 static char *app = "Read";
00128
00129 static int read_exec(struct ast_channel *chan, const char *data)
00130 {
00131 int res = 0;
00132 char tmp[256] = "";
00133 int maxdigits = 255;
00134 int tries = 1, to = 0, x = 0;
00135 double tosec;
00136 char *argcopy = NULL;
00137 struct ast_tone_zone_sound *ts = NULL;
00138 struct ast_flags flags = {0};
00139 const char *status = "ERROR";
00140
00141 AST_DECLARE_APP_ARGS(arglist,
00142 AST_APP_ARG(variable);
00143 AST_APP_ARG(filename);
00144 AST_APP_ARG(maxdigits);
00145 AST_APP_ARG(options);
00146 AST_APP_ARG(attempts);
00147 AST_APP_ARG(timeout);
00148 );
00149
00150 pbx_builtin_setvar_helper(chan, "READSTATUS", status);
00151 if (ast_strlen_zero(data)) {
00152 ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
00153 return 0;
00154 }
00155
00156 argcopy = ast_strdupa(data);
00157
00158 AST_STANDARD_APP_ARGS(arglist, argcopy);
00159
00160 if (!ast_strlen_zero(arglist.options)) {
00161 ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
00162 }
00163
00164 if (!ast_strlen_zero(arglist.attempts)) {
00165 tries = atoi(arglist.attempts);
00166 if (tries <= 0)
00167 tries = 1;
00168 }
00169
00170 if (!ast_strlen_zero(arglist.timeout)) {
00171 tosec = atof(arglist.timeout);
00172 if (tosec <= 0)
00173 to = 0;
00174 else
00175 to = tosec * 1000.0;
00176 }
00177
00178 if (ast_strlen_zero(arglist.filename)) {
00179 arglist.filename = NULL;
00180 }
00181 if (!ast_strlen_zero(arglist.maxdigits)) {
00182 maxdigits = atoi(arglist.maxdigits);
00183 if ((maxdigits < 1) || (maxdigits > 255)) {
00184 maxdigits = 255;
00185 } else
00186 ast_verb(3, "Accepting a maximum of %d digits.\n", maxdigits);
00187 }
00188 if (ast_strlen_zero(arglist.variable)) {
00189 ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[,filename][,maxdigits][,option][,attempts][,timeout])\n\n");
00190 return 0;
00191 }
00192 if (ast_test_flag(&flags, OPT_INDICATION)) {
00193 if (!ast_strlen_zero(arglist.filename)) {
00194 ts = ast_get_indication_tone(chan->zone, arglist.filename);
00195 }
00196 }
00197 if (chan->_state != AST_STATE_UP) {
00198 if (ast_test_flag(&flags, OPT_SKIP)) {
00199
00200 pbx_builtin_setvar_helper(chan, arglist.variable, "");
00201 pbx_builtin_setvar_helper(chan, "READSTATUS", "SKIPPED");
00202 return 0;
00203 } else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
00204
00205 res = ast_answer(chan);
00206 }
00207 }
00208 if (!res) {
00209 while (tries && !res) {
00210 ast_stopstream(chan);
00211 if (ts && ts->data[0]) {
00212 if (!to)
00213 to = chan->pbx ? chan->pbx->rtimeoutms : 6000;
00214 res = ast_playtones_start(chan, 0, ts->data, 0);
00215 for (x = 0; x < maxdigits; ) {
00216 res = ast_waitfordigit(chan, to);
00217 ast_playtones_stop(chan);
00218 if (res < 1) {
00219 if (res == 0)
00220 status = "TIMEOUT";
00221 tmp[x]='\0';
00222 break;
00223 }
00224 tmp[x++] = res;
00225 if (tmp[x-1] == '#') {
00226 tmp[x-1] = '\0';
00227 status = "OK";
00228 break;
00229 }
00230 if (x >= maxdigits) {
00231 status = "OK";
00232 }
00233 }
00234 } else {
00235 res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
00236 if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED)
00237 status = "OK";
00238 else if (res == AST_GETDATA_TIMEOUT)
00239 status = "TIMEOUT";
00240 else if (res == AST_GETDATA_INTERRUPTED)
00241 status = "INTERRUPTED";
00242 }
00243 if (res > -1) {
00244 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00245 if (!ast_strlen_zero(tmp)) {
00246 ast_verb(3, "User entered '%s'\n", tmp);
00247 tries = 0;
00248 } else {
00249 tries--;
00250 if (tries)
00251 ast_verb(3, "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
00252 else
00253 ast_verb(3, "User entered nothing.\n");
00254 }
00255 res = 0;
00256 } else {
00257 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
00258 ast_verb(3, "User disconnected\n");
00259 }
00260 }
00261 }
00262
00263 if (ts) {
00264 ts = ast_tone_zone_sound_unref(ts);
00265 }
00266
00267 if (ast_check_hangup(chan))
00268 status = "HANGUP";
00269 pbx_builtin_setvar_helper(chan, "READSTATUS", status);
00270 return 0;
00271 }
00272
00273 static int unload_module(void)
00274 {
00275 return ast_unregister_application(app);
00276 }
00277
00278 static int load_module(void)
00279 {
00280 return ast_register_application_xml(app, read_exec);
00281 }
00282
00283 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read Variable Application");