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