Example #1
0
static int directory_exec(struct cw_channel *chan, int argc, char **argv)
{
	struct localuser *u;
	struct cw_config *cfg;
	char *context, *dialcontext, *dirintro;
	int res = 0;
	int last = 1;

	if (argc < 1 || argc > 3) {
		cw_log(LOG_ERROR, "Syntax: %s\n", directory_syntax);
		return -1;
	}

	LOCAL_USER_ADD(u);

	context = argv[0];
	dialcontext = (argc > 1 && argv[1][0] ? argv[1] : context);
	if (argc > 2 && strchr(argv[2], 'f'))
		last = 0;

	cfg = realtime_directory(context);
	if (!cfg) {
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	dirintro = cw_variable_retrieve(cfg, context, "directoryintro");
	if (cw_strlen_zero(dirintro))
		dirintro = cw_variable_retrieve(cfg, "general", "directoryintro");
	if (cw_strlen_zero(dirintro)) {
		if (last)
			dirintro = "dir-intro";	
		else
			dirintro = "dir-intro-fn";
	}
	
	for (;;) {
		if (!res)
			res = cw_streamfile(chan, dirintro, chan->language);
		if (!res)
			res = cw_waitstream(chan, CW_DIGIT_ANY);
		cw_stopstream(chan);
		if (!res)
			res = cw_waitfordigit(chan, 5000);
		if (res >0) {
			res = do_directory(chan, cfg, context, dialcontext, res, last);
			if (res > 0){
				res = cw_waitstream(chan, CW_DIGIT_ANY);
				cw_stopstream(chan);
				if (res >= 0) {
					continue;
				}
			}
		}
		break;
	}
	cw_config_destroy(cfg);
	LOCAL_USER_REMOVE(u);
	return res;
}
Example #2
0
static int conf_play_soundfile( struct cw_conf_member *member, char * file ) 
{
    int res = 0;

    if ( member->dont_play_any_sound ) 
	return 0;

    if ( !member->chan ) 
	return 0;

    cw_stopstream(member->chan);

    queue_incoming_silent_frame(member,3);

    if (
	    ( strrchr(file,'/')!=NULL ) || (cw_fileexists(file, NULL, member->chan->language) > 0) 
       )
    {
	res = cw_streamfile(member->chan, file, member->chan->language);
	if (!res) { 
	    res = cw_waitstream(member->chan, CW_DIGIT_ANY);	
	    cw_stopstream(member->chan);
	}
	//cw_log(LOG_DEBUG, "Soundfile found %s - %d\n", file, cw_fileexists(file, NULL,  member->chan->language) );
    } else 
	cw_log(LOG_DEBUG, "Soundfile not found %s - lang: %s\n", file, member->chan->language );


    cw_set_write_format( member->chan, CW_FORMAT_SLINEAR );

    return res;
}
Example #3
0
int cw_play_and_wait(struct cw_channel *chan, const char *fn)
{
	int d;
	d = cw_streamfile(chan, fn, chan->language);
	if (d)
		return d;
	d = cw_waitstream(chan, CW_DIGIT_ANY);
	cw_stopstream(chan);
	return d;
}
Example #4
0
int cw_app_getdata_full(struct cw_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
{
	int res,to,fto;
	if (prompt) {
		res = cw_streamfile(c, prompt, c->language);
		if (res < 0)
			return res;
	}
	fto = 6000;
	to = 2000;
	if (timeout > 0) 
		fto = to = timeout;
	if (timeout < 0) 
		fto = to = 1000000000;
	res = cw_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
	return res;
}
Example #5
0
int cw_app_getdata(struct cw_channel *c, char *prompt, char *s, int maxlen, int timeout)
{
	int res,to,fto;
	/* XXX Merge with full version? XXX */
	if (maxlen)
		s[0] = '\0';
	if (prompt) {
		res = cw_streamfile(c, prompt, c->language);
		if (res < 0)
			return res;
		}
	fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
	to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;

	if (timeout > 0)
		fto = to = timeout;
	if (timeout < 0)
		fto = to = 1000000000;
	res = cw_readstring(c, s, maxlen, to, fto, "#");
	return res;
} 
Example #6
0
static int record_exec(struct cw_channel *chan, int argc, char **argv)
{
	int res = 0;
	int count = 0;
	int percentflag = 0;
	char *ext = NULL;
	int i = 0;
	char tmp[256];

	struct cw_filestream *s = '\0';
	struct localuser *u;
	struct cw_frame *f = NULL;
	
	struct cw_dsp *sildet = NULL;   	/* silence detector dsp */
	int totalsilence = 0;
	int dspsilence = 0;
	int silence = 0;		/* amount of silence to allow */
	int gotsilence = 0;		/* did we timeout for silence? */
	int maxduration = 0;		/* max duration of recording in milliseconds */
	int gottimeout = 0;		/* did we timeout for maxduration exceeded? */
	int option_skip = 0;
	int option_noanswer = 0;
	int option_append = 0;
	int terminator = '#';
	int option_quiet = 0;
	int rfmt = 0;
	int flags;
	
	if (argc < 1 || argc > 4 || !argv[0][0]) {
		cw_log(LOG_ERROR, "Syntax: %s\n", record_syntax);
		return -1;
	}

	LOCAL_USER_ADD(u);

	if (strstr(argv[0], "%d"))
		percentflag = 1;
	ext = strrchr(argv[0], '.'); /* to support filename with a . in the filename, not format */
	if (!ext)
		ext = strchr(argv[0], ':');
	if (ext) {
		*ext = '\0';
		ext++;
	}

	if (!ext) {
		cw_log(LOG_WARNING, "No extension specified to filename!\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	if (argc > 1) {
		silence = atoi(argv[1]);
		if (silence > 0)
			silence *= 1000;
		else if (silence < 0)
			silence = 0;
	}
	
	if (argc > 2) {
		maxduration = atoi(argv[2]);
		if (maxduration > 0)
			maxduration *= 1000;
		else if (maxduration < 0)
			maxduration = 0;
	}

	if (argc > 3) {
		/* Retain backwards compatibility with old style options */
		if (!strcasecmp(argv[3], "skip"))
			option_skip = 1;
		else if (!strcasecmp(argv[3], "noanswer"))
			option_noanswer = 1;
		else {
			if (strchr(argv[3], 's'))
				option_skip = 1;
			if (strchr(argv[3], 'n'))
				option_noanswer = 1;
			if (strchr(argv[3], 'a'))
				option_append = 1;
			if (strchr(argv[3], 't'))
				terminator = '*';
			if (strchr(argv[3], 'q'))
				option_quiet = 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) {
		char *piece[100];
		int pieces;

		/* Separate each piece out by the format specifier */
		pieces = cw_separate_app_args(argv[0], '%', arraysize(piece), piece);

		do {
			int tmplen;
			/* First piece has no leading percent, so it's copied verbatim */
			cw_copy_string(tmp, piece[0], sizeof(tmp));
			tmplen = strlen(tmp);
			for (i = 1; i < pieces; i++) {
				if (piece[i][0] == 'd') {
					/* Substitute the count */
					snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%d", count);
					tmplen += strlen(tmp + tmplen);
				} else if (tmplen + 2 < sizeof(tmp)) {
					/* Unknown format specifier - just copy it verbatim */
					tmp[tmplen++] = '%';
					tmp[tmplen++] = piece[i][0];
				}
				/* Copy the remaining portion of the piece */
				cw_copy_string(tmp + tmplen, &(piece[i][1]), sizeof(tmp) - tmplen);
			}
			count++;
		} while ( cw_fileexists(tmp, ext, chan->language) != -1 );
		pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
	} else
		strncpy(tmp, argv[0], sizeof(tmp)-1);
	/* end of routine mentioned */
	
	
	
	if (chan->_state != CW_STATE_UP) {
		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 = cw_answer(chan);
		}
	}
	
	if (!res) {
	
		if (!option_quiet) {
			/* Some code to play a nice little beep to signify the start of the record operation */
			res = cw_streamfile(chan, "beep", chan->language);
			if (!res) {
				res = cw_waitstream(chan, "");
			} else {
				cw_log(LOG_WARNING, "cw_streamfile failed on %s\n", chan->name);
			}
			cw_stopstream(chan);
		}
		
		/* The end of beep code.  Now the recording starts */
		
		if (silence > 0) {
			rfmt = chan->readformat;
			res = cw_set_read_format(chan, CW_FORMAT_SLINEAR);
			if (res < 0) {
				cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
				LOCAL_USER_REMOVE(u);
				return -1;
			}
			sildet = cw_dsp_new();
			if (!sildet) {
				cw_log(LOG_WARNING, "Unable to create silence detector :(\n");
				LOCAL_USER_REMOVE(u);
				return -1;
			}
			cw_dsp_set_threshold(sildet, 256);
		} 
		
		
		flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
		s = cw_writefile( tmp, ext, NULL, flags , 0, 0644);
		
		if (s) {
			int waitres;

			/* Request a video update */
			cw_indicate(chan, CW_CONTROL_VIDUPDATE);

			if (maxduration <= 0)
				maxduration = -1;
			
			while ((waitres = cw_waitfor(chan, maxduration)) > -1) {
				if (maxduration > 0) {
					if (waitres == 0) {
						gottimeout = 1;
						break;
					}
					maxduration = waitres;
  				}
				
				f = cw_read(chan);
				if (!f) {
					res = -1;
					break;
				}
				if (f->frametype == CW_FRAME_VOICE) {
					res = cw_writestream(s, f);
					if (res) {
						cw_log(LOG_WARNING, "Problem writing frame\n");
						cw_fr_free(f);
						break;
					}
					
					if (silence > 0) {
						dspsilence = 0;
						cw_dsp_silence(sildet, f, &dspsilence);
						if (dspsilence) {
							totalsilence = dspsilence;
						} else {
							totalsilence = 0;
						}
						if (totalsilence > silence) {
							/* Ended happily with silence */
							cw_fr_free(f);
							gotsilence = 1;
							break;
						}
					}
				}
				if (f->frametype == CW_FRAME_VIDEO) {
					res = cw_writestream(s, f);
					if (res) {
						cw_log(LOG_WARNING, "Problem writing frame\n");
						cw_fr_free(f);
						break;
					}
				}
				if ((f->frametype == CW_FRAME_DTMF) &&
					(f->subclass == terminator)) {
					cw_fr_free(f);
					break;
				}
				cw_fr_free(f);
			}
			if (!f) {
				cw_log(LOG_DEBUG, "Got hangup\n");
				res = -1;
			}
			
			if (gotsilence) {
				cw_stream_rewind(s, silence-1000);
				cw_truncstream(s);
			} else if (!gottimeout) {
				/* Strip off the last 1/4 second of it */
				cw_stream_rewind(s, 250);
				cw_truncstream(s);
			}
			cw_closestream(s);
		} else
			cw_log(LOG_WARNING, "Could not create file %s\n", tmp);
	} else
		cw_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
	
	if ((silence > 0) && rfmt) {
		res = cw_set_read_format(chan, rfmt);
		if (res)
			cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
		if (sildet)
			cw_dsp_free(sildet);
	}

	LOCAL_USER_REMOVE(u);

	return res;
}
Example #7
0
static int do_directory(struct cw_channel *chan, struct cw_config *cfg, char *context, char *dialcontext, char digit, int last)
{
	/* Read in the first three digits..  "digit" is the first digit, already read */
	char ext[NUMDIGITS + 1];
	char name[80] = "";
	struct cw_variable *v;
	int res;
	int found=0;
	int lastuserchoice = 0;
	char *start, *pos, *conv,*stringp=NULL;

	if (cw_strlen_zero(context)) {
		cw_log(LOG_WARNING,
			"Directory must be called with an argument "
			"(context in which to interpret extensions)\n");
		return -1;
	}
	if (digit == '0') {
		if (!cw_goto_if_exists(chan, chan->context, "o", 1) ||
		    (!cw_strlen_zero(chan->proc_context) &&
		     !cw_goto_if_exists(chan, chan->proc_context, "o", 1))) {
			return 0;
		} else {
			cw_log(LOG_WARNING, "Can't find extension 'o' in current context.  "
				"Not Exiting the Directory!\n");
			res = 0;
		}
	}	
	if (digit == '*') {
		if (!cw_goto_if_exists(chan, chan->context, "a", 1) ||
		    (!cw_strlen_zero(chan->proc_context) &&
		     !cw_goto_if_exists(chan, chan->proc_context, "a", 1))) {
			return 0;
		} else {
			cw_log(LOG_WARNING, "Can't find extension 'a' in current context.  "
				"Not Exiting the Directory!\n");
			res = 0;
		}
	}	
	memset(ext, 0, sizeof(ext));
	ext[0] = digit;
	res = 0;
	if (cw_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1;
	if (!res) {
		/* Search for all names which start with those digits */
		v = cw_variable_browse(cfg, context);
		while(v && !res) {
			/* Find all candidate extensions */
			while(v) {
				/* Find a candidate extension */
				start = strdup(v->value);
				if (start && !strcasestr(start, "hidefromdir=yes")) {
					stringp=start;
					strsep(&stringp, ",");
					pos = strsep(&stringp, ",");
					if (pos) {
						cw_copy_string(name, pos, sizeof(name));
						/* Grab the last name */
						if (last && strrchr(pos,' '))
							pos = strrchr(pos, ' ') + 1;
						conv = convert(pos);
						if (conv) {
							if (!strcmp(conv, ext)) {
								/* Match! */
								found++;
								free(conv);
								free(start);
								break;
							}
							free(conv);
						}
					}
					free(start);
				}
				v = v->next;
			}

			if (v) {
				/* We have a match -- play a greeting if they have it */
				res = play_mailbox_owner(chan, context, dialcontext, v->name, name);
				switch (res) {
					case -1:
						/* user pressed '1' but extension does not exist, or
						 * user hungup
						 */
						lastuserchoice = 0;
						break;
					case '1':
						/* user pressed '1' and extensions exists;
						   play_mailbox_owner will already have done
						   a goto() on the channel
						 */
						lastuserchoice = res;
						break;
					case '*':
						/* user pressed '*' to skip something found */
						lastuserchoice = res;
						res = 0;
						break;
					default:
						break;
				}
				v = v->next;
			}
		}

		if (lastuserchoice != '1') {
			if (found) 
				res = cw_streamfile(chan, "dir-nomore", chan->language);
			else
				res = cw_streamfile(chan, "dir-nomatch", chan->language);
			if (!res)
				res = 1;
			return res;
		}
		return 0;
	}
	return res;
}
Example #8
0
/* play name of mailbox owner.
 * returns:  -1 for bad or missing extension
 *           '1' for selected entry from directory
 *           '*' for skipped entry from directory
 */
static int play_mailbox_owner(struct cw_channel *chan, char *context, char *dialcontext, char *ext, char *name) {
	int res = 0;
	int loop = 3;
	char fn[256];
	char fn2[256];

	/* Check for the VoiceMail2 greeting first */
	snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
		(char *)cw_config_CW_SPOOL_DIR, context, ext);

	/* Otherwise, check for an old-style Voicemail greeting */
	snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
		(char *)cw_config_CW_SPOOL_DIR, ext);

	if (cw_fileexists(fn, NULL, chan->language) > 0) {
		res = cw_streamfile(chan, fn, chan->language);
		if (!res) {
			res = cw_waitstream(chan, CW_DIGIT_ANY);
		}
		cw_stopstream(chan);
	} else if (cw_fileexists(fn2, NULL, chan->language) > 0) {
		res = cw_streamfile(chan, fn2, chan->language);
		if (!res) {
			res = cw_waitstream(chan, CW_DIGIT_ANY);
		}
		cw_stopstream(chan);
	} else {
		res = cw_say_character_str(chan, !cw_strlen_zero(name) ? name : ext,
					CW_DIGIT_ANY, chan->language);
	}

	while (loop) {
		if (!res) {
			res = cw_streamfile(chan, "dir-instr", chan->language);
		}
		if (!res) {
			res = cw_waitstream(chan, CW_DIGIT_ANY);
		}
		if (!res) {
			res = cw_waitfordigit(chan, 3000);
		}
		cw_stopstream(chan);
	
		if (res > -1) {
			switch (res) {
				case '1':
					/* Name selected */
					loop = 0;
					if (cw_goto_if_exists(chan, dialcontext, ext, 1)) {
						cw_log(LOG_WARNING,
							"Can't find extension '%s' in context '%s'.  "
							"Did you pass the wrong context to Directory?\n",
							ext, dialcontext);
						res = -1;
					}
					break;
	
				case '*':   
					/* Skip to next match in list */
					loop = 0;
					break;
	
				default:
					/* Not '1', or '*', so decrement number of tries */
					res = 0;
					loop--;
					break;
			} /* end switch */
		} /* end if */
		else {
			/* User hungup, so jump out now */
			loop = 0;
		}
	} /* end while */

	return(res);
}
Example #9
0
int cw_play_and_prepend(struct cw_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
{
	int d = 0;
	char *fmts;
	char comment[256];
	int x, fmtcnt=1, res=-1,outmsg=0;
	struct cw_frame *f;
	struct cw_filestream *others[MAX_OTHER_FORMATS];
	struct cw_filestream *realfiles[MAX_OTHER_FORMATS];
	char *sfmt[MAX_OTHER_FORMATS];
	char *stringp=NULL;
	time_t start, end;
	struct cw_dsp *sildet;   	/* silence detector dsp */
	int totalsilence = 0;
	int dspsilence = 0;
	int gotsilence = 0;		/* did we timeout for silence? */
	int rfmt=0;	
	char prependfile[80];
	
	if (silencethreshold < 0)
		silencethreshold = global_silence_threshold;

	if (maxsilence < 0)
		maxsilence = global_maxsilence;

	/* barf if no pointer passed to store duration in */
	if (duration == NULL) {
		cw_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
		return -1;
	}

	cw_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
	snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);

	if (playfile || beep) {	
		if (!beep)
			d = cw_play_and_wait(chan, playfile);
		if (d > -1)
			d = cw_streamfile(chan, "beep",chan->language);
		if (!d)
			d = cw_waitstream(chan,"");
		if (d < 0)
			return -1;
	}
	cw_copy_string(prependfile, recordfile, sizeof(prependfile));	
	strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
			
	fmts = cw_strdupa(fmt);
	
	stringp=fmts;
	strsep(&stringp, "|,");
	cw_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);	
	sfmt[0] = cw_strdupa(fmts);
	
	while((fmt = strsep(&stringp, "|,"))) {
		if (fmtcnt > MAX_OTHER_FORMATS - 1) {
			cw_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
			break;
		}
		sfmt[fmtcnt++] = cw_strdupa(fmt);
	}

	time(&start);
	end=start;  /* pre-initialize end to be same as start in case we never get into loop */
	for (x=0;x<fmtcnt;x++) {
		others[x] = cw_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
		cw_verbose( VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
		if (!others[x]) {
			break;
		}
	}
	
	sildet = cw_dsp_new(); /* Create the silence detector */
	if (!sildet) {
		cw_log(LOG_WARNING, "Unable to create silence detector :(\n");
		return -1;
	}
	cw_dsp_set_threshold(sildet, silencethreshold);

	if (maxsilence > 0) {
		rfmt = chan->readformat;
		res = cw_set_read_format(chan, CW_FORMAT_SLINEAR);
		if (res < 0) {
			cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
			return -1;
		}
	}
						
	if (x == fmtcnt) {
	/* Loop forever, writing the packets we read to the writer(s), until
	   we read a # or get a hangup */
		f = NULL;
		for(;;) {
		 	res = cw_waitfor(chan, 2000);
			if (!res) {
				cw_log(LOG_DEBUG, "One waitfor failed, trying another\n");
				/* Try one more time in case of masq */
			 	res = cw_waitfor(chan, 2000);
				if (!res) {
					cw_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
					res = -1;
				}
			}
			
			if (res < 0) {
				f = NULL;
				break;
			}
			f = cw_read(chan);
			if (!f)
				break;
			if (f->frametype == CW_FRAME_VOICE) {
				/* write each format */
				for (x=0;x<fmtcnt;x++) {
					if (!others[x])
						break;
					res = cw_writestream(others[x], f);
				}
				
				/* Silence Detection */
				if (maxsilence > 0) {
					dspsilence = 0;
					cw_dsp_silence(sildet, f, &dspsilence);
					if (dspsilence)
						totalsilence = dspsilence;
					else
						totalsilence = 0;
					
					if (totalsilence > maxsilence) {
					/* Ended happily with silence */
					if (option_verbose > 2) 
						cw_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
					cw_fr_free(f);
					gotsilence = 1;
					outmsg=2;
					break;
					}
				}
				/* Exit on any error */
				if (res) {
					cw_log(LOG_WARNING, "Error writing frame\n");
					cw_fr_free(f);
					break;
				}
			} else if (f->frametype == CW_FRAME_VIDEO) {
				/* Write only once */
				cw_writestream(others[0], f);
			} else if (f->frametype == CW_FRAME_DTMF) {
				/* stop recording with any digit */
				if (option_verbose > 2) 
					cw_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
				res = 't';
				outmsg = 2;
				cw_fr_free(f);
				break;
			}
			if (maxtime) {
				time(&end);
				if (maxtime < (end - start)) {
					if (option_verbose > 2)
						cw_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
					res = 't';
					outmsg=2;
					cw_fr_free(f);
					break;
				}
			}
			cw_fr_free(f);
		}
		if (end == start)
            time(&end);
		if (!f) {
			if (option_verbose > 2) 
				cw_verbose( VERBOSE_PREFIX_3 "User hung up\n");
			res = -1;
			outmsg=1;
#if 0
			/* delete all the prepend files */
			for (x=0;x<fmtcnt;x++) {
				if (!others[x])
					break;
				cw_closestream(others[x]);
				cw_filedelete(prependfile, sfmt[x]);
			}
#endif
		}
	} else {
		cw_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]); 
	}
	*duration = end - start;
#if 0
	if (outmsg > 1) {
#else
	if (outmsg) {
#endif
		struct cw_frame *fr;
		for (x=0;x<fmtcnt;x++) {
			snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
			realfiles[x] = cw_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
			if (!others[x] || !realfiles[x])
				break;
			if (totalsilence)
				cw_stream_rewind(others[x], totalsilence-200);
			else
				cw_stream_rewind(others[x], 200);
			cw_truncstream(others[x]);
			/* add the original file too */
			while ((fr = cw_readframe(realfiles[x]))) {
				cw_writestream(others[x],fr);
			}
			cw_closestream(others[x]);
			cw_closestream(realfiles[x]);
			cw_filerename(prependfile, recordfile, sfmt[x]);
#if 0
			cw_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
#endif
			cw_filedelete(prependfile, sfmt[x]);
		}
	}
	if (rfmt) {
		if (cw_set_read_format(chan, rfmt)) {
			cw_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", cw_getformatname(rfmt), chan->name);
		}
	}
	if (outmsg) {
		if (outmsg > 1) {
			/* Let them know it worked */
			cw_streamfile(chan, "auth-thankyou", chan->language);
			cw_waitstream(chan, "");
		}
	}	
	return res;
}

/* Channel group core functions */

int cw_app_group_split_group(char *data, char *group, int group_max, char *category, int category_max)
{
	int res=0;
	char tmp[256];
	char *grp=NULL, *cat=NULL;

	if (!cw_strlen_zero(data)) {
		cw_copy_string(tmp, data, sizeof(tmp));
		grp = tmp;
		cat = strchr(tmp, '@');
		if (cat) {
			*cat = '\0';
			cat++;
		}
	}

	if (!cw_strlen_zero(grp))
		cw_copy_string(group, grp, group_max);
	else
		res = -1;

	if (cat)
		snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat);
	else
		cw_copy_string(category, GROUP_CATEGORY_PREFIX, category_max);

	return res;
}
Example #10
0
int cw_play_and_record(struct cw_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
{
	int d;
	char *fmts;
	char comment[256];
	int x, fmtcnt=1, res=-1,outmsg=0;
	struct cw_frame *f;
	struct cw_filestream *others[MAX_OTHER_FORMATS];
	char *sfmt[MAX_OTHER_FORMATS];
	char *stringp=NULL;
	time_t start, end;
	struct cw_dsp *sildet=NULL;   	/* silence detector dsp */
	int totalsilence = 0;
	int dspsilence = 0;
	int gotsilence = 0;		/* did we timeout for silence? */
	int rfmt=0;

	if (silencethreshold < 0)
		silencethreshold = global_silence_threshold;

	if (maxsilence < 0)
		maxsilence = global_maxsilence;

	/* barf if no pointer passed to store duration in */
	if (duration == NULL) {
		cw_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
		return -1;
	}

	cw_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
	snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);

	if (playfile) {
		d = cw_play_and_wait(chan, playfile);
		if (d > -1)
			d = cw_streamfile(chan, "beep",chan->language);
		if (!d)
			d = cw_waitstream(chan,"");
		if (d < 0)
			return -1;
	}

	fmts = cw_strdupa(fmt);

	stringp=fmts;
	strsep(&stringp, "|,");
	cw_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
	sfmt[0] = cw_strdupa(fmts);

	while((fmt = strsep(&stringp, "|,"))) {
		if (fmtcnt > MAX_OTHER_FORMATS - 1) {
			cw_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
			break;
		}
		sfmt[fmtcnt++] = cw_strdupa(fmt);
	}

	time(&start);
	end=start;  /* pre-initialize end to be same as start in case we never get into loop */
	for (x=0;x<fmtcnt;x++) {
		others[x] = cw_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
		cw_verbose( VERBOSE_PREFIX_3 "x=%d, open writing:  %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);

		if (!others[x]) {
			break;
		}
	}

	if (path)
		cw_unlock_path(path);


	
	if (maxsilence > 0) {
		sildet = cw_dsp_new(); /* Create the silence detector */
		if (!sildet) {
			cw_log(LOG_WARNING, "Unable to create silence detector :(\n");
			return -1;
		}
		cw_dsp_set_threshold(sildet, silencethreshold);
		rfmt = chan->readformat;
		res = cw_set_read_format(chan, CW_FORMAT_SLINEAR);
		if (res < 0) {
			cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
			cw_dsp_free(sildet);
			return -1;
		}
	}
	/* Request a video update */
	cw_indicate(chan, CW_CONTROL_VIDUPDATE);

	if (x == fmtcnt) {
	/* Loop forever, writing the packets we read to the writer(s), until
	   we read a # or get a hangup */
		f = NULL;
		for(;;) {
		 	res = cw_waitfor(chan, 2000);
			if (!res) {
				cw_log(LOG_DEBUG, "One waitfor failed, trying another\n");
				/* Try one more time in case of masq */
			 	res = cw_waitfor(chan, 2000);
				if (!res) {
					cw_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
					res = -1;
				}
			}

			if (res < 0) {
				f = NULL;
				break;
			}
			f = cw_read(chan);
			if (!f)
				break;
			if (f->frametype == CW_FRAME_VOICE) {
				/* write each format */
				for (x=0;x<fmtcnt;x++) {
					res = cw_writestream(others[x], f);
				}

				/* Silence Detection */
				if (maxsilence > 0) {
					dspsilence = 0;
					cw_dsp_silence(sildet, f, &dspsilence);
					if (dspsilence)
						totalsilence = dspsilence;
					else
						totalsilence = 0;

					if (totalsilence > maxsilence) {
						/* Ended happily with silence */
						if (option_verbose > 2)
							cw_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
						cw_fr_free(f);
						gotsilence = 1;
						outmsg=2;
						break;
					}
				}
				/* Exit on any error */
				if (res) {
					cw_log(LOG_WARNING, "Error writing frame\n");
					cw_fr_free(f);
					break;
				}
			} else if (f->frametype == CW_FRAME_VIDEO) {
				/* Write only once */
				cw_writestream(others[0], f);
			} else if (f->frametype == CW_FRAME_DTMF) {
				if (f->subclass == '#') {
					if (option_verbose > 2)
						cw_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
					res = '#';
					outmsg = 2;
					cw_fr_free(f);
					break;
				}
				if (f->subclass == '0') {
				/* Check for a '0' during message recording also, in case caller wants operator */
					if (option_verbose > 2)
						cw_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
					res = '0';
					outmsg = 0;
					cw_fr_free(f);
					break;
				}
			}
			if (maxtime) {
				time(&end);
				if (maxtime < (end - start)) {
					if (option_verbose > 2)
						cw_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
					outmsg = 2;
					res = 't';
					cw_fr_free(f);
					break;
				}
			}
			cw_fr_free(f);
		}
		if (end == start) time(&end);
		if (!f) {
			if (option_verbose > 2)
				cw_verbose( VERBOSE_PREFIX_3 "User hung up\n");
			res = -1;
			outmsg=1;
		}
	} else {
		cw_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
	}

	*duration = end - start;

	for (x=0;x<fmtcnt;x++) {
		if (!others[x])
			break;
		if (res > 0) {
			if (totalsilence)
				cw_stream_rewind(others[x], totalsilence-200);
			else
				cw_stream_rewind(others[x], 200);
		}
		cw_truncstream(others[x]);
		cw_closestream(others[x]);
	}
	if (rfmt) {
		if (cw_set_read_format(chan, rfmt)) {
			cw_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", cw_getformatname(rfmt), chan->name);
		}
	}
	if (outmsg > 1) {
		/* Let them know recording is stopped */
		if(!cw_streamfile(chan, "auth-thankyou", chan->language))
			cw_waitstream(chan, "");
	}
	if (sildet)
		cw_dsp_free(sildet);
	return res;
}
Example #11
0
int cw_control_streamfile(struct cw_channel *chan, const char *file,
			   const char *fwd, const char *rev,
			   const char *stop, const char *pause,
			   const char *restart, int skipms) 
{
	long elapsed = 0, last_elapsed = 0;
	char *breaks = NULL;
	char *end = NULL;
	int blen = 2;
	int res;

	if (stop)
		blen += strlen(stop);
	if (pause)
		blen += strlen(pause);
	if (restart)
		blen += strlen(restart);

	if (blen > 2) {
		breaks = alloca(blen + 1);
		breaks[0] = '\0';
		if (stop)
			strcat(breaks, stop);
		if (pause)
			strcat(breaks, pause);
		if (restart)
			strcat(breaks, restart);
	}
	if (chan->_state != CW_STATE_UP)
		res = cw_answer(chan);

	if (chan)
		cw_stopstream(chan);

	if (file) {
		if ((end = strchr(file,':'))) {
			if (!strcasecmp(end, ":end")) {
				*end = '\0';
				end++;
			}
		}
	}

	for (;;) {
		struct timeval started = cw_tvnow();

		if (chan)
			cw_stopstream(chan);
		res = cw_streamfile(chan, file, chan->language);
		if (!res) {
			if (end) {
				cw_seekstream(chan->stream, 0, SEEK_END);
				end=NULL;
			}
			res = 1;
			if (elapsed) {
				cw_stream_fastforward(chan->stream, elapsed);
				last_elapsed = elapsed - 200;
			}
			if (res)
				res = cw_waitstream_fr(chan, breaks, fwd, rev, skipms);
			else
				break;
		}

		if (res < 1)
			break;

		/* We go at next loop if we got the restart char */
		if (restart && strchr(restart, res)) {
			cw_log(LOG_DEBUG, "we'll restart the stream here at next loop\n");
			elapsed=0; /* To make sure the next stream will start at beginning */
			continue;
		}

		if (pause != NULL && strchr(pause, res)) {
			elapsed = cw_tvdiff_ms(cw_tvnow(), started) + last_elapsed;
			for(;;) {
				if (chan)
					cw_stopstream(chan);
				res = cw_waitfordigit(chan, 1000);
				if (res == 0)
					continue;
				else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
					break;
			}
			if (res == *pause) {
				res = 0;
				continue;
			}
		}
		if (res == -1)
			break;

		/* if we get one of our stop chars, return it to the calling function */
		if (stop && strchr(stop, res)) {
			/* res = 0; */
			break;
		}
	}
	if (chan)
		cw_stopstream(chan);

	return res;
}
Example #12
0
int cw_app_getvoice(struct cw_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
{
	int res;
	struct cw_filestream *writer;
	int rfmt;
	int totalms=0, total;
	
	struct cw_frame *f;
	struct cw_dsp *sildet;
	/* Play prompt if requested */
	if (prompt) {
		res = cw_streamfile(c, prompt, c->language);
		if (res < 0)
			return res;
		res = cw_waitstream(c,"");
		if (res < 0)
			return res;
	}
	rfmt = c->readformat;
	res = cw_set_read_format(c, CW_FORMAT_SLINEAR);
	if (res < 0) {
		cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
		return -1;
	}
	sildet = cw_dsp_new();
	if (!sildet) {
		cw_log(LOG_WARNING, "Unable to create silence detector :(\n");
		return -1;
	}
	writer = cw_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
	if (!writer) {
		cw_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
		cw_dsp_free(sildet);
		return -1;
	}
	for(;;) {
		if ((res = cw_waitfor(c, 2000)) < 0) {
			cw_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
			break;
		}
		if (res) {
			f = cw_read(c);
			if (!f) {
				cw_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
				break;
			}
			if ((f->frametype == CW_FRAME_DTMF) && (f->subclass == '#')) {
				/* Ended happily with DTMF */
				cw_fr_free(f);
				break;
			} else if (f->frametype == CW_FRAME_VOICE) {
				cw_dsp_silence(sildet, f, &total); 
				if (total > silence) {
					/* Ended happily with silence */
					cw_fr_free(f);
					break;
				}
				totalms += f->samples / 8;
				if (totalms > maxsec * 1000) {
					/* Ended happily with too much stuff */
					cw_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
					cw_fr_free(f);
					break;
				}
				res = cw_writestream(writer, f);
				if (res < 0) {
					cw_log(LOG_WARNING, "Failed to write to stream at %s!\n", dest);
					cw_fr_free(f);
					break;
				}

			}
			cw_fr_free(f);
		}
	}
	res = cw_set_read_format(c, rfmt);
	if (res)
		cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
	cw_dsp_free(sildet);
	cw_closestream(writer);
	return 0;
}
Example #13
0
static int ivr_dispatch(struct cw_channel *chan, struct cw_ivr_option *option, char *exten, void *cbdata)
{
	int res;
	int (*ivr_func)(struct cw_channel *, void *);
	char *c;
	char *n;
	
	switch(option->action) {
	case CW_ACTION_UPONE:
		return RES_UPONE;
	case CW_ACTION_EXIT:
		return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
	case CW_ACTION_REPEAT:
		return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
	case CW_ACTION_RESTART:
		return RES_RESTART ;
	case CW_ACTION_NOOP:
		return 0;
	case CW_ACTION_BACKGROUND:
		res = cw_streamfile(chan, (char *)option->adata, chan->language);
		if (!res) {
			res = cw_waitstream(chan, CW_DIGIT_ANY);
		} else {
			cw_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
			res = 0;
		}
		return res;
	case CW_ACTION_PLAYBACK:
		res = cw_streamfile(chan, (char *)option->adata, chan->language);
		if (!res) {
			res = cw_waitstream(chan, "");
		} else {
			cw_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
			res = 0;
		}
		return res;
	case CW_ACTION_MENU:
		res = cw_ivr_menu_run_internal(chan, (struct cw_ivr_menu *)option->adata, cbdata);
		/* Do not pass entry errors back up, treat as though it was an "UPONE" */
		if (res == -2)
			res = 0;
		return res;
	case CW_ACTION_WAITOPTION:
		res = cw_waitfordigit(chan, 1000 * (chan->pbx ? chan->pbx->rtimeout : 10));
		if (!res)
			return 't';
		return res;
	case CW_ACTION_CALLBACK:
		ivr_func = option->adata;
		res = ivr_func(chan, cbdata);
		return res;
	case CW_ACTION_TRANSFER:
		res = cw_parseable_goto(chan, option->adata);
		return 0;
	case CW_ACTION_PLAYLIST:
	case CW_ACTION_BACKLIST:
		res = 0;
		c = cw_strdupa(option->adata);
		while((n = strsep(&c, ";")))
			if ((res = cw_streamfile(chan, n, chan->language)) || (res = cw_waitstream(chan, (option->action == CW_ACTION_BACKLIST) ? CW_DIGIT_ANY : "")))
				break;
		cw_stopstream(chan);
		return res;
	default:
		cw_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
		return 0;
	};
	return -1;
}
Example #14
0
int cw_record_review(struct cw_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path) 
{
	int silencethreshold = 128; 
	int maxsilence=0;
	int res = 0;
	int cmd = 0;
	int max_attempts = 3;
	int attempts = 0;
	int recorded = 0;
	int message_exists = 0;
	/* Note that urgent and private are for flagging messages as such in the future */

	/* barf if no pointer passed to store duration in */
	if (duration == NULL) {
		cw_log(LOG_WARNING, "Error cw_record_review called without duration pointer\n");
		return -1;
	}

	cmd = '3';	 /* Want to start by recording */

	while ((cmd >= 0) && (cmd != 't')) {
		switch (cmd) {
		case '1':
			if (!message_exists) {
				/* In this case, 1 is to record a message */
				cmd = '3';
				break;
			} else {
				cw_streamfile(chan, "vm-msgsaved", chan->language);
				cw_waitstream(chan, "");
				cmd = 't';
				return res;
			}
		case '2':
			/* Review */
			cw_verbose(VERBOSE_PREFIX_3 "Reviewing the recording\n");
			cw_streamfile(chan, recordfile, chan->language);
			cmd = cw_waitstream(chan, CW_DIGIT_ANY);
			break;
		case '3':
			message_exists = 0;
			/* Record */
			if (recorded == 1)
				cw_verbose(VERBOSE_PREFIX_3 "Re-recording\n");
			else	
				cw_verbose(VERBOSE_PREFIX_3 "Recording\n");
			recorded = 1;
			cmd = cw_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path);
			if (cmd == -1) {
			/* User has hung up, no options to give */
				return cmd;
			}
			if (cmd == '0') {
				break;
			} else if (cmd == '*') {
				break;
			} 
			else {
				/* If all is well, a message exists */
				message_exists = 1;
				cmd = 0;
			}
			break;
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		case '*':
		case '#':
			cmd = cw_play_and_wait(chan, "vm-sorry");
			break;
		default:
			if (message_exists) {
				cmd = cw_play_and_wait(chan, "vm-review");
			}
			else {
				cmd = cw_play_and_wait(chan, "vm-torerecord");
				if (!cmd)
					cmd = cw_waitfordigit(chan, 600);
			}
			
			if (!cmd)
				cmd = cw_waitfordigit(chan, 6000);
			if (!cmd) {
				attempts++;
			}
			if (attempts > max_attempts) {
				cmd = 't';
			}
		}
	}
	if (cmd == 't')
		cmd = 0;
	return cmd;
}
Example #15
0
static int privacy_exec (struct cw_channel *chan, int argc, char **argv)
{
	char phone[30];
	struct localuser *u;
	struct cw_config *cfg;
	char *s;
	int res=0;
	int retries;
	int maxretries = 3;
	int minlength = 10;
	int x;

	LOCAL_USER_ADD (u);

	if (!cw_strlen_zero(chan->cid.cid_num)) {
		if (option_verbose > 2)
			cw_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
		pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
	} else {
		/*Answer the channel if it is not already*/
		if (chan->_state != CW_STATE_UP) {
			res = cw_answer(chan);
			if (res) {
				pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL");
				LOCAL_USER_REMOVE(u);
				return 0;
			}
		}
		/*Read in the config file*/
		cfg = cw_config_load(PRIV_CONFIG);
		
		
		/*Play unidentified call*/
		res = cw_safe_sleep(chan, 1000);
		if (!res)
			res = cw_streamfile(chan, "privacy-unident", chan->language);
		if (!res)
			res = cw_waitstream(chan, "");

        if (cfg && (s = cw_variable_retrieve(cfg, "general", "maxretries"))) {
                if (sscanf(s, "%d", &x) == 1) {
                        maxretries = x;
                } else {
                        cw_log(LOG_WARNING, "Invalid max retries argument\n");
                }
        }
        if (cfg && (s = cw_variable_retrieve(cfg, "general", "minlength"))) {
                if (sscanf(s, "%d", &x) == 1) {
                        minlength = x;
                } else {
                        cw_log(LOG_WARNING, "Invalid min length argument\n");
                }
        }
			
		/*Ask for 10 digit number, give 3 attempts*/
		for (retries = 0; retries < maxretries; retries++) {
			if (!res ) 
				res = cw_app_getdata(chan, "privacy-prompt", phone, sizeof(phone), 0);

			if (res < 0)
				break;

			/*Make sure we get at least our minimum of digits*/
			if (strlen(phone) >= minlength ) 
				break;
			else {
				res = cw_streamfile(chan, "privacy-incorrect", chan->language);
				if (!res)
					res = cw_waitstream(chan, "");
			}
		}
		
		/*Got a number, play sounds and send them on their way*/
		if ((retries < maxretries) && res == 1 ) {
			res = cw_streamfile(chan, "privacy-thankyou", chan->language);
			if (!res)
				res = cw_waitstream(chan, "");
			cw_set_callerid (chan, phone, "Privacy Manager", NULL);
			if (option_verbose > 2)
				cw_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",phone);
			pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
		} else {
			/* Flag Failure  */
			pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL");
		}
		if (cfg) 
			cw_config_destroy(cfg);
	}

  LOCAL_USER_REMOVE (u);
  return 0;
}