Beispiel #1
0
static int checkMax(struct ast_channel *chan, struct roomdetails *dtmfmatch)
{
	int res=0;
    	struct ast_app *app;
	char getvar[30]="AstVar";
	char roomno[30]="";
	char maxusers[30]="";
	char currentusers[30]="";
	char prompt[50]="";
	char arg[255]="";

    	strcpy(maxusers,dtmfmatch->maxusers);
	strcpy(roomno,dtmfmatch->roomno);
    	strcat(arg,roomno);
    	strcat(arg,",");
	strcat(arg,getvar);

	if(!(app = pbx_findapp(ConfAppCount))) {
		ast_log(LOG_WARNING, "Invalid participant count application: %s\n", ConfAppCount);
		return -1;
	}
 	res = pbx_exec(chan, app, arg);
   	strcpy(currentusers, pbx_builtin_getvar_helper(chan, getvar));
	if(atoi(currentusers) < atoi(maxusers)){
	ast_log(LOG_NOTICE, "Currentusers: %i\n", atoi(currentusers));
		if(atoi(currentusers)>0){
			strcpy(prompt,"conf-thereare");
			if (!ast_streamfile(chan, "conf-thereare", chan->language)){
				res = ast_waitstream(chan,"");
				ast_stopstream(chan);
				
				if (!ast_say_number(chan, (atoi(currentusers)), AST_DIGIT_ANY, chan->language, (char *) NULL)){
					res = ast_waitstream(chan,"");
					ast_stopstream(chan);
				}
				if (!ast_streamfile(chan, "conf-otherinparty", chan->language)){
					res = ast_waitstream(chan,"");
					ast_stopstream(chan);
				}
			}
		}
		res=1;
	}
	else{
        	ast_log(LOG_NOTICE, "Maximum users exeeded, Current users in room: %s\n",currentusers);
        	strcpy(prompt, "conf-locked");
        	if (!ast_streamfile(chan, prompt, chan->language)){
        		res = ast_waitstream(chan,"");
			ast_stopstream(chan);
		}
		res=-1;
	}
	return res;
}
Beispiel #2
0
int getConf(struct ast_channel *chan, struct userkeyin dtmfinput, struct roomdetails *dtmfmatch)
{
	char *prompt;
	/* char *invalid;*/

	int res=0, retry=0, skip=0;

	if (ast_strlen_zero(dtmfinput.inroom)){
		strcpy(dtmfinput.inroom, "");
	} else {
		skip = 1;	
		retry = 2;
	}
	
	 while (retry++ < 3){ 
		if(!skip){
			prompt = "conf-getconfno";
        		if(ast_app_getdata(chan, prompt, dtmfinput.inroom, sizeof(dtmfinput.inroom) - 2, 0) < 0)
				return -1;
			res = ast_waitstream(chan,"");
		}
 		res = roomQuery(dtmfinput, dtmfmatch);
		if(res==1 || res==2)
			break;
		if(res == -2){
			prompt = "conf-has-not-started";
			if (!ast_streamfile(chan, prompt, chan->language)){
				res = ast_waitstream(chan,"");
				ast_stopstream(chan);
			}
			res = -1;
			break;
		}
		prompt = "conf-invalid";
		if (!ast_streamfile(chan, prompt, chan->language)){
			res = ast_waitstream(chan,"");
			ast_stopstream(chan);
		}
	}

	if(retry>=2 && (res < 1 && !skip)){
		prompt = "vm-goodbye";
		if (!ast_streamfile(chan, prompt, chan->language)){
			res = ast_waitstream(chan,"");
			ast_stopstream(chan);
		}
		res = -1;
	}
	return res;
}
Beispiel #3
0
static int _play_file(struct ast_channel* chan, char* filename) {
	int res;

	ast_stopstream(chan);
	res = ast_streamfile(chan, filename, chan->language);

	if(!res)
		res = ast_waitstream(chan, AST_DIGIT_ANY);
	else
		res = 0;

	ast_stopstream(chan);

	return res;
}
Beispiel #4
0
int getPass(struct ast_channel *chan, struct userkeyin dtmfinput, struct roomdetails *dtmfmatch)
{
	char *prompt;
	/* char *invalid; */
	int res = 0, retry=0;

        prompt = "agent-pass";
        if(ast_app_getdata(chan, prompt, dtmfinput.inpass, sizeof(dtmfinput.inpass) - 2, 0) < 0)
		return -1;
        res = ast_waitstream(chan,"");
        res = passQuery(dtmfinput, dtmfmatch);

        while (retry++ < 2 && res !=1){
		    prompt = "auth-incorrect";
		    if(ast_app_getdata(chan, prompt, dtmfinput.inpass, sizeof(dtmfinput.inpass) - 2, 0) < 0)
			return -1;
		    res = ast_waitstream(chan,"");
			res = passQuery(dtmfinput, dtmfmatch);
				if(res==1)
					break;
		}

       if(retry>1 && res != 1){
			prompt = "vm-goodbye";
			if (!ast_streamfile(chan, prompt, chan->language)){
				res = ast_waitstream(chan,"");
				ast_stopstream(chan);
			}
			res = -1;
        }
	return res;
}
Beispiel #5
0
int adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
{
	unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
	int msglens[5];
	int msgtypes[5];
	int newdatamode;
	int res;
	int x;
	int writeformat, readformat;

	writeformat = chan->writeformat;
	readformat = chan->readformat;

	newdatamode = chan->adsicpe & ADSI_FLAG_DATAMODE;

	for (x=0;x<msglen;x+=(msg[x+1]+2)) {
		if (msg[x] == ADSI_SWITCH_TO_DATA) 
			newdatamode = ADSI_FLAG_DATAMODE;
		
		if (msg[x] == ADSI_SWITCH_TO_VOICE)
			newdatamode = 0;
	}
	msgs[0] = msg;

	msglens[0] = msglen;
	msgtypes[0] = msgtype;

	if (msglen > 253) {
		ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen);
		return -1;
	}

	ast_stopstream(chan);

	if (ast_set_write_format(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
		return -1;
	}

	if (ast_set_read_format(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
		if (writeformat) {
			if (ast_set_write_format(chan, writeformat)) 
				ast_log(LOG_WARNING, "Unable to restore write format to %d\n", writeformat);
		}
		return -1;
	}
	res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes);
	if (!res)
		chan->adsicpe = (chan->adsicpe & ~ADSI_FLAG_DATAMODE) | newdatamode;

	if (writeformat)
		ast_set_write_format(chan, writeformat);
	if (readformat)
		ast_set_read_format(chan, readformat);

	return res;
}
Beispiel #6
0
int ast_play_and_wait(struct ast_channel *chan, char *fn)
{
    int d;
    d = ast_streamfile(chan, fn, chan->language);
    if (d)
        return d;
    d = ast_waitstream(chan, AST_DIGIT_ANY);
    ast_stopstream(chan);
    return d;
}
Beispiel #7
0
static int s_streamwait3(const say_args_t *a, const char *fn)
{
	int res = ast_streamfile(a->chan, fn, a->language);
	if (res) {
		ast_log(LOG_WARNING, "Unable to play message %s\n", fn);
		return res;
	}
	res = (a->audiofd  > -1 && a->ctrlfd > -1) ?
	ast_waitstream_full(a->chan, a->ints, a->audiofd, a->ctrlfd) :
	ast_waitstream(a->chan, a->ints);
	ast_stopstream(a->chan);
	return res;  
}
static int zapateller_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u;
	int answer = 0, nocallerid = 0;
	char *c;
	char *stringp=NULL;
	
	LOCAL_USER_ADD(u);

	stringp=data;
        c = strsep(&stringp, "|");
        while(!ast_strlen_zero(c)) {
		if (!strcasecmp(c, "answer"))
			answer = 1;
		else if (!strcasecmp(c, "nocallerid"))
			nocallerid = 1;

                c = strsep(&stringp, "|");
        }

	ast_stopstream(chan);
	if (chan->_state != AST_STATE_UP) {

		if (answer) 
			res = ast_answer(chan);
		if (!res) {
			res = ast_safe_sleep(chan, 500);
		}
	}
	if (chan->cid.cid_num && nocallerid) {
		LOCAL_USER_REMOVE(u);
		return res;
	} 
	if (!res) 
		res = ast_tonepair(chan, 950, 0, 330, 0);
	if (!res) 
		res = ast_tonepair(chan, 1400, 0, 330, 0);
	if (!res) 
		res = ast_tonepair(chan, 1800, 0, 330, 0);
	if (!res) 
		res = ast_tonepair(chan, 0, 0, 1000, 0);
	LOCAL_USER_REMOVE(u);
	return res;
}
/*! \brief Helper function that presents dialtone and grabs extension */
static int grab_transfer(struct ast_channel *chan, char *exten, size_t exten_len, const char *context)
{
	int res;

	/* Play the simple "transfer" prompt out and wait */
	res = ast_stream_and_wait(chan, "pbx-transfer", AST_DIGIT_ANY);
	ast_stopstream(chan);

	/* If the person hit a DTMF digit while the above played back stick it into the buffer */
	if (res) {
		exten[0] = (char)res;
	}

	/* Drop to dialtone so they can enter the extension they want to transfer to */
	res = ast_app_dtget(chan, context, exten, exten_len, 100, 1000);

	return res;
}
Beispiel #10
0
static int enterConf(struct ast_channel *chan, struct roomdetails *dtmfmatch)
{
        int res=0;
        /* char *prompt; */
	char prompt[50]="";
        struct ast_app *app;
	char arg2[255]="";
	char roomno2[80]="";
	char roomtype2[30]="";
	char recordfile[100]="conf-recordings/";

        strcpy(roomno2,dtmfmatch->roomno);
	strcpy(roomtype2,dtmfmatch->roomtype);
	strcpy(arg2, roomno2);

	strcat(arg2, ",");
	strcat(arg2, roomtype2);
	strcat(arg2, ",");

	strcat(recordfile, dtmfmatch->roomno);
	strcat(recordfile, "-");
	strcat(recordfile, dtmfmatch->bookid);

        ast_log(LOG_NOTICE, "Roomtype: %s\n", arg2);
	pbx_builtin_setvar_helper(chan, "MEETME_RECORDINGFILE", recordfile);
  
	if(strchr(dtmfmatch->aFlags, 'r'))
	{
		strcpy(prompt,"conf-call-recorded");
		if (!ast_streamfile(chan, prompt, chan->language)){
			res = ast_waitstream(chan,"");
			ast_stopstream(chan);
		}
	}
        if(!(app=pbx_findapp(ConfApp))){
		ast_log(LOG_WARNING, "Invalid conferencing application: %s\n", ConfApp);
		return -1;
	}
        res = pbx_exec(chan, app, arg2);

	return 1;
}
static int directory_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u;
	struct ast_config *cfg;
	int last = 1;
	int fromappvm = 0;
	char *context, *dialcontext, *dirintro, *options;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	context = ast_strdupa(data);
	dialcontext = strchr(context, '|');
	if (dialcontext) {
		*dialcontext = '\0';
		dialcontext++;
		options = strchr(dialcontext, '|');
		if (options) {
			*options = '\0';
			options++; 
			if (strchr(options, 'f'))
				last = 0;
			if (strchr(options, 'v'))
				fromappvm = 1;
		}
	} else	
		dialcontext = context;

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

	dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
	if (ast_strlen_zero(dirintro))
		dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
	if (ast_strlen_zero(dirintro)) {
		if (last)
			dirintro = "dir-intro";	
		else
			dirintro = "dir-intro-fn";
	}

	if (chan->_state != AST_STATE_UP) 
		res = ast_answer(chan);

	for (;;) {
		if (!res)
			res = ast_streamfile(chan, dirintro, chan->language);
		if (!res)
			res = ast_waitstream(chan, AST_DIGIT_ANY);
		ast_stopstream(chan);
		if (!res)
			res = ast_waitfordigit(chan, 5000);
		if (res > 0) {
			res = do_directory(chan, cfg, context, dialcontext, res, last, fromappvm);
			if (res > 0) {
				res = ast_waitstream(chan, AST_DIGIT_ANY);
				ast_stopstream(chan);
				if (res >= 0) {
					continue;
				}
			}
		}
		break;
	}
	ast_config_destroy(cfg);
	LOCAL_USER_REMOVE(u);
	return res;
}
Beispiel #12
0
int AST_OPTIONAL_API_NAME(ast_adsi_transmit_message_full)(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait)
{
	unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
	int msglens[5], msgtypes[5], newdatamode = (ast_channel_adsicpe(chan) & ADSI_FLAG_DATAMODE), res, x, waitforswitch = 0;
	struct ast_format writeformat;
	struct ast_format readformat;

	ast_format_copy(&writeformat, ast_channel_writeformat(chan));
	ast_format_copy(&readformat, ast_channel_readformat(chan));

	for (x = 0; x < msglen; x += (msg[x+1]+2)) {
		if (msg[x] == ADSI_SWITCH_TO_DATA) {
			ast_debug(1, "Switch to data is sent!\n");
			waitforswitch++;
			newdatamode = ADSI_FLAG_DATAMODE;
		}

		if (msg[x] == ADSI_SWITCH_TO_VOICE) {
			ast_debug(1, "Switch to voice is sent!\n");
			waitforswitch++;
			newdatamode = 0;
		}
	}
	msgs[0] = msg;

	msglens[0] = msglen;
	msgtypes[0] = msgtype;

	if (msglen > 253) {
		ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen);
		return -1;
	}

	ast_stopstream(chan);

	if (ast_set_write_format_by_id(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
		return -1;
	}

	if (ast_set_read_format_by_id(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
		if (writeformat.id) {
			if (ast_set_write_format(chan, &writeformat)) {
				ast_log(LOG_WARNING, "Unable to restore write format to %s\n", ast_getformatname(&writeformat));
			}
		}
		return -1;
	}
	res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes);

	if (dowait) {
		ast_debug(1, "Wait for switch is '%d'\n", waitforswitch);
		while (waitforswitch-- && ((res = ast_waitfordigit(chan, 1000)) > 0)) {
			res = 0;
			ast_debug(1, "Waiting for 'B'...\n");
		}
	}

	if (!res) {
		ast_channel_adsicpe_set(chan, (ast_channel_adsicpe(chan) & ~ADSI_FLAG_DATAMODE) | newdatamode);
	}

	if (writeformat.id) {
		ast_set_write_format(chan, &writeformat);
	}
	if (readformat.id) {
		ast_set_read_format(chan, &readformat);
	}

	if (!res) {
		res = ast_safe_sleep(chan, 100 );
	}
	return res;
}
Beispiel #13
0
static int conf_exec(struct ast_channel *chan, void *data)
{
	int res=-1;
	int confflags = 0;
	int confno = 0;
	char confnostr[80] = "", *tmp = NULL;
	struct ast_channel *tempchan = NULL, *lastchan = NULL, *ichan = NULL;
	struct ast_frame *f;
	char *desired_group;
	int input = 0, search_group = 0;

	if (chan->_state != AST_STATE_UP)
		ast_answer(chan);

	desired_group = ast_strdupa(data);
	if (!ast_strlen_zero(desired_group)) {
		ast_verb(3, "Scanning for group %s\n", desired_group);
		search_group = 1;
	}

	for (;;) {
		if (ast_waitfor(chan, 100) < 0)
			break;

		f = ast_read(chan);
		if (!f)
			break;
		if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
			ast_frfree(f);
			break;
		}
		ast_frfree(f);
		ichan = NULL;
		if(input) {
			ichan = get_dahdi_channel_locked(input);
			input = 0;
		}

		tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);

		if (!tempchan && !lastchan) {
			break;
		}

		if (tempchan && search_group) {
			const char *mygroup;
			if ((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) {
				ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group);
			} else {
				ast_channel_unlock(tempchan);
				lastchan = tempchan;
				continue;
			}
		}
		if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan)) {
			ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name);
			ast_copy_string(confnostr, tempchan->name, sizeof(confnostr));
			ast_channel_unlock(tempchan);
			if ((tmp = strchr(confnostr, '-'))) {
				*tmp = '\0';
			}
			confno = atoi(strchr(confnostr, '/') + 1);
			ast_stopstream(chan);
			ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
			res = conf_run(chan, confno, confflags);
			if (res < 0) {
				break;
			}
			input = res;
		} else if (tempchan) {
			ast_channel_unlock(tempchan);
		}
		lastchan = tempchan;
	}
	return res;
}
Beispiel #14
0
static int NBScat_exec(struct ast_channel *chan, const char *data)
{
	int res=0;
	int fds[2];
	int ms = -1;
	int pid = -1;
	struct ast_format owriteformat;
	struct timeval next;
	struct ast_frame *f;
	struct myframe {
		struct ast_frame f;
		char offset[AST_FRIENDLY_OFFSET];
		short frdata[160];
	} myf;

	ast_format_clear(&owriteformat);
	if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
		ast_log(LOG_WARNING, "Unable to create socketpair\n");
		return -1;
	}
	
	ast_stopstream(chan);

	ast_format_copy(&owriteformat, &chan->writeformat);
	res = ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		return -1;
	}
	
	res = NBScatplay(fds[1]);
	/* Wait 1000 ms first */
	next = ast_tvnow();
	next.tv_sec += 1;
	if (res >= 0) {
		pid = res;
		/* Order is important -- there's almost always going to be mp3...  we want to prioritize the
		   user */
		for (;;) {
			ms = ast_tvdiff_ms(next, ast_tvnow());
			if (ms <= 0) {
				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
				if (res > 0) {
					myf.f.frametype = AST_FRAME_VOICE;
					ast_format_set(&myf.f.subclass.format, AST_FORMAT_SLINEAR, 0);
					myf.f.datalen = res;
					myf.f.samples = res / 2;
					myf.f.mallocd = 0;
					myf.f.offset = AST_FRIENDLY_OFFSET;
					myf.f.src = __PRETTY_FUNCTION__;
					myf.f.delivery.tv_sec = 0;
					myf.f.delivery.tv_usec = 0;
					myf.f.data.ptr = myf.frdata;
					if (ast_write(chan, &myf.f) < 0) {
						res = -1;
						break;
					}
				} else {
					ast_debug(1, "No more mp3\n");
					res = 0;
					break;
				}
				next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
			} else {
				ms = ast_waitfor(chan, ms);
				if (ms < 0) {
					ast_debug(1, "Hangup detected\n");
					res = -1;
					break;
				}
				if (ms) {
					f = ast_read(chan);
					if (!f) {
						ast_debug(1, "Null frame == hangup() detected\n");
						res = -1;
						break;
					}
					if (f->frametype == AST_FRAME_DTMF) {
						ast_debug(1, "User pressed a key\n");
						ast_frfree(f);
						res = 0;
						break;
					}
					ast_frfree(f);
				} 
			}
		}
	}
	close(fds[0]);
	close(fds[1]);
	
	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && owriteformat.id)
		ast_set_write_format(chan, &owriteformat);

	return res;
}
static int read_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u;
	char tmp[256];
	char *timeout = NULL;
	char *varname = NULL;
	char *filename = NULL;
	char *loops;
	char *maxdigitstr=NULL;
	char *options=NULL;
	int option_skip = 0;
	int option_noanswer = 0;
	int maxdigits=255;
	int tries = 1;
	int to = 0;
	int x = 0;
	char *argcopy = NULL;
	char *args[8];

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
		return -1;
	}

	LOCAL_USER_ADD(u);
	
	argcopy = ast_strdupa(data);
	if (!argcopy) {
		ast_log(LOG_ERROR, "Out of memory\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	if (ast_app_separate_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
		ast_log(LOG_WARNING, "Cannot Parse Arguments.\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	varname = args[x++];
	filename = args[x++];
	maxdigitstr = args[x++];
	options = args[x++];
	loops = args[x++];
	timeout = args[x++];
	
	if (options) { 
		if (!strcasecmp(options, "skip"))
			option_skip = 1;
		else if (!strcasecmp(options, "noanswer"))
			option_noanswer = 1;
		else {
			if (strchr(options, 's'))
				option_skip = 1;
			if (strchr(options, 'n'))
				option_noanswer = 1;
		}
	}

	if(loops) {
		tries = atoi(loops);
		if(tries <= 0)
			tries = 1;
	}

	if(timeout) {
		to = atoi(timeout);
		if (to <= 0)
			to = 0;
		else
			to *= 1000;
	}

	if (ast_strlen_zero(filename)) 
		filename = NULL;
	if (maxdigitstr) {
		maxdigits = atoi(maxdigitstr);
		if ((maxdigits<1) || (maxdigits>255)) {
    			maxdigits = 255;
		} else if (option_verbose > 2)
			ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %d digits.\n", maxdigits);
	}
	if (ast_strlen_zero(varname)) {
		ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	if (chan->_state != AST_STATE_UP) {
		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);
		}
	}
	if (!res) {
		while(tries && !res) {
			ast_stopstream(chan);
			res = ast_app_getdata(chan, filename, tmp, maxdigits, to);
			if (res > -1) {
				pbx_builtin_setvar_helper(chan, varname, tmp);
				if (!ast_strlen_zero(tmp)) {
					if (option_verbose > 2)
						ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
					tries = 0;
				} else {
					tries--;
					if (option_verbose > 2) {
						if (tries)
							ast_verbose(VERBOSE_PREFIX_3 "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
						else
							ast_verbose(VERBOSE_PREFIX_3 "User entered nothing.\n");
					}
				}
				res = 0;
			} else {
				if (option_verbose > 2)
					ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
			}
		}
	}
	LOCAL_USER_REMOVE(u);
	return res;
}
Beispiel #16
0
/*! \brief SpeechBackground(Sound File|Timeout) Dialplan Application */
static int speech_background(struct ast_channel *chan, void *data)
{
        unsigned int timeout = 0;
        int res = 0, done = 0, argc = 0, started = 0, quieted = 0, max_dtmf_len = 0;
        struct ast_module_user *u = NULL;
        struct ast_speech *speech = find_speech(chan);
        struct ast_frame *f = NULL;
        int oldreadformat = AST_FORMAT_SLINEAR;
        char dtmf[AST_MAX_EXTENSION] = "";
        time_t start, current;
        struct ast_datastore *datastore = NULL;
        char *argv[2], *args = NULL, *filename_tmp = NULL, *filename = NULL, tmp[2] = "", dtmf_terminator = '#';
	const char *tmp2 = NULL;

        args = ast_strdupa(data);

        u = ast_module_user_add(chan);

        if (speech == NULL) {
                ast_module_user_remove(u);
                return -1;
        }

	/* If channel is not already answered, then answer it */
	if (chan->_state != AST_STATE_UP && ast_answer(chan)) {
		ast_module_user_remove(u);
		return -1;
	}

        /* Record old read format */
        oldreadformat = chan->readformat;

        /* Change read format to be signed linear */
        if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
                ast_module_user_remove(u);
                return -1;
        }

        /* Parse out options */
        argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
        if (argc > 0) {
                /* Yay sound file */
                filename_tmp = ast_strdupa(argv[0]);
		if (!ast_strlen_zero(argv[1])) {
			if ((timeout = atoi(argv[1])) == 0)
				timeout = -1;
		} else
			timeout = 0;
        }

	/* See if the maximum DTMF length variable is set... we use a variable in case they want to carry it through their entire dialplan */
	if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_MAXLEN")) && !ast_strlen_zero(tmp2))
		max_dtmf_len = atoi(tmp2);

	/* See if a terminator is specified */
	if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_TERMINATOR"))) {
		if (ast_strlen_zero(tmp2))
			dtmf_terminator = '\0';
		else
			dtmf_terminator = tmp2[0];
	}

        /* Before we go into waiting for stuff... make sure the structure is ready, if not - start it again */
        if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
                ast_speech_start(speech);
        }

	/* Ensure no streams are currently running */
	ast_stopstream(chan);

        /* Okay it's streaming so go into a loop grabbing frames! */
        while (done == 0) {
		/* If the filename is null and stream is not running, start up a new sound file */
		if (!quieted && (chan->streamid == -1 && chan->timingfunc == NULL) && (filename = strsep(&filename_tmp, "&"))) {
			/* Discard old stream information */
			ast_stopstream(chan);
			/* Start new stream */
			speech_streamfile(chan, filename, chan->language);
		}

                /* Run scheduled stuff */
                ast_sched_runq(chan->sched);

                /* Yay scheduling */
                res = ast_sched_wait(chan->sched);
                if (res < 0) {
                        res = 1000;
                }

                /* If there is a frame waiting, get it - if not - oh well */
                if (ast_waitfor(chan, res) > 0) {
                        f = ast_read(chan);
                        if (f == NULL) {
                                /* The channel has hung up most likely */
                                done = 3;
                                break;
                        }
                }

		/* Do timeout check (shared between audio/dtmf) */
		if ((!quieted || strlen(dtmf)) && started == 1) {
			time(&current);
			if ((current-start) >= timeout) {
				done = 1;
				if (f)
					ast_frfree(f);
				break;
			}
		}

                /* Do checks on speech structure to see if it's changed */
                ast_mutex_lock(&speech->lock);
                if (ast_test_flag(speech, AST_SPEECH_QUIET)) {
			if (chan->stream)
				ast_stopstream(chan);
			ast_clear_flag(speech, AST_SPEECH_QUIET);
			quieted = 1;
                }
                /* Check state so we can see what to do */
                switch (speech->state) {
                case AST_SPEECH_STATE_READY:
                        /* If audio playback has stopped do a check for timeout purposes */
                        if (chan->streamid == -1 && chan->timingfunc == NULL)
                                ast_stopstream(chan);
                        if (!quieted && chan->stream == NULL && timeout && started == 0 && !filename_tmp) {
				if (timeout == -1) {
					done = 1;
					if (f)
						ast_frfree(f);
					break;
				}
				time(&start);
				started = 1;
                        }
                        /* Write audio frame out to speech engine if no DTMF has been received */
                        if (!strlen(dtmf) && f != NULL && f->frametype == AST_FRAME_VOICE) {
                                ast_speech_write(speech, f->data, f->datalen);
                        }
                        break;
                case AST_SPEECH_STATE_WAIT:
                        /* Cue up waiting sound if not already playing */
			if (!strlen(dtmf)) {
				if (chan->stream == NULL) {
					if (speech->processing_sound != NULL) {
						if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
							speech_streamfile(chan, speech->processing_sound, chan->language);
						}
					}
				} else if (chan->streamid == -1 && chan->timingfunc == NULL) {
					ast_stopstream(chan);
					if (speech->processing_sound != NULL) {
						if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
							speech_streamfile(chan, speech->processing_sound, chan->language);
						}
					}
				}
			}
                        break;
                case AST_SPEECH_STATE_DONE:
			/* Now that we are done... let's switch back to not ready state */
			ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
			if (!strlen(dtmf)) {
				/* Copy to speech structure the results, if available */
				speech->results = ast_speech_results_get(speech);
				/* Break out of our background too */
				done = 1;
				/* Stop audio playback */
				if (chan->stream != NULL) {
					ast_stopstream(chan);
				}
			}
                        break;
                default:
                        break;
                }
                ast_mutex_unlock(&speech->lock);

                /* Deal with other frame types */
                if (f != NULL) {
                        /* Free the frame we received */
                        switch (f->frametype) {
                        case AST_FRAME_DTMF:
				if (dtmf_terminator != '\0' && f->subclass == dtmf_terminator) {
					done = 1;
				} else {
					if (chan->stream != NULL) {
						ast_stopstream(chan);
					}
					if (!started) {
						/* Change timeout to be 5 seconds for DTMF input */
						timeout = (chan->pbx && chan->pbx->dtimeout) ? chan->pbx->dtimeout : 5;
						started = 1;
					}
					time(&start);
					snprintf(tmp, sizeof(tmp), "%c", f->subclass);
					strncat(dtmf, tmp, sizeof(dtmf) - strlen(dtmf) - 1);
					/* If the maximum length of the DTMF has been reached, stop now */
					if (max_dtmf_len && strlen(dtmf) == max_dtmf_len)
						done = 1;
				}
                                break;
                        case AST_FRAME_CONTROL:
                                switch (f->subclass) {
                                case AST_CONTROL_HANGUP:
                                        /* Since they hung up we should destroy the speech structure */
                                        done = 3;
                                default:
                                        break;
                                }
                        default:
                                break;
                        }
                        ast_frfree(f);
                        f = NULL;
                }
        }

	if (strlen(dtmf)) {
		/* We sort of make a results entry */
		speech->results = ast_calloc(1, sizeof(*speech->results));
		if (speech->results != NULL) {
			ast_speech_dtmf(speech, dtmf);
			speech->results->score = 1000;
			speech->results->text = strdup(dtmf);
			speech->results->grammar = strdup("dtmf");
		}
		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
	}

        /* See if it was because they hung up */
        if (done == 3) {
                /* Destroy speech structure */
                ast_speech_destroy(speech);
                datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
                if (datastore != NULL) {
                        ast_channel_datastore_remove(chan, datastore);
                }
        } else {
                /* Channel is okay so restore read format */
                ast_set_read_format(chan, oldreadformat);
        }

        ast_module_user_remove(u);

        return 0;
}
Beispiel #17
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 ast_channel *chan, char *context,
		char *dialcontext, char *ext, char *name, int readext,
		int fromappvm)
{
	int res = 0;
	int loop;
	char fn[256];

	/* Check for the VoiceMail2 greeting first */
	snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
		ast_config_AST_SPOOL_DIR, context, ext);
#ifdef ODBC_STORAGE
	retrieve_file(fn);
#endif

	if (ast_fileexists(fn, NULL, chan->language) <= 0) {
		/* no file, check for an old-style Voicemail greeting */
		snprintf(fn, sizeof(fn), "%s/vm/%s/greet",
			ast_config_AST_SPOOL_DIR, ext);
	}
#ifdef ODBC_STORAGE
	retrieve_file(fn);
#endif

	if (ast_fileexists(fn, NULL, chan->language) > 0) {
		res = ast_stream_and_wait(chan, fn, chan->language, AST_DIGIT_ANY);
		ast_stopstream(chan);
		/* If Option 'e' was specified, also read the extension number with the name */
		if (readext) {
			ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY);
			res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
		}
	} else {
		res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language);
		if (!ast_strlen_zero(name) && readext) {
			ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY);
			res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
		}
	}
#ifdef ODBC_STORAGE
	ast_filedelete(fn, NULL);	
#endif

	for (loop = 3 ; loop > 0; loop--) {
		if (!res)
			res = ast_stream_and_wait(chan, "dir-instr", chan->language, AST_DIGIT_ANY);
		if (!res)
			res = ast_waitfordigit(chan, 3000);
		ast_stopstream(chan);
	
		if (res < 0) /* User hungup, so jump out now */
			break;
		if (res == '1') {	/* Name selected */
			if (fromappvm) {
				/* We still want to set the exten though */
				ast_copy_string(chan->exten, ext, sizeof(chan->exten));
			} else {
				if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
					ast_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;
		}
		if (res == '*') /* Skip to next match in list */
			break;

		/* Not '1', or '*', so decrement number of tries */
		res = 0;
	}

	return(res);
}
Beispiel #18
0
int ast_control_streamfile(struct ast_channel *chan, char *file, char *fwd, char *rev, char *stop, char *pause, int skipms)
{
    struct timeval started, ended;
    long elapsed = 0,last_elapsed =0;
    char *breaks=NULL;
    char *end=NULL;
    int blen=2;
    int res=0;

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

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

    if (chan)
        ast_stopstream(chan);


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

    for (;;) {
        gettimeofday(&started,NULL);

        if (chan)
            ast_stopstream(chan);
        res = ast_streamfile(chan, file, chan->language);
        if (!res) {
            if (end) {
                ast_seekstream(chan->stream, 0, SEEK_END);
                end=NULL;
            }
            res = 1;
            if (elapsed) {
                ast_stream_fastforward(chan->stream, elapsed);
                last_elapsed = elapsed - 200;
            }
            if (res)
                res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
            else
                break;
        }

        if (res < 1)
            break;

        if (pause != NULL && strchr(pause, res)) {
            gettimeofday(&ended, NULL);
            elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
            for(;;) {
                if (chan)
                    ast_stopstream(chan);
                res = ast_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)
        ast_stopstream(chan);

    return res;
}
static int nv_background_detect_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	char tmp[256] = "\0";
	char *p = NULL;
	char *filename = NULL;
	char *options = NULL;
	char *silstr = NULL;
	char *minstr = NULL;
	char *maxstr = NULL;
	struct ast_frame *fr = NULL;
	struct ast_frame *fr2 = NULL;
	int notsilent = 0;
	struct timeval start = {0, 0}, end = {0, 0};
	int sildur = 1000;
	int mindur = 100;
	int maxdur = -1;
	int skipanswer = 0;
	int noextneeded = 0;
	int ignoredtmf = 0;
	int ignorefax = 0;
	int ignoretalk = 0;
	int x = 0;
	struct ast_format* origrformat = NULL;
	int features = 0;
	struct ast_dsp *dsp = NULL;
	struct ast_format_cap *cap;
	struct ast_format linearFormat;
	
	/* linear format capabilities */
	ast_format_set(&linearFormat, AST_FORMAT_SLINEAR, 0);
	cap = ast_format_cap_alloc_nolock();
	ast_format_cap_add(cap, &linearFormat);
	/* done */
	
	pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "FAXEXTEN", "");
	pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "TALK_DETECTED", "");
	
	if (!data || ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "NVBackgroundDetect requires an argument (filename)\n");
		return -1;
	}	
	
	strncpy(tmp, data, sizeof(tmp)-1);
	p = tmp;
	
	filename = strsep(&p, ",");
	options = strsep(&p, ",");
	silstr = strsep(&p, ",");
	minstr = strsep(&p, ",");	
	maxstr = strsep(&p, ",");	
	
	if (options) {
		if (strchr(options, 'n'))
			skipanswer = 1;
		if (strchr(options, 'x'))
			noextneeded = 1;
		if (strchr(options, 'd'))
			ignoredtmf = 1;
		if (strchr(options, 'f'))
			ignorefax = 1;
		if (strchr(options, 't'))
			ignoretalk = 1;
	}
	
	if (silstr) {
		if ((sscanf(silstr, "%d", &x) == 1) && (x > 0))
			sildur = x;
	}
	
	if (minstr) {
		if ((sscanf(minstr, "%d", &x) == 1) && (x > 0))
			mindur = x;
	}
	
	if (maxstr) {
		if ((sscanf(maxstr, "%d", &x) == 1) && (x > 0))
			maxdur = x;
	}
	
	ast_log(LOG_DEBUG, "Preparing detect of '%s' (sildur=%dms, mindur=%dms, maxdur=%dms)\n", tmp, sildur, mindur, maxdur);
						
	//	LOCAL_USER_ADD(u);
	if (ast_channel_state(chan) != AST_STATE_UP && !skipanswer) {
		/* Otherwise answer unless we're supposed to send this while on-hook */
		res = ast_answer(chan);
	}
	if (!res) {
		origrformat = ast_channel_readformat(chan); //chan->readformat;
		
// 		if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR))) 
// 			ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
		
		if ((res = ast_set_read_format_from_cap(chan, cap)) ){
			ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
		}
		
		
		
	}
	if (!(dsp = ast_dsp_new())) {
		ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
		res = -1;
	}

	if (dsp) {	
		if (!ignoretalk)
			; /* features |= DSP_FEATURE_SILENCE_SUPPRESS; */
		if (!ignorefax)
			features |= DSP_FEATURE_FAX_DETECT;
		//if (!ignoredtmf)
			features |= DSP_FEATURE_DIGIT_DETECT;
			
		ast_dsp_set_threshold(dsp, 256);
		ast_dsp_set_features(dsp, features | DSP_DIGITMODE_RELAXDTMF);
		ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_DTMF);
	}
	
	if (!res) {
		ast_stopstream(chan);
// 		res = ast_streamfile(chan, tmp, chan->language);
		res = ast_streamfile(chan, tmp, ast_channel_language(chan));
		if (!res) {
// 			while(chan->stream) {
			while( ast_channel_stream(chan) ) {
// 				res = ast_sched_wait(chan->sched);
				res = ast_sched_wait( ast_channel_sched(chan) );
// 				if ((res < 0) && !chan->timingfunc) {
				if ((res < 0) && !ast_channel_timingfunc(chan)) {
					res = 0;
					break;
				}
				if (res < 0)
					res = 1000;
				res = ast_waitfor(chan, res);
				if (res < 0) {
// 					ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
					ast_log(LOG_WARNING, "Waitfor failed on %s\n", ast_channel_name(chan));
					break;
				} else if (res > 0) {
					fr = ast_read(chan);
					if (!fr) {
						ast_log(LOG_DEBUG, "Got hangup\n");
						res = -1;
						break;
					}
					
					fr2 = ast_dsp_process(chan, dsp, fr);
					if (!fr2) {
						ast_log(LOG_WARNING, "Bad DSP received (what happened!!)\n");
						fr2 = fr;
					} 
					
					if (fr2->frametype == AST_FRAME_DTMF) {
// 						if (fr2->subclass == 'f' && !ignorefax) {
						if (fr2->subclass.integer == 'f' && !ignorefax) {
							/* Fax tone -- Handle and return NULL */
// 							ast_log(LOG_DEBUG, "Fax detected on %s\n", chan->name);
							ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan));
// 							if (strcmp(chan->exten, "fax")) {
							if (strcmp(ast_channel_exten(chan), "fax")) {
								ast_log(LOG_NOTICE, "Redirecting %s to fax extension\n", ast_channel_name(chan));
								pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "1");
// 								pbx_builtin_setvar_helper(chan,"FAXEXTEN",chan->exten);
								pbx_builtin_setvar_helper(chan,"FAXEXTEN", ast_channel_exten(chan));
// 								if (ast_exists_extension(chan, chan->context, "fax", 1, chan->CALLERID_FIELD)) {
								if (ast_exists_extension(chan, ast_channel_context(chan), "fax", 1, ast_channel_caller(chan)->id.number.str)) {
									/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
// 									strncpy(chan->exten, "fax", sizeof(chan->exten)-1);
// 									chan->priority = 0;
									ast_channel_exten_set(chan, "fax");
									ast_channel_priority_set(chan, 0);
								} else
									ast_log(LOG_WARNING, "Fax detected, but no fax extension\n");
							} else
								ast_log(LOG_WARNING, "Already in a fax extension, not redirecting\n");

							res = 0;
							ast_frfree(fr);
							break;
						} else if (!ignoredtmf) {
							ast_log(LOG_DEBUG, "DTMF detected on %s\n", ast_channel_name(chan));
							char t[2];
// 							t[0] = fr2->subclass;
							t[0] = fr2->subclass.integer;
							t[1] = '\0';
// 							if (noextneeded || ast_canmatch_extension(chan, chan->context, t, 1, chan->CALLERID_FIELD)) {
							if (noextneeded || ast_canmatch_extension(chan, ast_channel_context(chan), t, 1, ast_channel_caller(chan)->id.number.str)) {
								pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "1");
								/* They entered a valid extension, or might be anyhow */
								if (noextneeded) {
									ast_log(LOG_NOTICE, "DTMF received (not matching to exten)\n");
									res = 0;
								} else {
									ast_log(LOG_NOTICE, "DTMF received (matching to exten)\n");
// 									res = fr2->subclass;
									res = fr2->subclass.integer;
								}
								ast_frfree(fr);
								break;
							} else
								ast_log(LOG_DEBUG, "Valid extension requested and DTMF did not match\n");
						}
// 					} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && !ignoretalk) {
					} else if ((fr->frametype == AST_FRAME_VOICE) && ( ast_format_cap_iscompatible(cap, &fr->subclass.format)) && !ignoretalk) {
						int totalsilence;
						int ms;
						res = ast_dsp_silence(dsp, fr, &totalsilence);
						if (res && (totalsilence > sildur)) {
							/* We've been quiet a little while */
							if (notsilent) {
								/* We had heard some talking */
								gettimeofday(&end, NULL);
								ms = (end.tv_sec - start.tv_sec) * 1000;
								ms += (end.tv_usec - start.tv_usec) / 1000;
								ms -= sildur;
								if (ms < 0)
									ms = 0;
								if ((ms > mindur) && ((maxdur < 0) || (ms < maxdur))) {
									char ms_str[10];
									ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
// 									ast_log(LOG_NOTICE, "Redirecting %s to talk extension\n", chan->name);
									ast_log(LOG_NOTICE, "Redirecting %s to talk extension\n", ast_channel_name(chan));

									/* Save detected talk time (in milliseconds) */ 
									sprintf(ms_str, "%d", ms);	
									pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);
									
// 									if (ast_exists_extension(chan, chan->context, "talk", 1, chan->CALLERID_FIELD)) {
									if (ast_exists_extension(chan, ast_channel_context(chan), "talk", 1, ast_channel_caller(chan)->id.number.str)) {
// 										strncpy(chan->exten, "talk", sizeof(chan->exten) - 1);
// 										chan->priority = 0;
										ast_channel_exten_set(chan, "talk");
										ast_channel_priority_set(chan, 0);
									} else
										ast_log(LOG_WARNING, "Talk detected, but no talk extension\n");
									res = 0;
									ast_frfree(fr);
									break;
								} else
									ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
								notsilent = 0;
							}
						} else {
							if (!notsilent) {
								/* Heard some audio, mark the begining of the token */
								gettimeofday(&start, NULL);
								ast_log(LOG_DEBUG, "Start of voice token!\n");
								notsilent = 1;
							}
						}						
					}
					ast_frfree(fr);
				}
// 				ast_sched_runq(chan->sched);
				ast_sched_runq( ast_channel_sched(chan) );
			}
			ast_stopstream(chan);
		} else {
// 			ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
			ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", ast_channel_name(chan), (char *)data);
			res = 0;
		}
	} else
// 		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan));
	
	if (res > -1) {
		if (origrformat && ast_set_read_format(chan, origrformat)) {
// 			ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", chan->name, ast_getformatname(origrformat));
			ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", ast_channel_name(chan), ast_getformatname(origrformat));
		}
	}
	
	if (dsp)
		ast_dsp_free(dsp);
	
	//	LOCAL_USER_REMOVE(u);
	
	ast_format_cap_destroy(cap);
	return res;
}
static int mp3_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct localuser *u;
	int fds[2];
	int ms = -1;
	int pid = -1;
	int owriteformat;
	int timeout = 2000;
	struct timeval next;
	struct ast_frame *f;
	struct myframe {
		struct ast_frame f;
		char offset[AST_FRIENDLY_OFFSET];
		short frdata[160];
	} myf;
	
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	ast_stopstream(chan);

	owriteformat = chan->writeformat;
	res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	res = mp3play((char *)data, fds[1]);
	if (!strncasecmp((char *)data, "http://", 7)) {
		timeout = 10000;
	}
	/* Wait 1000 ms first */
	next = ast_tvnow();
	next.tv_sec += 1;
	if (res >= 0) {
		pid = res;
		/* Order is important -- there's almost always going to be mp3...  we want to prioritize the
		   user */
		for (;;) {
			ms = ast_tvdiff_ms(next, ast_tvnow());
			if (ms <= 0) {
				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
				if (res > 0) {
					myf.f.frametype = AST_FRAME_VOICE;
					myf.f.subclass = AST_FORMAT_SLINEAR;
					myf.f.datalen = res;
					myf.f.samples = res / 2;
					myf.f.mallocd = 0;
					myf.f.offset = AST_FRIENDLY_OFFSET;
					myf.f.src = __PRETTY_FUNCTION__;
					myf.f.delivery.tv_sec = 0;
					myf.f.delivery.tv_usec = 0;
					myf.f.data = myf.frdata;
					if (ast_write(chan, &myf.f) < 0) {
						res = -1;
						break;
					}
				} else {
					ast_log(LOG_DEBUG, "No more mp3\n");
					res = 0;
					break;
				}
				next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
			} else {
				ms = ast_waitfor(chan, ms);
				if (ms < 0) {
					ast_log(LOG_DEBUG, "Hangup detected\n");
					res = -1;
					break;
				}
				if (ms) {
					f = ast_read(chan);
					if (!f) {
						ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
						res = -1;
						break;
					}
					if (f->frametype == AST_FRAME_DTMF) {
						ast_log(LOG_DEBUG, "User pressed a key\n");
						ast_frfree(f);
						res = 0;
						break;
					}
					ast_frfree(f);
				} 
			}
		}
	}
	close(fds[0]);
	close(fds[1]);
	
	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && owriteformat)
		ast_set_write_format(chan, owriteformat);

	LOCAL_USER_REMOVE(u);
	
	return res;
}
Beispiel #21
0
static int ices_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	int fds[2];
	int ms = -1;
	int pid = -1;
	int flags;
	struct ast_format oreadformat;
	struct ast_frame *f;
	char filename[256]="";
	char *c;

	ast_format_clear(&oreadformat);
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
		return -1;
	}
	
	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		return -1;
	}
	flags = fcntl(fds[1], F_GETFL);
	fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
	
	ast_stopstream(chan);

	if (ast_channel_state(chan) != AST_STATE_UP)
		res = ast_answer(chan);
		
	if (res) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Answer failed!\n");
		return -1;
	}

	ast_format_copy(&oreadformat, ast_channel_readformat(chan));
	res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		return -1;
	}
	if (((char *)data)[0] == '/')
		ast_copy_string(filename, (char *) data, sizeof(filename));
	else
		snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
	/* Placeholder for options */		
	c = strchr(filename, '|');
	if (c)
		*c = '\0';	
	res = icesencode(filename, fds[0]);
	if (res >= 0) {
		pid = res;
		for (;;) {
			/* Wait for audio, and stream */
			ms = ast_waitfor(chan, -1);
			if (ms < 0) {
				ast_debug(1, "Hangup detected\n");
				res = -1;
				break;
			}
			f = ast_read(chan);
			if (!f) {
				ast_debug(1, "Null frame == hangup() detected\n");
				res = -1;
				break;
			}
			if (f->frametype == AST_FRAME_VOICE) {
				res = write(fds[1], f->data.ptr, f->datalen);
				if (res < 0) {
					if (errno != EAGAIN) {
						ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
						res = -1;
						ast_frfree(f);
						break;
					}
				}
			}
			ast_frfree(f);
		}
	}
	close(fds[0]);
	close(fds[1]);

	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && oreadformat.id)
		ast_set_read_format(chan, &oreadformat);

	return res;
}
Beispiel #22
0
static void *dialstring(void *string)
{
	struct ast_channel *channel;
	char *bufptr,*destptr;
	int  ms=10000;		/* ms affects number of rings */
	int  cnt=0,first;
	char tech[256];
	char tele[256];
	char filename[256];
	int  answered=0;

	for(first=0, bufptr=(char *)string, destptr=tech; *bufptr&&cnt<256; cnt++){
		if(*bufptr=='/' && !first) {
			*destptr=0;
			destptr=tele;
			first=1;
		}
		else if(*bufptr==',') {
			*destptr=0;
			destptr=filename;
		} else {
			*destptr=*bufptr;
			destptr++;
		}
		bufptr++;
	} 
	*destptr=0;
	ast_log(LOG_DEBUG, "Printing string arg: %s Eos\n", (char *)string);
	if(strlen(tech)+strlen(tele)+strlen(filename) > 256) {
		ast_log(LOG_ERROR, "Autodial:Error string too long\n");
		free(string);
		pthread_exit(NULL);
	}
	ast_log(LOG_DEBUG, "Autodial Tech %s(%d) Tele %s(%d) Filename %s(%d)\n",tech, (int)strlen(tech), tele, (int)strlen(tele), filename, (int)strlen(filename));

	channel=ast_request(tech,AST_FORMAT_SLINEAR,tele);
	if(channel!=NULL){
		ast_call(channel,tele,10000);
	} else {
		ast_log(LOG_ERROR, "Autodial:Sorry unable to obtain channel\n");
		free(string);
		pthread_exit(NULL);
	}
	if(channel->_state==AST_STATE_UP)
		ast_log(LOG_DEBUG, "Autodial:Line is Up\n");
	while(ms>0){
		struct ast_frame *f;

		ms=ast_waitfor(channel,ms);
		f=ast_read(channel);
		if(!f){
			ast_log(LOG_DEBUG, "Autodial:Hung Up\n");
			break;
		}
		if (f->frametype==AST_FRAME_CONTROL) {
			if (f->subclass==AST_CONTROL_ANSWER) {
				ast_log(LOG_DEBUG, "Autodial:Phone Answered\n");
				if (channel->_state==AST_STATE_UP) {
					char res;

					ast_streamfile(channel,filename,0);
					/* Press Five for snooze */
					res=ast_waitstream(channel, "37");
					if(res=='3'){
						answered=1;
						set_snooze_alarm((char *)string,60);
						ast_streamfile(channel,"demo-thanks",0);
						ast_waitstream(channel, "");
					}
					else if(res=='7'){
						answered=1;
						ast_streamfile(channel,"demo-thanks",0);
						ast_waitstream(channel, "");
					}
					ast_stopstream(channel);
					ms=0;
				}
			}
			else if (f->subclass==AST_CONTROL_RINGING)
				ast_log(LOG_DEBUG, "Autodial:Phone Ringing end\n");
		}
		ast_frfree(f);
	}
	if(!answered)
		set_snooze_alarm((char *) string, 5);
	free(string);
	ast_hangup(channel);
	ast_log(LOG_DEBUG, "Autodial:Hung up channel\n");
	pthread_exit(NULL);
	return NULL;
}
/* 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 ast_channel *chan, char *context, char *dialcontext, char *ext, char *name, int fromappvm) {
	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 *)ast_config_AST_SPOOL_DIR, context, ext);
#ifdef USE_ODBC_STORAGE
	retrieve_file(fn);
#endif

	/* Otherwise, check for an old-style Voicemail greeting */
	snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
		(char *)ast_config_AST_SPOOL_DIR, ext);
#ifdef USE_ODBC_STORAGE
	retrieve_file(fn2);
#endif

	if (ast_fileexists(fn, NULL, chan->language) > 0) {
		res = ast_streamfile(chan, fn, chan->language);
		if (!res) {
			res = ast_waitstream(chan, AST_DIGIT_ANY);
		}
		ast_stopstream(chan);
	} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
		res = ast_streamfile(chan, fn2, chan->language);
		if (!res) {
			res = ast_waitstream(chan, AST_DIGIT_ANY);
		}
		ast_stopstream(chan);
	} else {
		res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext,
					AST_DIGIT_ANY, chan->language);
	}
#ifdef USE_ODBC_STORAGE
	ast_filedelete(fn, NULL);	
	ast_filedelete(fn2, NULL);	
#endif

	while (loop) {
		if (!res) {
			res = ast_streamfile(chan, "dir-instr", chan->language);
		}
		if (!res) {
			res = ast_waitstream(chan, AST_DIGIT_ANY);
		}
		if (!res) {
			res = ast_waitfordigit(chan, 3000);
		}
		ast_stopstream(chan);
	
		if (res > -1) {
			switch (res) {
				case '1':
					/* Name selected */
					loop = 0;
					if (fromappvm) {
						/* We still want to set the exten */
						ast_copy_string(chan->exten, ext, sizeof(chan->exten));
					} else {
						if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
							ast_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);
}
Beispiel #24
0
static int ices_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct localuser *u;
	int fds[2];
	int ms = -1;
	int pid = -1;
	int flags;
	int oreadformat;
	struct timeval last;
	struct ast_frame *f;
	char filename[256]="";
	char *c;
	last.tv_usec = 0;
	last.tv_sec = 0;
	if (!data || !strlen(data)) {
		ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
		return -1;
	}
	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		return -1;
	}
	flags = fcntl(fds[1], F_GETFL);
	fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
	
	LOCAL_USER_ADD(u);
	ast_stopstream(chan);

	if (chan->_state != AST_STATE_UP)
		res = ast_answer(chan);
		
	if (res) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Answer failed!\n");
		return -1;
	}

	oreadformat = chan->readformat;
	res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		return -1;
	}
	if (((char *)data)[0] == '/')
		strncpy(filename, (char *)data, sizeof(filename) - 1);
	else
		snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
	/* Placeholder for options */		
	c = strchr(filename, '|');
	if (c)
		*c = '\0';	
	res = icesencode(filename, fds[0]);
	close(fds[0]);
	if (res >= 0) {
		pid = res;
		for (;;) {
			/* Wait for audio, and stream */
			ms = ast_waitfor(chan, -1);
			if (ms < 0) {
				ast_log(LOG_DEBUG, "Hangup detected\n");
				res = -1;
				break;
			}
			f = ast_read(chan);
			if (!f) {
				ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
				res = -1;
				break;
			}
			if (f->frametype == AST_FRAME_VOICE) {
				res = write(fds[1], f->data, f->datalen);
				if (res < 0) {
					if (errno != EAGAIN) {
						ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
						res = -1;
						break;
					}
				}
			}
			ast_frfree(f);
		}
	}
	close(fds[1]);
	LOCAL_USER_REMOVE(u);
	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && oreadformat)
		ast_set_read_format(chan, oreadformat);
	return res;
}
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys) {
    int res=0;
    int fds[2];
    int ms = -1;
    int pid = -1;
    int needed = 0;
    int owriteformat;
    struct ast_frame *f;
    struct myframe {
        struct ast_frame f;
        char offset[AST_FRIENDLY_OFFSET];
        char frdata[2048];
    } myf;

    if (pipe(fds)) {
        ast_log(LOG_WARNING, "Unable to create pipe\n");
        return -1;
    }

    /* Answer if it's not already going */
    if (chan->_state != AST_STATE_UP)
        ast_answer(chan);
    ast_stopstream(chan);
    ast_indicate(chan, -1);

    owriteformat = chan->writeformat;
    res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
    if (res < 0) {
        ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
        return -1;
    }

    res=send_waveform_to_fd(waveform,length,fds[1]);
    if (res >= 0) {
        pid = res;
        /* Order is important -- there's almost always going to be mp3...  we want to prioritize the
           user */
        for (;;) {
            ms = 1000;
            res = ast_waitfor(chan, ms);
            if (res < 1) {
                res = -1;
                break;
            }
            f = ast_read(chan);
            if (!f) {
                ast_log(LOG_WARNING, "Null frame == hangup() detected\n");
                res = -1;
                break;
            }
            if (f->frametype == AST_FRAME_DTMF) {
                ast_log(LOG_DEBUG, "User pressed a key\n");
                if (intkeys && strchr(intkeys, f->subclass)) {
                    res = f->subclass;
                    ast_frfree(f);
                    break;
                }
            }
            if (f->frametype == AST_FRAME_VOICE) {
                /* Treat as a generator */
                needed = f->samples * 2;
                if (needed > sizeof(myf.frdata)) {
                    ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
                            (int)sizeof(myf.frdata) / 2, needed/2);
                    needed = sizeof(myf.frdata);
                }
                res = read(fds[0], myf.frdata, needed);
                if (res > 0) {
                    myf.f.frametype = AST_FRAME_VOICE;
                    myf.f.subclass = AST_FORMAT_SLINEAR;
                    myf.f.datalen = res;
                    myf.f.samples = res / 2;
                    myf.f.mallocd = 0;
                    myf.f.offset = AST_FRIENDLY_OFFSET;
                    myf.f.src = __PRETTY_FUNCTION__;
                    myf.f.data = myf.frdata;
                    if (ast_write(chan, &myf.f) < 0) {
                        res = -1;
                        ast_frfree(f);
                        break;
                    }
                    if (res < needed) { /* last frame */
                        ast_log(LOG_DEBUG, "Last frame\n");
                        res=0;
                        ast_frfree(f);
                        break;
                    }
                } else {
                    ast_log(LOG_DEBUG, "No more waveform\n");
                    res = 0;
                }
            }
            ast_frfree(f);
        }
    }
    close(fds[0]);
    close(fds[1]);

    /*	if (pid > -1) */
    /*		kill(pid, SIGKILL); */
    if (!res && owriteformat)
        ast_set_write_format(chan, owriteformat);
    return res;
}
Beispiel #26
0
static int app_exec(struct ast_channel *chan, void *data)
{
	int res = 0, argc = 0, max_digits = 0, timeout = 0, alreadyran = 0, old_writeformat = 0;
	int ms, len, availatend;
	char *argv[3], *parse = NULL, *text = NULL, *rc = NULL;
	char tmp_exten[2], results[20];
	struct ast_module_user *u;
	struct ast_frame *f;
	struct timeval next;
	struct stuff *ps;

	struct myframe {
		struct ast_frame f;
		unsigned char offset[AST_FRIENDLY_OFFSET];
		unsigned char frdata[framesize];
	} myf;

	swift_engine *engine;
	swift_port *port = NULL;
	swift_voice *voice;
	swift_params *params;
	swift_result_t sresult;
	swift_background_t tts_stream;
	unsigned int event_mask;

	memset(results, 0 ,20);
	memset(tmp_exten, 0, 2);
	memset(argv, 0, 3);

	parse = ast_strdupa(data);
	u = ast_module_user_add(chan);
	argc = ast_app_separate_args(parse, ',', argv, 3);
	text = argv[0];

	if (!ast_strlen_zero(argv[1])) {
		timeout = strtol(argv[1], NULL, 0);
	}
	if (!ast_strlen_zero(argv[2])) {
		max_digits = strtol(argv[2], NULL, 0);
	}
	if (ast_strlen_zero(text)) {
		ast_log(LOG_WARNING, "%s requires text to speak!\n", app);
		return -1;
	}
	if (!ast_strlen_zero(text)) {
		ast_log(LOG_DEBUG, "Text to Speak : %s\n", text);
	}
	if (timeout > 0) {
		ast_log(LOG_DEBUG, "Timeout : %d\n", timeout);
	}
	if (max_digits > 0) {
		ast_log(LOG_DEBUG, "Max Digits : %d\n", max_digits);
	}

	ps = malloc(sizeof(struct stuff));
	swift_init_stuff(ps);

	/* Setup synthesis */

	if ((engine = swift_engine_open(NULL)) == NULL) {
		ast_log(LOG_ERROR, "Failed to open Swift Engine.\n");
		goto exception;
	}

	params = swift_params_new(NULL);
	swift_params_set_string(params, "audio/encoding", "ulaw");
	swift_params_set_string(params, "audio/sampling-rate", "8000");
	swift_params_set_string(params, "audio/output-format", "raw");
	swift_params_set_string(params, "tts/text-encoding", "utf-8");

	/* Additional swift parameters
	 *
	 * swift_params_set_float(params, "speech/pitch/shift", 1.0);
	 * swift_params_set_int(params, "speech/rate", 150);
	 * swift_params_set_int(params, "audio/volume", 110);
	 * swift_params_set_int(params, "audio/deadair", 0);
	 */

	if ((port = swift_port_open(engine, params)) == NULL) {
		ast_log(LOG_ERROR, "Failed to open Swift Port.\n");
		goto exception;
	}
	if ((voice = swift_port_set_voice_by_name(port, cfg_voice)) == NULL) {
		ast_log(LOG_ERROR, "Failed to set voice.\n");
		goto exception;
	}

	event_mask = SWIFT_EVENT_AUDIO | SWIFT_EVENT_END;
	swift_port_set_callback(port, &swift_cb, event_mask, ps);

	if (SWIFT_FAILED(swift_port_speak_text(port, text, 0, NULL, &tts_stream, NULL))) {
		ast_log(LOG_ERROR, "Failed to speak.\n");
		goto exception;
	}
	if (chan->_state != AST_STATE_UP) {
		ast_answer(chan);
	}

	ast_stopstream(chan);
	old_writeformat = chan->writeformat;

	if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) {
		ast_log(LOG_WARNING, "Unable to set write format.\n");
		goto exception;
	}

	res = 0;

	/* Wait 100ms first for synthesis to start crankin'; if that's not
	 * enough the
	 */

	next = ast_tvadd(ast_tvnow(), ast_tv(0, 100000));

	while (swift_generator_running(ps)) {
		ms = ast_tvdiff_ms(next, ast_tvnow());

		if (ms <= 0) {
			if (swift_bytes_available(ps) > 0) {
				ASTOBJ_WRLOCK(ps);
				len = fmin(framesize, ps->qc);
				availatend = cfg_buffer_size - (ps->pq_r - ps->q);

				if (len > availatend) {
					/* read #1: to end of q buf */
					memcpy(myf.frdata, ps->pq_r, availatend);
					ps->qc -= availatend;

					/* read #2: reset to start of q buf and get rest */
					ps->pq_r = ps->q;
					memcpy(myf.frdata + availatend, ps->pq_r, len - availatend);
					ps->qc -= len - availatend;
					ps->pq_r += len - availatend;
				} else {
					ast_log(LOG_DEBUG, "Easy read; %d bytes and %d at end, %d free\n", len, availatend, cfg_buffer_size - ps->qc);
					memcpy(myf.frdata, ps->pq_r, len);
					ps->qc -= len;
					ps->pq_r += len;
				}

				myf.f.frametype = AST_FRAME_VOICE;
				myf.f.subclass = AST_FORMAT_ULAW;
				myf.f.datalen = len;
				myf.f.samples = len;
				myf.f.data.ptr = myf.frdata;
				myf.f.mallocd = 0;
				myf.f.offset = AST_FRIENDLY_OFFSET;
				myf.f.src = __PRETTY_FUNCTION__;
				myf.f.delivery.tv_sec = 0;
				myf.f.delivery.tv_usec = 0;

				if (ast_write(chan, &myf.f) < 0) {
					ast_log(LOG_DEBUG, "ast_write failed\n");
				}

				ast_log(LOG_DEBUG, "wrote a frame of %d\n", len);

				if (ps->qc < 0) {
					ast_log(LOG_DEBUG, "queue claims to contain negative bytes. Huh? qc < 0\n");
				}

				ASTOBJ_UNLOCK(ps);
				next = ast_tvadd(next, ast_samp2tv(myf.f.samples, samplerate));
			} else {
				next = ast_tvadd(next, ast_samp2tv(framesize / 2, samplerate));
				ast_log(LOG_DEBUG, "Whoops, writer starved for audio\n");
			}
		} else {
			ms = ast_waitfor(chan, ms);

			if (ms < 0) {
				ast_log(LOG_DEBUG, "Hangup detected\n");
				res = -1;
				ASTOBJ_WRLOCK(ps);
				ps->immediate_exit = 1;
				ASTOBJ_UNLOCK(ps);
			} else if (ms) {
				f = ast_read(chan);

				if (!f) {
					ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
					res = -1;
					ASTOBJ_WRLOCK(ps);
					ps->immediate_exit = 1;
					ASTOBJ_UNLOCK(ps);
				} else if (f->frametype == AST_FRAME_DTMF && timeout > 0 && max_digits > 0) {
					char originDTMF = f->subclass;
					alreadyran = 1;
					res = 0;
					ASTOBJ_WRLOCK(ps);
					ps->immediate_exit = 1;
					ASTOBJ_UNLOCK(ps);

					if (max_digits > 1) {
						rc = listen_for_dtmf(chan, timeout, max_digits - 1);
					}
					if (rc) {
						sprintf(results, "%c%s", originDTMF, rc);
					} else {
						sprintf(results, "%c", originDTMF);
					}

					ast_log(LOG_NOTICE, "DTMF = %s\n", results);
					pbx_builtin_setvar_helper(chan, "SWIFT_DTMF", results);
				}
				ast_frfree(f);
			}
		}

		ASTOBJ_RDLOCK(ps);

		if (ps->immediate_exit && !ps->generating_done) {
			if (SWIFT_FAILED(sresult = swift_port_stop(port, tts_stream, SWIFT_EVENT_NOW))) {
				ast_log(LOG_NOTICE, "Early top of swift port failed\n");
			}
		}

		ASTOBJ_UNLOCK(ps);
	}
	if (alreadyran == 0 && timeout > 0 && max_digits > 0) {
		rc = listen_for_dtmf(chan, timeout, max_digits);

		if (rc != NULL) {
			sprintf(results, "%s", rc);
			ast_log(LOG_NOTICE, "DTMF = %s\n", results);
			pbx_builtin_setvar_helper(chan, "SWIFT_DTMF", results);
		}
	}
	if (max_digits >= 1 && results != NULL) {
		if (cfg_goto_exten) {
			ast_log(LOG_NOTICE, "GoTo(%s|%s|%d) : ", chan->context, results, 1);

			if (ast_exists_extension (chan, chan->context, results, 1, chan->cid.cid_num)) {
				ast_log(LOG_NOTICE, "OK\n");
				ast_copy_string(chan->exten, results, sizeof(chan->exten) - 1);
				chan->priority = 0;
			} else {
				ast_log(LOG_NOTICE, "FAILED\n");
			}
		}
	}

	exception:

	if (port != NULL) {
		swift_port_close(port);
	}
	if (engine != NULL) {
		swift_engine_close(engine);
	}
	if (ps && ps->q) {
		ast_free(ps->q);
		ps->q = NULL;
	}
	if (ps) {
		ast_free(ps);
		ps = NULL;
	}
	if (!res && old_writeformat) {
		ast_set_write_format(chan, old_writeformat);
	}

	ast_module_user_remove(u);
	return res;
}
int adsi_transmit_message_full(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype, int dowait)
{
	unsigned char *msgs[5] = { NULL, NULL, NULL, NULL, NULL };
	int msglens[5];
	int msgtypes[5];
	int newdatamode;
	int res;
	int x;
	int writeformat, readformat;
	int waitforswitch = 0;

	writeformat = chan->writeformat;
	readformat = chan->readformat;

	newdatamode = chan->adsicpe & ADSI_FLAG_DATAMODE;

	for (x=0;x<msglen;x+=(msg[x+1]+2)) {
		if (msg[x] == ADSI_SWITCH_TO_DATA) {
			ast_log(LOG_DEBUG, "Switch to data is sent!\n");
			waitforswitch++;
			newdatamode = ADSI_FLAG_DATAMODE;
		}
		
		if (msg[x] == ADSI_SWITCH_TO_VOICE) {
			ast_log(LOG_DEBUG, "Switch to voice is sent!\n");
			waitforswitch++;
			newdatamode = 0;
		}
	}
	msgs[0] = msg;

	msglens[0] = msglen;
	msgtypes[0] = msgtype;

	if (msglen > 253) {
		ast_log(LOG_WARNING, "Can't send ADSI message of %d bytes, too large\n", msglen);
		return -1;
	}

	ast_stopstream(chan);

	if (ast_set_write_format(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set write format to ULAW\n");
		return -1;
	}

	if (ast_set_read_format(chan, AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "Unable to set read format to ULAW\n");
		if (writeformat) {
			if (ast_set_write_format(chan, writeformat)) 
				ast_log(LOG_WARNING, "Unable to restore write format to %d\n", writeformat);
		}
		return -1;
	}
	res = __adsi_transmit_messages(chan, msgs, msglens, msgtypes);

	if (dowait) {
		ast_log(LOG_DEBUG, "Wait for switch is '%d'\n", waitforswitch);
		while(waitforswitch-- && ((res = ast_waitfordigit(chan, 1000)) > 0)) { res = 0; ast_log(LOG_DEBUG, "Waiting for 'B'...\n"); }
	}
	
	if (!res)
		chan->adsicpe = (chan->adsicpe & ~ADSI_FLAG_DATAMODE) | newdatamode;

	if (writeformat)
		ast_set_write_format(chan, writeformat);
	if (readformat)
		ast_set_read_format(chan, readformat);

	if (!res)
		res = ast_safe_sleep(chan, 100 );
	return res;
}
Beispiel #28
0
static int mp3_exec(struct ast_channel *chan, const char *data)
{
	int res=0;
	int fds[2];
	int ms = -1;
	int pid = -1;
	RAII_VAR(struct ast_format *, owriteformat, NULL, ao2_cleanup);
	int timeout = 2000;
	struct timeval next;
	struct ast_frame *f;
	struct myframe {
		struct ast_frame f;
		char offset[AST_FRIENDLY_OFFSET];
		short frdata[160];
	} myf = {
		.f = { 0, },
	};
	struct ast_format * native_format;
	unsigned int sampling_rate;
	struct ast_format * write_format;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
		return -1;
	}

	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		return -1;
	}
	
	ast_stopstream(chan);

	native_format = ast_format_cap_get_format(ast_channel_nativeformats(chan), 0);
	sampling_rate = ast_format_get_sample_rate(native_format);
	write_format = ast_format_cache_get_slin_by_rate(sampling_rate);

	owriteformat = ao2_bump(ast_channel_writeformat(chan));
	res = ast_set_write_format(chan, write_format);
	if (res < 0) {
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		return -1;
	}

	myf.f.frametype = AST_FRAME_VOICE;
	myf.f.subclass.format = write_format;
	myf.f.mallocd = 0;
	myf.f.offset = AST_FRIENDLY_OFFSET;
	myf.f.src = __PRETTY_FUNCTION__;
	myf.f.delivery.tv_sec = 0;
	myf.f.delivery.tv_usec = 0;
	myf.f.data.ptr = myf.frdata;
	
	res = mp3play(data, sampling_rate, fds[1]);
	if (!strncasecmp(data, "http://", 7)) {
		timeout = 10000;
	}
	/* Wait 1000 ms first */
	next = ast_tvnow();
	next.tv_sec += 1;
	if (res >= 0) {
		pid = res;
		/* Order is important -- there's almost always going to be mp3...  we want to prioritize the
		   user */
		for (;;) {
			ms = ast_tvdiff_ms(next, ast_tvnow());
			if (ms <= 0) {
				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
				if (res > 0) {
					myf.f.datalen = res;
					myf.f.samples = res / 2;
					if (ast_write(chan, &myf.f) < 0) {
						res = -1;
						break;
					}
				} else {
					ast_debug(1, "No more mp3\n");
					res = 0;
					break;
				}
				next = ast_tvadd(next, ast_samp2tv(myf.f.samples, sampling_rate));
			} else {
				ms = ast_waitfor(chan, ms);
				if (ms < 0) {
					ast_debug(1, "Hangup detected\n");
					res = -1;
					break;
				}
				if (ms) {
					f = ast_read(chan);
					if (!f) {
						ast_debug(1, "Null frame == hangup() detected\n");
						res = -1;
						break;
					}
					if (f->frametype == AST_FRAME_DTMF) {
						ast_debug(1, "User pressed a key\n");
						ast_frfree(f);
						res = 0;
						break;
					}
					ast_frfree(f);
				} 
			}
		}
	}
	close(fds[0]);
	close(fds[1]);
	
	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && owriteformat)
		ast_set_write_format(chan, owriteformat);

	ast_frfree(&myf.f);
	
	return res;
}
static int record_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	int count = 0;
	int percentflag = 0;
	char *filename, *ext = NULL, *silstr, *maxstr, *options;
	char *vdata, *p;
	int i = 0;
	char tmp[256];

	struct ast_filestream *s = '\0';
	struct localuser *u;
	struct ast_frame *f = NULL;
	
	struct ast_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;
	int waitres;
	struct ast_silence_generator *silgen = NULL;
	
	/* The next few lines of code parse out the filename and header from the input string */
	if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
		ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	/* Yay for strsep being easy */
	vdata = ast_strdupa(data);
	if (!vdata) {
		ast_log(LOG_ERROR, "Out of memory\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	p = vdata;
	filename = strsep(&p, "|");
	silstr = strsep(&p, "|");
	maxstr = strsep(&p, "|");	
	options = strsep(&p, "|");
	
	if (filename) {
		if (strstr(filename, "%d"))
			percentflag = 1;
		ext = strrchr(filename, '.'); /* to support filename with a . in the filename, not format */
		if (!ext)
			ext = strchr(filename, ':');
		if (ext) {
			*ext = '\0';
			ext++;
		}
	}
	if (!ext) {
		ast_log(LOG_WARNING, "No extension specified to filename!\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	if (silstr) {
		if ((sscanf(silstr, "%d", &i) == 1) && (i > -1)) {
			silence = i * 1000;
		} else if (!ast_strlen_zero(silstr)) {
			ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", silstr);
		}
	}
	
	if (maxstr) {
		if ((sscanf(maxstr, "%d", &i) == 1) && (i > -1))
			/* Convert duration to milliseconds */
			maxduration = i * 1000;
		else if (!ast_strlen_zero(maxstr))
			ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", maxstr);
	}
	if (options) {
		/* Retain backwards compatibility with old style options */
		if (!strcasecmp(options, "skip"))
			option_skip = 1;
		else if (!strcasecmp(options, "noanswer"))
			option_noanswer = 1;
		else {
			if (strchr(options, 's'))
				option_skip = 1;
			if (strchr(options, 'n'))
				option_noanswer = 1;
			if (strchr(options, 'a'))
				option_append = 1;
			if (strchr(options, 't'))
				terminator = '*';
			if (strchr(options, '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) {
		do {
			snprintf(tmp, sizeof(tmp), filename, count);
			count++;
		} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
		pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
	} else
		strncpy(tmp, filename, sizeof(tmp)-1);
	/* end of routine mentioned */
	
	
	
	if (chan->_state != AST_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 = ast_answer(chan);
		}
	}
	
	if (res) {
		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
		goto out;
	}
	
	if (!option_quiet) {
		/* Some code to play a nice little beep to signify the start of the record operation */
		res = ast_streamfile(chan, "beep", chan->language);
		if (!res) {
			res = ast_waitstream(chan, "");
		} else {
			ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", chan->name);
		}
		ast_stopstream(chan);
	}
		
	/* The end of beep code.  Now the recording starts */
		
	if (silence > 0) {
		rfmt = chan->readformat;
		res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
		if (res < 0) {
			ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
			LOCAL_USER_REMOVE(u);
			return -1;
		}
		sildet = ast_dsp_new();
		if (!sildet) {
			ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
			LOCAL_USER_REMOVE(u);
			return -1;
		}
		ast_dsp_set_threshold(sildet, 256);
	} 
		
		
	flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
	s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
		
	if (!s) {
		ast_log(LOG_WARNING, "Could not create file %s\n", filename);
		goto out;
	}

	if (option_transmit_silence_during_record)
		silgen = ast_channel_start_silence_generator(chan);
	
	/* Request a video update */
	ast_indicate(chan, AST_CONTROL_VIDUPDATE);
	
	if (maxduration <= 0)
		maxduration = -1;
	
	while ((waitres = ast_waitfor(chan, maxduration)) > -1) {
		if (maxduration > 0) {
			if (waitres == 0) {
				gottimeout = 1;
				break;
			}
			maxduration = waitres;
		}
		
		f = ast_read(chan);
		if (!f) {
			res = -1;
			break;
		}
		if (f->frametype == AST_FRAME_VOICE) {
			res = ast_writestream(s, f);
			
			if (res) {
				ast_log(LOG_WARNING, "Problem writing frame\n");
				ast_frfree(f);
				break;
			}
			
			if (silence > 0) {
				dspsilence = 0;
				ast_dsp_silence(sildet, f, &dspsilence);
				if (dspsilence) {
					totalsilence = dspsilence;
				} else {
					totalsilence = 0;
				}
				if (totalsilence > silence) {
					/* Ended happily with silence */
					ast_frfree(f);
					gotsilence = 1;
					break;
				}
			}
		} else if (f->frametype == AST_FRAME_VIDEO) {
			res = ast_writestream(s, f);
			
			if (res) {
				ast_log(LOG_WARNING, "Problem writing frame\n");
				ast_frfree(f);
				break;
			}
		} else if ((f->frametype == AST_FRAME_DTMF) &&
		    (f->subclass == terminator)) {
			ast_frfree(f);
			break;
		}
		ast_frfree(f);
	}
	if (!f) {
		ast_log(LOG_DEBUG, "Got hangup\n");
		res = -1;
	}
			
	if (gotsilence) {
		ast_stream_rewind(s, silence-1000);
		ast_truncstream(s);
	} else if (!gottimeout) {
		/* Strip off the last 1/4 second of it */
		ast_stream_rewind(s, 250);
		ast_truncstream(s);
	}
	ast_closestream(s);

	if (silgen)
		ast_channel_stop_silence_generator(chan, silgen);
	
 out:
	if ((silence > 0) && rfmt) {
		res = ast_set_read_format(chan, rfmt);
		if (res)
			ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
		if (sildet)
			ast_dsp_free(sildet);
	}

	LOCAL_USER_REMOVE(u);

	return res;
}