Index: apps/app_read.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_read.c,v retrieving revision 1.7 diff -u -r1.7 app_read.c --- apps/app_read.c 22 Jun 2004 19:32:52 -0000 1.7 +++ apps/app_read.c 30 Jun 2004 16:37:44 -0000 @@ -31,13 +31,17 @@ static char *synopsis = "Read a variable"; static char *descrip = -" Read(variable[|filename][|maxdigits]): Reads a #-terminated string of digits from\n" -"the user, optionally playing a given filename first. Returns -1 on hangup or\n" -"error and 0 otherwise.\n" -" maxdigits -- maximum acceptable number of digits. Stops reading after maxdigits\n" -" have been entered (without requiring the user press the '#' key).\n" -" Defaults to 0 - no limit - wait for the user press the '#' key.\n" -" Any value below 0 means the same. Max accepted value is 255.\n"; +" Read(variable[|filename][|maxdigits][|option])\n\n" +"Reads a #-terminated string of digits from the user in to the given variable,\n" +"optionally playing a given filename first.\n" +" maxdigits -- maximum acceptable number of digits. Stops reading after\n" +" maxdigits have been entered (without requiring the user to\n" +" press the '#' key).\n" +" Defaults to 0 - no limit - wait for the user press the '#' key.\n" +" Any value below 0 means the same. Max accepted value is 255.\n" +" option -- may be 'skip' to return immediately if the line is not up,\n" +" or 'noanswer' to read digits even if the line is not up.\n\n" +"Returns -1 on hangup or error and 0 otherwise.\n"; STANDARD_LOCAL_USER; @@ -48,21 +52,29 @@ int res = 0; struct localuser *u; char tmp[256]; + char argdata[256] = ""; char *varname; char *filename; char *stringp; char *maxdigitstr; + char *options; + int option_skip = 0; + int option_noanswer = 0; int maxdigits=255; if (!data || ast_strlen_zero((char *)data)) { ast_log(LOG_WARNING, "Read requires an argument (variable)\n"); return -1; } - strncpy(tmp, (char *)data, sizeof(tmp)-1); - stringp=(char *)calloc(1,strlen(tmp)+1); - snprintf(stringp,strlen(tmp)+1,"%s",tmp); + strncpy(argdata, (char *)data, sizeof(argdata)-1); + stringp=argdata; varname = strsep(&stringp, "|"); filename = strsep(&stringp, "|"); maxdigitstr = strsep(&stringp,"|"); + options = strsep(&stringp, "|"); + if (options && !strcasecmp(options, "skip")) + option_skip = 1; + if (options && !strcasecmp(options, "noanswer")) + option_noanswer = 1; if (!(filename) || ast_strlen_zero(filename)) filename = NULL; if (maxdigitstr) { @@ -78,10 +90,16 @@ } LOCAL_USER_ADD(u); if (chan->_state != AST_STATE_UP) { - /* Answer if the line isn't up. */ - res = ast_answer(chan); + if (option_skip) { + /* At the user's option, skip if the line is not up */ + pbx_builtin_setvar_helper(chan, varname, "\0"); + LOCAL_USER_REMOVE(u); + return 0; + } else if (!option_noanswer) { + /* Otherwise answer unless we're supposed to read while on-hook */ + res = ast_answer(chan); + } } - strncpy(tmp, (char *)varname, sizeof(tmp)-1); if (!res) { ast_stopstream(chan); res = ast_app_getdata(chan, filename, tmp, maxdigits, 0); Index: apps/app_record.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_record.c,v retrieving revision 1.18 diff -u -r1.18 app_record.c --- apps/app_record.c 22 Jun 2004 19:32:52 -0000 1.18 +++ apps/app_record.c 30 Jun 2004 16:37:44 -0000 @@ -29,10 +29,15 @@ static char *synopsis = "Record to a file"; static char *descrip = -" Record(filename:format|silence): Records from the channel into a given\n" -"filename. If the file exists it will be overwritten. \n" +" Record(filename:format|silence[|maxduration][|option])\n\n" +"Records from the channel into a given filename. If the file exists it will\n" +"be overwritten.\n" "- 'format' is the format of the file type to be recorded (wav, gsm, etc).\n" -"- 'silence' is the number of seconds of silence to allow before returning.\n\n" +"- 'silence' is the number of seconds of silence to allow before returning.\n" +"- 'maxduration' is the maximum recording duration in seconds. If missing\n" +"or 0 there is no maximum.\n" +"- 'option' may be 'skip' to return immediately if the line is not up,\n" +"or 'noanswer' to attempt to record even if the line is not up.\n\n" "If filename contains '%d', these characters will be replaced with a number\n" "incremented by one each time the file is recorded. \n\n" "Formats: g723, g729, gsm, h263, ulaw, alaw, vox, wav, WAV\n\n" @@ -65,7 +70,13 @@ int silence = 0; /* amount of silence to allow */ int gotsilence = 0; /* did we timeout for silence? */ char silencestr[5]; - int k = 0; + char durationstr[8]; + int maxduration = 0; /* max duration of recording */ + int gottimeout = 0; /* did we timeout for maxduration exceeded? */ + time_t timeout = 0; + char option[16]; + int option_skip = 0; + int option_noanswer = 0; int rfmt = 0; vdata = data; /* explained above */ @@ -80,50 +91,90 @@ if ((vdata[i] == '%') && (vdata[i+1] == 'd')) { percentflag = 1; /* the wildcard is used */ } - - if (i == strlen(vdata) ) { - ast_log(LOG_WARNING, "No extension found\n"); - return -1; - } - fil[i] = vdata[i]; + if (j < sizeof(fil) - 1) + fil[j++] = vdata[i]; + } + fil[j] = '\0'; + + if (vdata[i] != ':') { + ast_log(LOG_WARNING, "No extension found\n"); + return -1; } - fil[i++] = '\0'; + i++; - for (; j < 10 && i < strlen(data) && (vdata[i] != '|'); i++, j++) - ext[j] = vdata[i]; + j = 0; + for (; vdata[i] && (vdata[i] != '|'); i++) + if (j < sizeof(ext) - 1) + ext[j++] = vdata[i]; ext[j] = '\0'; - if (vdata[i] && (vdata[i] == '|')) i++; - for (; vdata[i] && (vdata[i] != '|') && (k < 3) && i < strlen(data); i++, k++) - silencestr[k] = vdata[i]; - silencestr[k] = '\0'; + if (vdata[i] == '|') + i++; - if (silencestr) { + j = 0; + for (; vdata[i] && (vdata[i] != '|'); i++) + if (j < sizeof(silencestr) - 1) + silencestr[j++] = vdata[i]; + silencestr[j] = '\0'; + + if (j > 0) { silence = atoi(silencestr); if (silence > 0) silence *= 1000; } + if (vdata[i] == '|') + i++; + + j = 0; + for (; vdata[i] && (vdata[i] != '|'); i++) + if (j < sizeof(durationstr) - 1) + durationstr[j++] = vdata[i]; + durationstr[j] = '\0'; + + if (j > 0) + maxduration = atoi(durationstr); + + if (vdata[i] == '|') + i++; + + j = 0; + for (; vdata[i] && (vdata[i] != '|'); i++) + if (j < sizeof(option) - 1) + option[j++] = vdata[i]; + option[j] = '\0'; + + if (!strcasecmp(option, "skip")) + option_skip = 1; + if (!strcasecmp(option, "noanswer")) + option_noanswer = 1; + /* done parsing */ - + /* these are to allow the use of the %d in the config file for a wild card of sort to create a new file with the inputed name scheme */ if (percentflag) { do { - snprintf(tmp, 256, fil, count); + snprintf(tmp, sizeof(tmp)-1, fil, count); count++; } while ( ast_fileexists(tmp, ext, chan->language) != -1 ); pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp); } else - strncpy(tmp, fil, 256-1); + strncpy(tmp, fil, sizeof(tmp)-1); /* end of routine mentioned */ LOCAL_USER_ADD(u); if (chan->_state != AST_STATE_UP) { - res = ast_answer(chan); /* Shouldn't need this, but checking to see if channel is already answered - * Theoretically asterisk should already have answered before running the app */ + if (option_skip) { + /* At the user's option, skip if the line is not up */ + LOCAL_USER_REMOVE(u); + return 0; + } else if (!option_noanswer) { + /* Otherwise answer unless we're supposed to record while on-hook */ + res = ast_answer(chan); + } } if (!res) { @@ -157,7 +208,15 @@ s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644); if (s) { + if (maxduration > 0) + timeout = time(NULL) + (time_t)maxduration; + while (ast_waitfor(chan, -1) > -1) { + if (maxduration > 0 && time(NULL) > timeout) { + gottimeout = 1; + break; + } + f = ast_read(chan); if (!f) { res = -1; @@ -210,7 +269,7 @@ if (gotsilence) { ast_stream_rewind(s, silence-1000); ast_truncstream(s); - } else { + } else if (!gottimeout) { /* Strip off the last 1/4 second of it */ ast_stream_rewind(s, 250); ast_truncstream(s);